This article will explore the concept of a socket in the Linux operating system: basic data structures, how they work, and whether it is possible to manipulate socket state using an application. As a practice, we will consider the netcat and socat tools.
What is a socket?
A socket is an abstraction of networking in the Linux operating system. Each socket has an IP address + port number pair. This is the standard definition everyone is used to, thanks wiki… Although no, here here better described. Since the socket is just an abstraction, the linking IP-address + port number is already an implementation in the OS. The correct name for this implementation is “Internet Socket”. Abstraction is used so that the operating system can work with any type of data transmission channel. That is why, in Linux, the Internet socket is a descriptor that the system treats like a file. There are, of course, many socket types. more… In the Linux kernel, sockets are represented by three main structures:
struct socket – socket representation BSD, the kind of socket that became the basis for modern “Internet sockets”;
struct sock – its own shell, which in Linux is called “INET socket”;
struct sk_buff – “storage” of data that the socket sends or receives;
As you can see from the source codes, all structures are quite voluminous. Working with them is possible when using a programming language or special wrappers and writing an application. To effectively manage these structures, you need to know what types of socket operations exist and when to use them. There is a set of standard actions for sockets:
socket – create a socket;
bind – the action is used on the server side. In standard terms, this is opening a listening port using the specified interface;
listen – Used to put a socket into a listening state. Applies to the server socket;
connect – used to initialize the connection;
accept – used by the server, creates a new connection for the client;
send / recv – used to work with sending / receiving data;
close – disconnection, socket destruction.
While the structures described above are taken care of by the operating system kernel, in the case of connection control commands, the responsibility is taken by the application that wants to send data over the network. Let’s try to use our knowledge of sockets to work with netcat and socat applications.
The original utility appeared 25 years ago and is no longer supported. Today, there are ports that are supported by various distributions: Debian, Ubuntu, FreeBSD, MacOS. In the operating system, the utility can be invoked using the nc, nc.traditional, or ncat commands, depending on the OS. The utility allows you to work out of the box with sockets that use TCP and UDP protocols as a transport. Examples of use cases that, according to the author, are most interesting:
redirecting incoming / outgoing requests;
transmission of data to the screen in hexadecimal format.
Let’s try the operations in action. The challenge will be to send TCP data over netcat on a UDP connection. For the lab, the following network topology will be used:
Let’s enter the command to open the port on the Destination machine:
nc -u lvvp 7878
Let’s set up the Repeater machine. Since the transmission from one interface of this machine will take place via the TCP protocol, and the other interface will be transmitted via the UDP protocol, for such actions it is necessary to make a connector that will be able to accumulate data and send it between open ports. A FIFO file is perfect for this role. Therefore, the command to run will look like this:
sudo mkfifo /tmp/repeater #создать FIFO файл
sudo nc -l -p 4545 < /tmp/repeater | nc -u -l 10.0.3.5 7878 > tmp/repeaterIP address 10.0.3.5 is the address of the Destination machine. The characters “|” and “> <" represent the pipe and data redirect, respectively. The function is provided by the terminal shell.
We start the connection from the Source machine:
nc 10.0.2.4 4545
As a result, we get the ability to read data from the Source machine:
In the Destination car:
An example with broadcasting data in hexadecimal format can be done in the same way, but replace the command with Destination or add another pipe to Repeater:
nc -l -p 4545 -o file
As a result, a file will be created in which you can find the transmitted data in hexadecimal format:
As you can see from the test use case, netcat gives you almost nothing control, except for the direction of data. There is neither differentiation of access to resources that are sent, nor the ability to work with two sockets without additional tweaks, nor the ability to control socket actions. Let’s test socat.
A tool that is still supported and has a very extensive functionality for gluing channels for interaction. The tool is referred to by the developers as netcat ++. Below is a small list of what can be redirected via socat:
STDIO -> TCP Socket;
FILE -> TCP Socket;
TCP Socket -> Custom Application;
UDP Socket -> Custom Application;
Socket -> Socket.
For everyday use, there are enough options, but if you need to work directly with the serial port or virtual terminal, socat can do it too. A complete list of options can be called using the command:
In addition to redirects, socat can also be used as a universal server for sharing resources; through it, you can restrict privileges and access to system directories like through chroot.
To use this tool comfortably, you need to remember the command line pattern that socat expects:
socat additionalOptions addr1 addr2
additionalOptions – options that can add the ability to log information, control the direction of data transfer;
addr1 – data source or receiver (the use of the U or u flag affects), it can be a socket, file, pipe or virtual terminal;
addr2 – data source or receiver (the use of the U or u flag affects), it can be a socket, file, pipe or virtual terminal;
Let’s try to broadcast data from socket to socket. We will use 1 car for this. Before starting the experiment, it should be noted that the peculiarity of socat is that for its correct operation, it is necessary to write 2 addresses. Moreover, the address does not have to be an address, it can be both an application and standard output to the screen.
For example, to use socat as netcat as a TCP server, you can run this command:
socat TCP-LISTEN:4545, STDOUT
For the connection, you can use netcat:
nc localhost 4545
With this use, socat allows you to send messages in both directions, but if you add the “-u” flag, then communication will only be from client to server. All server messages will not be forwarded:
Let’s fine-tune our server by adding new options separated by commas after the action used:
socat TCP-LISTEN:4545,reuseaddr,keepalive,fork STDOUT
The additional parameters cover the actions that socat can perform on the address. A complete list of options can be found here For more information, see the “SOCKET option group” section.
Thus, socat gives almost complete control over the state of sockets and shared resources.
The article was written on the eve of the start of the course Network engineer. Basic… Anyone who wants to learn more about the course and career prospects, we invite sign up for an open day, which will take place on February 4.