Scapy - cant send vlan tagged packet - scapy

I can sent a basic packet using scapy and inspect it on the receiving PC using wireshark.
When I add a VLAN tag I cannot receive the packet or capture it in wireshark on the origination side
sendp( Ether()/IP(dst="172.16.64.49")/Raw(load="some data"))
sendp( Ether()/Dot1Q(vlan=42)/IP(dst="172.16.64.49")/Raw(load="some data"))
[Ethernet]
dst= 00:15:17:e4:55:52
src= b0:83:fe:e2:df:b7
type= n_802_1Q
[802.1Q}
prio= 0
id= 0
vlan= 42
type= IPv4
[IP]
version= 4
ihl= 5
tos= 0x0
len= 29
id= 1
flags=
frag= 0
ttl= 64
proto= ip
chksum= 0x7c32
src= 172.16.102.92
dst= 172.16.64.49
\options\
[Raw]
load= 'some data'
The data looks as i would expect in scapy, any thoughts?

It looks like two things happened, the Switches in my network discarded the outer VLAN, this i discovered when i sent a packet with double VLAN encapsulation. only one VLAN label showed up at the receiving side.
The second issue with the local Wireshark not showing the packet sent was a wireshark filter mis-configuration

Related

Trying to use raw socket in Python 3 to blindly send an IP package, But keep getting ARP lookups how to disable

I am trying to send an IP package in Python 3 on a point to point network IE Host and Client are connected directly to each other with static IP.
I'm using the following code:
import socket
class Client:
def __init__(self):
self._sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
self._sock.bind(('192.168.1.10',0))
def send(self, data):
data_to_send = bytes([0x0,0x1C,0x23,0x17,0x4A,0xCB,0x00,0x50,0xB6,0x0D,0x35,0x9F,0x08,0x00,0x45,0x00,0x00,0x2E,0x00,0x00,0x40,0x00,0x40,0x00,0xB7,0x6A,0xC0,0xA8,0x01,0x0A,0xC0,0xA8,0x01,0x0B,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00])
self._sock.sendto(data_to_send, ('192.168.1.11', 0))
However every time I try and send the package I always get ARP lookups (and the package never gets transmittet).
1 0.000000 GoodWayI_0d:35:9f Broadcast ARP 42 Who has 192.168.1.11? Tell 192.168.1.10
2 0.981801 GoodWayI_0d:35:9f Broadcast ARP 42 Who has 192.168.1.11? Tell 192.168.1.10
3 1.981830 GoodWayI_0d:35:9f Broadcast ARP 42 Who has 192.168.1.11? Tell 192.168.1.10
How do I avoid these lookups and just send the package blindly ?
It seems my search fu is broken because I cant find much documentation on Python 3 Sockets.
Regards
I did get around this issue by adding the IP/MAC to the ARP list
using
netsh interface ip add neighbors "Ethernet 3" "192.168.1.11" "00-1C-23-17-4A-CB"
However I would like to be able to switch it off in python
regards

SSDP M-search does not work for unicast - single IP

