netcat: listen and capture TCP packets - pcap

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.

Related

tcpdump expression syntax error in `ip proto tcp`

I scrutinized the man pages of tcpdump and pcap-filter (which dictates the grammar of tcpdump's expression), but I could not find why my expression is error:
$ sudo tcpdump -i lo 'ip proto tcp'
tcpdump: syntax error
The man page clearly spells out ip proto protocol is valid grammar: https://www.tcpdump.org/manpages/pcap-filter.7.html
Could the issue be a version mismatch?
It looks like tcpdump doesn't understand the tcp alias in that context. You'll need to use the actual IP protocol number:
sudo tcpdump -i lo ip proto 0x6
If you want IPv6 as well (which is what tcpdump -i lo tcp translates to):
sudo tcpdump -i lo ip proto 0x6 or ip6 proto 0x6

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.

Socat not closing tcp connection

I use socat 1.7.3.1-r0 and run following command on an alpine 3.3 linux server:
socat -d -d -d PTY,link=/dev/ttyFOOBAR,echo=0,raw,unlink-close=0 TCP-LISTEN:7000,forever,reuseaddr
Socat will listen for clients and create a bidirectional communication by passing data from the virtual serial port /dev/ttyFOOBAR to the client and back again over TCP. Once the client disconnects socat should exit.
When such a connection is established socat logs the following:
I socat by Gerhard Rieger - see www.dest-unreach.org
I This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit. (http://www.openssl.org/)
I This product includes software written by Tim Hudson (tjh#cryptsoft.com)
I setting option "symbolic-link" to "/dev/ttyFOOBAR"
I setting option "echo" to 0
I setting option "raw"
I setting option "unlink-close" to 0
I openpty({5}, {6}, {"/dev/pts/3"},,) -> 0
N PTY is /dev/pts/3
I setting option "forever" to 1
I setting option "so-reuseaddr" to 1
I socket(2, 1, 6) -> 7
I starting accept loop
N listening on AF=2 0.0.0.0:7000
I accept(7, {2, AF=2 CLIENT_IP:PORT}, 16) -> 8
N accepting connection from AF=2 CLIENT_IP:PORT on AF=2 172.20.0.2:7000
I permitting connection from AF=2 CLIENT_IP:PORT
I close(7)
I resolved and opened all sock addresses
N starting data transfer loop with FDs [5,5] and [8,8]
ss command on the server prints:
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
tcp ESTAB 0 0 172.20.0.2:7000 CLIENT_IP:PORT
The problem is, that when I disconnect the client (by switching it off), the tcp connection is still established and no addition logging is coming from socat. ss still shows the connection as ESTAB. Any ideas why? When I again connect the client following appears in the logs:
W read(8, 0x7fa8f48c4020, 8192): Connection reset by peer
N socket 2 to socket 1 is in error
N socket 2 (fd 8) is at EOF
I poll timed out (no data within 0.500000 seconds)
I close(5)
I shutdown(8, 2)
I shutdown(8, 2): Socket not connected
N exiting with status 0
But why does this happen on connect instead of disconnect?
If there is no data to send or receive on a socket and you cut the underlying connection neither side is aware until it attempts to send data. Normally, that would be application level data, but at the protocol level you can enable TCP keep alives to emulate flowing data whenever there is no real data.
According to the socat manpage you could try something like:
socat -d -d -d PTY,link=/dev/ttyFOOBAR,echo=0,raw,unlink-close=0 TCP-LISTEN:7000,forever,reuseaddr,keepalive,keepidle=10,keepintvl=10,keepcnt=2
(keepalive actually looks like the essential option but it is unclear what the defaults will be for the tuning options if unset.)

tun device: message is not received by server process

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!

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'