How can I capture Gre or Vxlan inner network traffic? - wireshark

I want to capture some network traffic with the filter like "src x.x.x.x and dst x.x.x.x".
Ususally it works, but it doesn't work when the network traffic is encapsulated by protocls like Gre or Vxlan.
For example, the Gre encapsulate a message like this:
Ethernet II, Src: VMware_91:f6:ad (00:0c:29:91:f6:ad), Dst: VMware_dc:c7:71 (00:0c:29:dc:c7:71)
Internet Protocol Version 4, Src: 10.75.2.161, Dst: 10.75.2.140
Generic Routing Encapsulation (Transparent Ethernet bridging)
Ethernet II, Src: Micro-St_e3:51:57 (4c:cc:6a:e3:51:57), Dst: VMware_91:f6:ad (00:0c:29:91:f6:ad)
Internet Protocol Version 4, Src: 10.75.2.11, Dst: 10.75.2.160
So what should I do to capture those inner traffic?
I use "src 10.75.2.160" to capture but it tcpdump captured nothing.
tcpdump -i eth0 "src 10.75.2.11"
It doesn't work.
I use "ip[54:4]" to capture, it works, but my leader tell me it's not accurate.
So what else can I try?

I don't know how accurate your leader wants the filter, but if we can make a few assumptions about the outer IP and GRE headers, then the filter isn't too complicated. So here are the 2 assumptions:
The outer IP header is a standard 20 bytes. If this isn't the case or can't be relied upon, then everywhere I use 20 in the filter will need to be replaced with the IP header length calculation, which is (ip[0] & 0x0f) * 4.
The GRE header is a standard size of 4 bytes. If options are present and you can guarantee that all GRE headers are exactly the same size, then you can substitute 4 for the actual GRE header length, but if GRE options could vary, then it should still be possible to specify a capture filter that works with any size GRE header, but it will be much more complicated and hard to follow. I leave that as an exercise for the reader.
With those assumptions out of the way, here's a filter that would be the equivalent of "src 10.75.2.11" but for the inner source IP address of a IP/GRE/IP packet:
(ip proto 47) && (ip[20 + 2:2] = 0x0800) && (ip[20 + 4 + 12:4] = 0x0a4b0x0b)
Explanation:
ip proto 47: This captures only IP/GRE packets as GRE is assigned protocol number 47.
ip[20 + 2:2] = 0x0800: Since 0x0800 is the assigned Ethertype for IPv4, this captures only GRE packets where the Protocol Type field is IP, so only IP/GRE/IP packets. (NOTE: RFC 1701 states, "The Protocol Type field contains the protocol type of the payload packet. In general, the value will be the Ethernet protocol type field for the packet.")
ip[20 + 4 + 12:4] = 0x0a4b020b: This captures only the IP/GRE/IP packets where the source IP address field of the inner IP header is 10.75.2.11. (NOTE: To get 0x0a4b020b from 10.75.2.11, you just need to convert each decimal octet to hexadecimal and combine them into a single 4 byte value.)
To verify the resulting BPF code, you can run tcpdump with the -d option to check that the filter meets your expectations, for example:
tcpdump -i eth0 "(ip proto 47) && (ip[20 + 2:2] = 0x0800) && (ip[20 + 4 + 12:4] = 0x0a4b020b)"
You should see output of the following form:
(000) ldh [12]
(001) jeq #0x800 jt 2 jf 9
(002) ldb [23]
(003) jeq #0x2f jt 4 jf 9
(004) ldh [36]
(005) jeq #0x800 jt 6 jf 9
(006) ld [50]
(007) jeq #0xa4b020b jt 8 jf 9
(008) ret #262144
(009) ret #0
If you're not familiar with BPF code, then I would suggest further reading elsewhere, as providing a BPF tutorial here is beyond the scope of this answer.
Finally, if you need to filter for the source IP address whether it's in the outer IP header or the inner IP header, then you can basically just combine the 2 filters, i.e.:
"(ip src 10.75.2.11) || ((ip proto 47) && (ip[20 + 2:2] = 0x0800) && (ip[20 + 4 + 12:4] = 0x0a4b020b))"

Related

Capturing all traffic in Wireshark from a specific MAC OUI?

