I need to rebuild my mental model of networking (long forgotten, now inaccurate).
Ultimately I want to remember what exactly happens when a packet is received by my computer, how it is “sent” to the correct application, how it made it there.
Here I play with netcat
on a linux VM.
netcat
man output
NAME nc — arbitrary TCP and UDP connections and listens
What does this mean?
The description is a bit more useful
DESCRIPTION The nc (or netcat) utility is used for just about anything under the sun involving TCP, UDP, or UNIX-domain sockets. It can open TCP connections, send UDP packets, listen on arbitrary TCP and UDP ports, do port scanning, and deal with both IPv4 and IPv6. Unlike telnet(1), nc scripts nicely, and separates error messages onto standard error instead of sending them to standard output, as telnet(1) does with some.
Why does it mention telnet
? I guess there’s some history that links the two somehow. TBC
Listen to a port (thanks to ` -l`)
It’s kind of in server mode.
nc -l -p 4004
Listen for an incoming connection rather than initiating a connection to a remote host. The destination and port to listen on can be specified either as non-optional arguments, or with options -s and -p respectively. Cannot be used together with -x or -z. Additionally, any timeouts specified with the -w option are ignored.
Establishes a connection.
It’s kind of in client mode.
nc localhost 4004
Executing these 2 commands in 2 consoles create a connection and one can send data from either console :)
Observation 1
If you do nc localhost -p 4004
without first opening a connection, nothing happens and it returns.
strace
shows:
connect(3, {sa_family=AF_INET, sin_port=htons(4004), sin_addr=inet_addr("127.0.0.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
pselect6(4, NULL, [3], NULL, NULL, NULL) = 1 (out [3])
getsockopt(3, SOL_SOCKET, SO_ERROR, [ECONNREFUSED], [4]) = 0
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
close(3) = 0
exit_group(1) = ?
+++ exited with 1 +++
So something about a ECONNREFUSED but I don’t know (yet) what these various system calls do.
Observation 2
I can check the port is opened:
nc -zv 127.0.0.1 4000-4010
This scans the port on the localhost between 4000-4010.
I noticed when I executed this that it caused the connection on the other end to close.
I ran strace
and realised all this does is just looping “normal” nc on all ports: so scanning ports here means trying to establish a connection on all the passed ports.
Observation 3
strace nc -l -p 4004
The last few lines are what makes most sense to me:
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
setsockopt(3, SOL_SOCKET, SO_REUSEPORT, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(4004), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(3, 1) = 0
accept4(3,
-
socket
creates a socket:
Function signature:int socket(int domain, int type, int protocol);
AF_INET
: IPv4 Internet protocols,SOCK_STREAM
: the socket type (leaving that one aside),IPPROTO_TCP
: I guess IP over TCP) -
setsockopt
sets some options -
bind
Not fully clear yet but this is important so that the process binds the socket just created and itself. This is only done on the server side. listens
The man page is great :)marks the socket referred to by sockfd as a passive socket, that is, as a socket that will be used to accept incoming connection requests using accept(2).
accept
It gets ready to accept connection.
Observation 4
I don’t understand why doing nc -l -p 4004
twice at the same time doesn’t fail on the 2nd call with something like “already used”.
I thought there will be some sort of checks.