SSDP M-search request for discovery works great for multicast address 239.255.255.250. However, I have a requirement to send this request to a specific IP. It does not work. As per the UPnP architecture document unicast discover message is supported, with a small difference from the multicast message
The multi-cast message is
M-SEARCH * HTTP/1.1
HOST:239.255.255.250:1900
MAN:ssdp:discover
ST:ssdp:all
MX:1
Unicast message is similar - except that the multicast IP is changed to specific IP and MX:1 is removed (as per the specification - did not find any code sample for unicast discover m-search)
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
msg = 'M-SEARCH * HTTP/1.1\r\nHOST:239.255.255.250:1900\r\nMAN:\"ssdp:discover\"\r\nST:ssdp:all\r\nMX:1\r\n\r\n'
s.sendto(msg.encode('utf-8'), ('239.255.255.250', 1900))
resp = s.recv(1024)
print (resp)
This works great. But the following doesn't - the recv() call times out
sock_1 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
msg = 'M-SEARCH * HTTP/1.1\r\nHOST:<specific ip>:1900\r\nMAN:\"ssdp:discover\"\r\nST:ssdp:all\r\n\r\n'
sock_1.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 32)
sock_1.settimeout(30)
sock_1.sendto(msg.encode('utf-8'), ('<specific ip>', 1900))
resp = sock_1.recv(1024)
I have tried a few more variations of 'setsockopt' which did not work.
Please share if there are any clues for possible reasons - could it be from the device side that it responds to the multicast on 1900 but not to the unicast message?
Thanks in advance!
msg = 'M-SEARCH * HTTP/1.1\r\nHOST:<specific ip>:1900\r\nMAN:\"ssdp:discover\"\r\nST:ssdp:all\r\n'
You're missing a final \r\n in the end (it's for the empty line signaling end of headers: without it the receiver will just keep waiting for more).
The only difference with a unicast m-search is the HOST, like you've got.
Are you binding the socket? It should be bound to port 0. Here's an example of setting up a socket for ssdp: https://github.com/lbryio/aioupnp/blob/master/aioupnp/protocols/multicast.py#L64
In addition to the final \r\n pointed out by Jussi, you may find you need to try different permutations of the M-SEARCH format, some gateways are very finicky. For some the value for MAN must be in quotes, for others it must not. Additional quirks are the order of MAN, MX, ST and the capitalization of HOST/Host and MAN/Man . You may also need to try a variety of search targets.

UDP Broadcast sendto failed:"network is unreachable" on linux 2.6.30

I write a program using udp broadcast.Code segment as follows:
struct sockaddr_in broadcast_addr;
socklen_t sock_len=sizeof(broadcast_addr);
bzero(&broadcast_addr,sock_len);
broadcast_addr.sin_family=AF_INET;
broadcast_addr.sin_port=12345;
broadcast_addr.sin_addr.s_addr=inet_addr("255.255.255.255");
int fd=socket(AF_INET,SOCK_DGRAM,0);
int broadcast_enable=1;
setsockopt(fd,SOL_SOCKET,SO_BROADCAST,&broadcast_enable,sizeof(broadcast_enable));
uint8_t send_buf[100];
int ret=sendto(fd,send_buf,sizeof(send_buf),0,
(struct sockaddr*)&broadcast_addr,sock_len);
if(ret==-1)
perror("sendto failed");
output:
sendto failed: Network is unreachable
But when I run "add default gateway" command like " route add default gw 10.10.10.111 ",the error disappears.When setting a new ipaddress to netdev,command as above should be ran,otherwise the error comes. Why? Thanks.
Not sure why 255.255.255.255 isn't working for you. However, I've never used that as a broadcast IP myself. When I send a broadcast packet I usually derive the broadcast IP from my subnet mask, i.e. if your subnet mask is 255.255.255.0 (/24) and say your IP is 192.168.0.5, then to send a UDP broadcast your destination IP should be 192.168.0.255.

wireless sniffing using pcap, MAC address filter