I would like to capture all wifi traffic from a specific device manufacturer using Wireshark/Tshark/TCPDump/etc. I want to use a CAPTURE filter, not a display filter. Basically, I want to capture all packets from the MAC address 11:22:33:xx:xx:xx and nothing else. Or, put another way, the first 3 octets or OUI of the MAC address using Berkeley Packet Filtering Syntax. Anyone have a preferred method?
Per this post, use syntax like ether[A:B] in your capture filter where
A = start byte location in ethernet frame, starting at 0
B = number of bytes, must be 1, 2, or 4
So to match 3 bytes, you have to have 2 comparisons: Match 2 bytes and 1 byte separately.
If you only want about packets coming from this OUI (per question):
tcpdump 'ether[0:2] == 0x1122 && ether[2:1] == 0x33'
If you want all packets going to/from this OUI:
tcpdump 'ether[0:2] == 0x1122 && ether[2:1] == 0x33 \
|| ether[6:2] == 0x1122 && ether[8:1] == 0x33'
The first 12 bytes (0-11) of the ethernet header consist of the destination and then source mac addresses. So to select both sets of 3 bytes 0-2 and 6-8, select 2 bytes at 0, 1 byte at 2, 2 bytes at 6 and 1 byte at 8.
You should also be able to use this with tshark as long as you preface this with the -f capture filter flag.

What port byte order is used in URL?

When you want to bind to port in C you have to use htons(port) to convert the port from host byte order to network byte order. This happens because the port number is copied directly to the TCP packets, so they have to match on little-endian and big-endian machines.
Consider the following example in C:
int port = 5000;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
Notice the use of htons. Now, if you run netstat -anp --tcp (on Linux) you'll see that 0.0.0.0:5000 is being listened. It looks like the port number uses host endianness.
Now, a question arises: if port number is host-endian in URL, does this mean that a big-endian client can't use http://a.b.c.d:5000 URL to connect to a little-endian server listening on 0.0.0.0:5000?
No, you're almost certainly misapplying the rules at the wrong abstraction level.
The local browser, in all likelihood, will grab the :5000 string off the end of the URL and use that to create the integer 5000 in host format. It will then pass that to htons as part of constructing the session, in exactly the same way your code snippet does.
And, voila, the structures contain the correct network order.

Problem using mosquitto broker with netcat

