tun device: message is not received by server process - sockets

I set up two tun devices. The data that is written to each tun device is forwarded over a UDP socket to the other tun device using a simple loop:
// the tuntap device is created using these flags
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
[...]
fd_set fd_list;
FD_ZERO(&fd_list);
FD_SET(fd1, &fd_list); // fd1 is the tun device
FD_SET(fd2, &fd_list); // fd2 is the udp socket
int fds[] = {fd1, fd2};
while(select(max(fd1, fd2)+1, &fd_list, NULL, NULL, NULL) > -1) {
for(i = 0; i < 2; ++i)
if(FD_ISSET(fds[i], &fd_list)) {
nread = read(fds[i], buf, sizeof(buf));
assert(nread > 0);
ret = write(fds[(i+1)%2], buf, nread);
if(ret == -1)
perror("write():");
}
}
After setting up the interfaces using
ifconfig tun0 10.0.0.1
ifconfig tun1 10.0.0.2
I send a ping from one device to the other
ping -I tun1 10.0.0.1
I can see that the IPv4 packet is received by the UDP socket for tun0 and this packet is correctly written to tun0. Also watching the traffic on tun0 using wireshark shows that the packet is received by tun0. However, no ping response packet is created.
I thought that might be a special case for ICMP packets but when I'm using
socat -d -d -d - TCP-LISTEN:2000,so-bindtodevice=tun0 &
sleep 1
echo 2 | socat -d -d -d - TCP:10.0.0.1:2000,so-bindtodevice=tun1
again no connection is established. the connect process (2nd socat call) only continues firing TCP-SYN packets and eventually times out. Again, watching the traffic on tun0 using wireshark shows that the TCP-SYN packet is delivered to the tun0 device.
Why is this packet not forwared to the socat TCP-LISTEN process so it can establish the connection??

Looks like this is a routing error.
When I run the program on two different machines, then the packets are routed through the tun0 device on each machine respectively and http://backreference.org/wp-content/uploads/2010/03/simpletun.tar.bz2 works fine. Running the programm on one machine twice does not work!

Related

Binding to UDP socket *from* a specific IP address

I have packets coming from a specific device directly connected to my machine. When I do a tcpdump -i eno3 -n -n, I can see the packets:
23:58:22.831239 IP 192.168.0.3.6516 > 255.255.255.255.6516: UDP, length 130
eno3 is configured as 192.168.0.10/24
When I set the socket the typical way:
gOptions.sockfd = socket(AF_INET, SOCK_DGRAM, 0);
memset((void *)&gOptions.servaddr, 0, sizeof(struct sockaddr_in));
gOptions.servaddr.sin_family = AF_INET;
inet_pton(AF_INET, gOptions.sourceIP, &(gOptions.servaddr.sin_addr));
gOptions.servaddr.sin_port = htons(gOptions.udpPort);
bind(gOptions.sockfd, (struct sockaddr *)&gOptions.servaddr, sizeof(struct sockaddr_in));
And I use the sourceIP of "255.255.255.255" on port "6516" - it connects and reads.
What I want to do, however, is bind such that I am limiting my connection from the source IP - "192.168.0.3". I have figured out how to connect on the device using either device name ("eno3") of the iface of that device ("192.168.0.10") - but that doesn't help as I may have multiple devices connected to "192.168.0.10" that blab on that port, but I only want the packets from 192.168.0.3 for port 6516.
I thought s_addr - part of sin.addr - was the source IP... but it is not.
You can't bind() to a remote IP/port, only to a local IP/port. So, for what you have described, you need to bind() to the IP/port where the packets are being sent to (192.168.0.10:6516).
Now, you have two options to choose from. You can either:
use recvfrom() to receive packets, using its src_addr parameter to be given each sender's IP/port, and then you can discard packets that were not sent from the desired sender (192.168.0.3:6516).
or, use connect() to statically assign the desired sender's IP/port (192.168.0.3:6516), and then you can use recv() (not recvfrom()) to receive packets from only that sender.