I am writing a wireless packet sniffer program in C. I have set my wireless interface in monitor mode using airmon-ng, and now i am sniffing on the interface "mon0". I am using linux(ubuntu 10.10).
I want to set MAC address as the filter for the packets.
I have done it as shown below, but it says
"mon0 no IPV4 address assigned"
pcap_lookupnet(dev,&net,&mask,errbuf);
printf("%s\n",errbuf);
/* Open the session in promiscuous mode */
handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
if (handle == NULL) {
printf("Couldn't open device %s: %s\n", dev, errbuf);
return 2;
}
if(pcap_compile(handle,&fp,argv[0],0,net)==-1){
fprintf(stderr,"Error calling pcap_compile\n");exit(1);}
if(pcap_setfilter(handle,&fp) == -1){
fprintf(stderr,"Error setting filter\n");exit(1);}
/* The call pcap_loop() and pass our callback function */
pcap_loop(handle, 10, my_callback, NULL);
Please help me, how i can set the filter for MAC address??
"no IPV4 address assigned" is an error from pcap_lookupnet(). All it means is that the network interface on which you're trying to capture does not have an IPv4 address assigned to it. What airmon-ng did was to create a "monitor" interface for the Wi-Fi adapter; the regular network interface for the adapter might have an IP address assigned to it, but the monitor interface won't have one.
The only place where the IP address matters is for ip broadcast filter expressions; if you're not filtering for IPv4 broadcast addresses, which you probably won't be, there's no need to get the IPv4 address. To quote the pcap_compile() man page:
If the netmask of the network on which packets are being captured isn't known to the program, or if packets are being captured on the Linux "any" pseudo-interface that can capture on more than one network, a value of 0 can be supplied; tests for IPv4 broadcast addreses won't be done correctly, but all other tests in the filter program will be OK.
so just pass 0 as the "net" argument to pcap_compile().
If you want to search for packets being sent to a particular MAC address, you can just use wlan dst XX:XX:XX:XX:XX:XX; if you want to search for packets being sent from a particular MAC address, you can just use wlan src XX:XX:XX:XX:XX:XX; if you want to search for packets being sent to or from a particular MAC address, you can just use wlan host XX:XX:XX:XX:XX:XX. If you care about the access point address, rather than the station address, you'll need to use filters such as wlan ra XX:XX:XX:XX:XX:XX or wlan ta XX:XX:XX:XX:XX:XX, at least with newer versions of libpcap. (See the pcap-filter man page or, if you don't have a pcap-filter man page, the tcpdump man page for details.)

linux raw ethernet socket bind to specific protocol

I'm writing code to send raw Ethernet frames between two Linux boxes. To test this I just want to get a simple client-send and server-receive.
I have the client correctly making packets (I can see them using a packet sniffer).
On the server side I initialize the socket like so:
fd = socket(PF_PACKET, SOCK_RAW, htons(MY_ETH_PROTOCOL));
where MY_ETH_PROTOCOL is a 2 byte constant I use as an ethertype so I don't hear extraneous network traffic.
when I bind this socket to my interface I must pass it a protocol again in the socket_addr struct:
socket_address.sll_protocol = htons(MY_ETH_PROTOCOL);
If I compile and run the code like this then it fails. My server does not see the packet. However if I change the code like so:
socket_address.sll_protocol = htons(ETH_P_ALL);
The server then can see the packet sent from the client (as well as many other packets) so I have to do some checking of the packet to see that it matches MY_ETH_PROTOCOL.
But I don't want my server to hear traffic that isn't being sent on the specified protocol so this isn't a solution. How do I do this?
I have resolved the issue.
According to http://linuxreviews.org/dictionary/Ethernet/ referring to the 2 byte field following the MAC addresses:
"values of that field between 64 and 1522 indicated the use of the new 802.3 Ethernet format with a length field, while values of 1536 decimal (0600 hexadecimal) and greater indicated the use of the original DIX or Ethernet II frame format with an EtherType sub-protocol identifier."
so I have to make sure my ethertype is >= 0x0600.
According to http://standards.ieee.org/regauth/ethertype/eth.txt use of 0x88b5 and 0x88b6 is "available for public use for prototype and vendor-specific protocol development." So this is what I am going to use as an ethertype. I shouldn't need any further filtering as the kernel should make sure to only pick up ethernet frames with the right destination MAC address and using that protocol.
I've worked around this problem in the past by using a packet filter.
Hand Waving (untested pseudocode)
struct bpf_insn my_filter[] = {
...
}
s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol));
struct sock_fprog pf;
pf.filter = my_filter;
pf.len = my_filter_len;
setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf));
sll.sll_family = PF_PACKET;
sll.sll_protocol = htons(protocol);
sll.sll_ifindex = if_nametoindex("eth0");
bind(s, &sll, sizeof(sll));
Error checking and getting the packet filter right is left as an exercise for the reader...
Depending on your application, an alternative that may be easier to get working is libpcap.

Resources