I trying to use mosquitto broker for an IoT application. I have a embedded hardware, actually not much documented/exampled on the internet. I've succesfully implemented an TCP client on this hardware, and now i can send/listen messages throught any port i want via TCP and i listen via netcat. But when i tried to connect mosquitto, it doesn't accept the literal language. I digged on the internet. The broker take messages like shown below, but even this one not working.
I can not found any documentation. I even tried to watch Wireshark packages, and i can not find any pattern. Any help will appreciated.
$ echo -en "\x10\x0d\x00\x04MQTT\x04\x00\x00\x00\x00\x01a" |nc localhost 1883|hd
00000000 20 02 01 00 | ...|
00000004
Had a similar usecase like you and this is how I managed to decode this message and create my own connect request.
echo -en "\x10\x0d\x00\x04MQTT\x04\x00\x00\x00\x00\x01a" |nc localhost 1883
The above message is broken down as follows:
nc localhost 1883, opens a tcp socket to the mqtt port 1883 (to the broker (on localhost) listening to port 1883)
\x10\x0d\x00\x04MQTT\x04\x00\x00\x00\x00\x01a is the connect packet sent to the socket that was opened. This connect packet can be broken down as follows:
\x10: MQTT connect packet (Constitutes the control field with the 1st 4 bits representing the command type "0001" and the 2nd 4 bits the control flag.
\x0d: Remaining length: is the total length of both the variable header and the payload. This needs to be set after the whole payload is complete.
*Variable header = Protocol Name + Protocol level + Connect Flag byte + Keep Alive
Payload = ClientId, username, password, e.t.c, each entry is provided in the format lengthOfEntry + Entry e.g for a clientId and username and password, this gives: lengthOfClientId + ClientId + lengthOfUsername + Username + lengthOfPassword + Password. *Note: the length is always provided as two bytes.
\x00\x04MQTT: Represents the protocol name "MQTT". The first two bytes 0x00 and 0x04 are the protocol length and MQTT is then the protocol. These give a total of 6 bytes.
\x04: is the protocol level. From MQTT specification, the value of the Protocol Level field for the version 3.1.1 of the protocol is 4 (0x04)
\0x00: is the connect flag byte. each byte is represented as follows:
UsernameFlag|PasswordFlag|Will Retain|Will|QoS|Will Flag|CleanSession|Reserved. 0x00 means none of the flags are set and persistent sessions will be used. Hence the payload doesn't require a username or password as will be seen in the payload bytes.
\0x00\0x00: two bytes that represent the keepAlive time. In this case 0 is provided which means that the server is not required to disconnect the client on grounds of inactivity. keepalive mechanism is turned off
The next bytes are already the payload. Since the connect flag was set such that no username or password is required, then we only have to provide the client id. In the above example the clientid is "a". This is of length 1 byte.
\0x00\0x01: represents the length of the clientId. since we have the character "a" as the clientId we have just the length 1. The length is always given in 16bit (2 bytes).
a: the clientId.
If we count all the bytes, we come up to a total of 13 bytes which gives us our remaining le0gnth as 0x0d.
If you need to add a username and password, set the connect flag accordingly 0b11000000 = 0xC0. The username and password are added to the payload right after the clientId in the order lengthofClientId, clientId, lengthOfUSername, Username, LengthofPassword, Password. The reminaining length needs to be adjusted to reflect this.
Tip: The variable header has a fixed number of bytes of 10. The payload length always depends on the data provided. the length of each element is always 2 bytes. so for the above case, we have a clientid of 1 byte and the length which take 2 bytes to give a total of 10 + 2 + 1 = 13.
I hope this helps you out and answers your question.
Useful links:
https://openlabpro.com/guide/mqtt-packet-format/
http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718024

How does only numbers in URL resolve to a domain?

I've been seeing some examples such as http://38263628 that resolves to a legitimate website https://example.com
When doing dig or nslookup on 38263628, it returns me NXDOMAIN.
How does the redirection or resolution work?
For data protection reasons, I can't give the actual numbers and domain it resolves to.
Thanks!
We usually write IP addresses as four dot-separated numbers like 12.34.56.78 but the address is just a number and it can be written in other ways. For example, 12.34.56.78 can also be written as 12.34.14414 or 12.2242638 or 203569230 or 0xc22384e or 0xc.0x22.0x38.0x4e.
The four-dot-separated form is effectively a base-256 representation of the number, so to convert from a single large number N into the four-dot-separated form A.B.C.D you would calculate these four values:
A = N / 256 / 256 / 256
B = N / 256 / 256 % 256
C = N / 256 % 256
D = N % 256
So your 38263628 is equivalent to 2.71.219.76
dig and nslookup don't work with plain numbers because they treat their arguments as strings, even when the arguments are known to represent IP addresses. (For instance, man dig says that the -x option requires an address in the four-dot form. That's because dig just wants to treat it as a string that can be split on the dots and rearranged into a in-addr.arpa query.)
However, most commands that convert their arguments into actual IP address numbers will accept any of the number formats. Try it with ping (which will helpfully show the address in four-dot format when it shows its results):
$ ping 203569230
PING 203569230 (12.34.56.78): 56 data bytes
...
That also gives you an easy way to convert any number into four-dot form -- just give the number as an argument to ping and let it do the conversion for you.

How does one calculate ones link-local ipv6 address?