UDP packets visible in wireshark are not captured in Windows sockets (even with raw sockets)

I have a board (with FPGA) connecting to a windows 10 host through a 10G NIC. The board is set to static IP 10.254.210.10 & the host is 10.254.210.11. I can see the UDP packets in wireshark but it is not pass through to the sockets.
UDP packet not able to capture through socket
a) I tried UDP server with socket bind to INADDR_ANY and port 2222. The host has another WI-FI NIC(192.168.x.x). We can capture the packet through sockets when it is entering through this interface. So, I guess it is not a firewall issue.
UDP packet able to capture through socket
b) I created a raw socket but still couldn't capture the packet observed in wireshark.
Enabled promiscuous mode.
// enable promiscuous mode
DWORD dwValue = RCVALL_ON;
DWORD dwBytesReturned = 0;
if (WSAIoctl(s, SIO_RCVALL, &dwValue, sizeof(dwValue), NULL, 0, &dwBytesReturned, NULL, NULL) == SOCKET_ERROR)
{
sprintf(err_msg, "Error to set in promiscous mode: WSAIoctl returned error code %d\n", WSAGetLastError());
printf("Ioctl failed with error code : %d", WSAGetLastError());
fwrite(err_msg, sizeof(err_msg), 1, fp);
closesocket(s);
WSACleanup();
exit(EXIT_FAILURE);
}
puts("Ioctl done\n");
c) netstat doesn't show any errors in "UDP STatistics for IPv4"
d) Both IP checksum and UDP checksum is set to 0000 (i.e disabled).

netcat: listen and capture TCP packets

Is it possible to just listen(not create a new connection) for TCP packets on a port which is already in use, i.e. is sending over data from a router to a server.
I am aware that the following starts the listening process on the mentioned port, and saves it in the pcap file:
SERVER SIDE: nc -l -p <port> > file_name.pcap
CLIENT SIDE: sudo tcpdump -s 0 -U -n -i eth0 not host <server_ip> -w file_name.pcap | nc <server_ip> <port>
But this creates a new connection on the given port and captures packet related to it. I want to capture packets on a port which is already being used to send packets.
Netcat doesn't seem to have that capability currently (according to the man page).
When listening netcat typically opens a socket of family AF_INET (network layer, i.e., TCP/UDP) and type SOCK_STREAM (two-way connection). In contrast, to dump packets, tcpdump opens a socket of family AF_PACKET (device driver layer) and type SOCK_RAW (direct access to packets received).
You can observe this with strace to trace syscalls (here, socket and the subsequent bind) and their arguments:
$ sudo strace -e trace=socket,bind nc -l 8888
socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(8888), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
$
$ sudo strace -e trace=socket,bind tcpdump -w tmp.pcap
[...]
socket(PF_PACKET, SOCK_RAW, 768) = 3
bind(3, {sa_family=AF_PACKET, proto=0x03, if2, pkttype=PACKET_HOST, addr(0)={0, }, 20) = 0
[...]
You can dump traffic at the device driver level (like tcpdump) or the network layer by using a socket of type SOCK_RAW. I.e., you could very well retrieve the file sent over netcat by opening a socket of family AF_INET and type SOCK_RAW, as is implemented in this blog post.

Can I detect whether an UDP-socket or a connected UDP socket is used?

Can I detect whether a client application uses an UDP-socket or a connected UDP-socket?
If yes, how? If no, why?
As I said in my comment above, code call connect on a UDP socket. That enforces only traffic to/from the connection address is allowed (and all other packets get dropped) and allows you to use send instead of sendto, but the traffic is still UDP.
But you can use the netstat command from the command line to see if the datagram socket has a remote address association:
For example, imagine if the code did this:
// create a datagram socket that listens on port 12345
sock = socket(AF_INET, SOCK_DGRAM, 0);
port = 12345;
addrLocal.sin_family = AF_INET;
addrLocal.sin_port = htons(port);
result = bind(sock, (sockaddr*)&addrLocal, sizeof(addrLocal));
// associate the socket only with packets arriving from 1.2.3.4:6666
addrRemote.sin_family = AF_INET;
addrRemote.sin_port = htons(6666);
addrRemote.sin_addr.s_addr = ipaddress; // e.g. "1.2.3.4"
result = connect(sock, (sockaddr*)&addrRemote, sizeof(addrRemote));
A corresponding netstat -a -u will reveal the following:
ubuntu#ip-10-0-0-15:~$ netstat -u -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
udp 0 0 ip-10-0-0-15:12345 1.2.3.4:6666 ESTABLISHED
The presence of a value that isn't *:* in the Foreign Address column for the UDP socket will reveal if the socket has connection address associated with it.

TCL script cannot configure multicast socket

I'm working with tcl script under ubuntu 12.04, and I'm facing some problem when I try to configure a multicast socket. What I'm trying to do is to forward traffic from some socket to a multicast one, but I don't know why although the multicast socket is created well,apparently; it isn't bound to the multicast group I want to.
This is the script I'm using
#!/bin/sh
# test.tcl \
exec tclsh "$0" ${1+"$#"}
package require udp
set multicastPort "50003"
proc connector {unicastIP multicastIP port {protocol tcp}} {
if { [string equal $protocol "tcp"] } {
socket -server serverTCP -myaddr $unicastIP $port
puts "tcp"
} elseif {[string equal $protocol "udp" ] } {
serverUDP $unicastIP $multicastIP $port
puts "udp"
}
}
proc serverUDP {unicastIP multicastIP port} {
global multicastPort
set socketUDP [udp_open $port]
puts " $unicastIP"
fconfigure $socketUDP -blocking false -translation binary -buffering none -remote [list $unicastIP $port]
#fileevent $socketUDP readable [list gettingData $socketUDP]
set multicastSocket [udp_open $multicastPort]
udp_conf $multicastSocket -ttl 4
fconfigure $multicastSocket -blocking false -translation binary -buffering none -mcastadd $multicastIP -remote [list $multicastIP $port]
fileevent $socketUDP readable [list forwarding $socketUDP $multicastSocket ]
#puts $socketUDP "hello!"
#flush $socketUDP
}
proc forwarding {socketSrc socketDst} {
set data [read -nonewline $socketSrc]
puts "Read data-> $data"
puts -nonewline $socketDst $data
puts "Written data-> [read -nonewline $socketDst]"
}
connector 127.0.0.1 224.0.1.1 50000 udp
vwait forever
However if I run the script and check out the ports in my system, the multicast port is not assigned the proper multicast IP as you can see
~$ netstat -ptnlu
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
udp 0 0 0.0.0.0:50000 0.0.0.0:* 3334/tclsh
udp 0 0 0.0.0.0:50003 0.0.0.0:* 3334/tclsh
Could anyone tell me the reason?
THanks in advance,
Regards!
AFAIK, that is OK. I have a multicast daemon in production using Tcl and its udp package, and netstat and ss tools also show me the socket as listening on the wildcard address.
"The trick" here, I suppose, is that multicasting is one level up the stack: joining a multicast group is not merely opening a socket or an endpoint on the group address but rather sending a very real IGMP "join" message to the local transport segment (Ethernet, in most deployments) and further communicating with the nearby IGMP routers (again, on Ethernet, they're mostly switches).
So, in your case, just fire up tcpdump and see what it dumps when you start your program. A useful call to tcpdump looks something like this:
tcpdump -i eth0 -n 'igmp and host 224.0.1.1'
To observe UDP traffic exchanges use
tcpdump -i eth0 -n 'udp and host 224.0.1.1 and port 50000'