So there are several sites that will calculate your link-local ipv6 address for you, like this one right here.
Nevertheless, it does not give any useful into as to how this address is calculated nor what the input parameters are. So what is the procedure(or algorithm)to compute a link local ipv6 address if one knows ones ipv4 address, subnet mask, and gateway address? I'm doing a project with SCTP sockets that uses ISATAP network tunneling and the LL ipv6 address is used in constructing the ISATAP address.
Appendix A of RFC 4291 describes the method for computing a modified EUI-64 from a MAC address. Once you have the modified EUI-64, you just put it in the lower 64 bits of the address and put fe80:: in the top 64 bits.
Basically you flip the 7th bit of the MAC address, and pack its first 24 bits (including the flipped bit), then fffe, then the lower 24 bits of the MAC address, resulting in 64 bits total.
That being said, your question is how to derive the link local address from the IPv4 address and subnet mask. That, you can't do. The IPv4 address and subnet mask (if indeed there is one – IPv6 does not require that IPv4 be running at all on the same interface) has nothing to do with the IPv6 address and the two aren't related in any way. The IPv4 gateway address (again, if there is one) is even less relevant.
The link-local address can be based on the MAC address per RFC 4862 or randomly generated as per RFC 4941.
Normally this should be limited to global scope, but some systems extend this privacy extension implementation to link-local scope. Follow this question on serverfault for discussion of the topic.
The previous answers failed to note that there is a defined procedure for generating a link local IPv6 address from an IPv4 address when using ISATAP, and there is a different process for generating a link local IPv6 address from a MAC address. The two things are unrelated.
For ISATAP, the 32-bit IPv4 address is prepended wit the 96 bits of either fe80::200:5efe or fe80::200:5efe to get the 128-bit IPv6 link-local address.
For MAC to IPv6, the 48-bit MAC address is split in half, 16 bits are inserted in the middle, those bits being ff:fe, then it is prepended by the 64-bit link-local prefix fe80::, and finally the 7th bit in the 5th IPv6 segment is flipped, to get the 128-bit IPv6 link-local address.
The following code provides examples showing how to use the The IPAddress library to do the conversions in either Java or Go. Disclaimer: I am the project manager of those libraries.
These examples also help to visualize the conversions described above.
Go:
func convertToIsatap(ipv4Str string, isGlobal bool) string {
ipv4Address := ipaddr.NewIPAddressString(ipv4Str).GetAddress().ToIPv4()
zero := &ipaddr.IPv6AddressSegment{}
segments := make([]*ipaddr.IPv6AddressSegment, ipaddr.IPv6SegmentCount)
segments[1], segments[2], segments[3], segments[4] = zero, zero, zero, zero
segments[0] = ipaddr.NewIPv6Segment(0xfe80)
segments[5] = ipaddr.NewIPv6Segment(0x5efe)
if isGlobal {
segments[4] = ipaddr.NewIPv6Segment(0x200)
}
ipv6Address, _ := ipv4Address.GetIPv6Address(ipaddr.NewIPv6Section(segments))
return ipv6Address.String()
}
func convertToLinkLocalIPv6(macAddr string) string {
macAddress := ipaddr.NewMACAddressString(macAddr).GetAddress()
ipv6LinkLocal, _ := macAddress.ToLinkLocalIPv6()
return ipv6LinkLocal.String()
}
fmt.Println("1.2.3.4 becomes ISATAP " +
convertToIsatap("1.2.3.4", true))
fmt.Println("aa:bb:cc:11:22:33 becomes " +
convertToLinkLocalIPv6("aa:bb:cc:11:22:33"))
Java:
static String convertToIsatap(String ipv4Str, boolean isGlobal) {
IPv4Address ipv4Address = new IPAddressString(ipv4Str).getAddress().toIPv4();
IPv6AddressSegment zeroSeg = new IPv6AddressSegment(0);
IPv6AddressSegment segments[] =
new IPv6AddressSegment[IPv6Address.SEGMENT_COUNT - 2];
segments[1] = segments[2] = segments[3] = segments[4] = zeroSeg;
segments[0] = new IPv6AddressSegment(0xfe80);
segments[5] = new IPv6AddressSegment(0x5efe);
if(isGlobal) {
segments[4] = new IPv6AddressSegment(0x200);
}
return ipv4Address.getIPv6Address(
new IPv6AddressSection(segments)).toString();
}
static String convertToLinkLocalIPv6(String macStr) {
MACAddress macAddress = new MACAddressString(macStr).getAddress();
return macAddress.toLinkLocalIPv6().toString();
}
System.out.println("1.2.3.4 becomes ISATAP " +
convertToIsatap("1.2.3.4", true));
System.out.println("aa:bb:cc:11:22:33 becomes " +
convertToLinkLocalIPv6("aa:bb:cc:11:22:33"));
The output is the same for both examples:
1.2.3.4 becomes ISATAP fe80::200:5efe:102:304
aa:bb:cc:11:22:33 becomes fe80::a8bb:ccff:fe11:2233

Resources