Sockets | UNIX Domain Socket (IPC) | Network Socket
Enable inter-process communication (IPC) between programs running on a server, or between programs running on separate servers. Communication between servers relies on network sockets, which use the Internet Protocol (IP) to encapsulate and handle sending and receiving data.
Network sockets on both clients and servers are referred to by their socket address. An address is a unique combination of a transport protocol like the Transmission Control Protocol (TCP) or User Datagram Protocol (UDP), an IP address, and a port number. A network socket is effectively a network port (location) as seen from inside the target node (machine).
The server listens (passive socket); the client connects (active socket).
Socket Types
- TCP Stream Sockets use TCP as the underlying protocol.
- UDP Datagram Sockets
- Unix Domain Sockets
- Use local files, instead of network interfaces and IP packets, to send and receive data.
- Use local files, instead of network interfaces and IP packets, to send and receive data.
Utilities
socat(1): SOcketcat; Multipurpose relay; establishes two bidirectional byte streams and transfers data between them. Streams can be constructed from a large set of different types of data sinks and sources; lots of address options may be applied to the streams; used for many different purposes.- The life cycle of a
socatinstance typically consists of four phases.- In the init phase, the command line options are parsed and logging is initialized
- The first address and then second address are opened. These steps are usually blocking; thus, especially for complex address types like SOCKS, connection requests or authentication dialogs must be completed before the next step is started.
- In the transfer phase,
socatwatches bothstreamscqread and write file descriptors; when data is available on one side and can be written to the other side, socat reads it, performs newline character conversions if required, and writes the data to the write file descriptor of the other stream, then continues waiting for more data in both directions. - When one of the streams effectively reaches
EOF, the closing phase begins; theEOFcondition is transfered to the other stream, i.e. tries to shutdown only its write stream, giving it a chance to terminate gracefully. For a defined timesocatcontinues to transfer data in the other direction, but then closes all remaining channels and terminates.
- The life cycle of a
ss(8): socket statistics; newer and similar tonetstat(8)utility.nc(1): AKAnetcat; arbitrary TCP and UDP connections and listens; just about anything involving TCP or UDP. 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. Unliketelnet(1),ncscripts nicely, and separatesSTDERRfromSTDOUT.
Use socat(1)
# Usage syntax
socat [options] <address> <address>
# <address>
protocol:ip:port
TCP-based Stream Sockets
Stream sockets are connection oriented; packets sent to and received from a network socket are delivered by the host operating system in order for processing by an application. Network based stream sockets typically use the Transmission Control Protocol (TCP) to encapsulate and transmit data over a network interface.
TCP is designed to be a reliable network protocol that relies on a stateful connection. Data that is sent by a program using a TCP-based stream socket will be successfully received by a remote system (assuming there are no routing, firewall, or other connectivity issues). TCP packets can arrive on a physical network interface in any order. In the event that packets arrive out of order, the network adapter and host operating system will ensure that they are reassembled in the correct sequence for processing by an application.
A typical use for a TCP-based stream socket would be for a web server like Apache or Nginx handling HTTP requests on port 80, or HTTPS on port 443. For HTTP, a socket address would be similar to 203.0.113.1:80, and for HTTPS it would be something like 203.0.113.1:443.
Creating TCP-based Stream Sockets
Emulate a web server listening for HTTP requests on port 8080 (the alternative HTTP port); create two TCP-based sockets that are listening for connections on port 8080 using IPv4 and IPv6 interfaces:
socat TCP4-LISTEN:8080,fork /dev/null &
socat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null &
TCP4-LISTEN:8080andTCP6-LISTEN:8080args are protocol type and port number to use; creates TCP sockets on port8080on all IPv4 and IPv6 interfaces, and listens to each socket for incoming connections. Valid port range is0to65535.forkoption prevents thesocatprocess from termating after it handles a connection./dev/nullpath is used here in place of what would be the remote socket address; prints (cat) incoming input to that file, which silently discards it.ipv6only=1flag is used for the IPv6 socket to tell the operating system that the socket is not configured to send packets to IPv4-mapped IPv6 addresses. Without this flag, socat will bind to both IPv4 and IPv6 addresses.&character instructs the shell to run the command (process) in the background, so we can invoke other commands on this terminal to examine the socket.
Examining TCP-based Stream Sockets
Show socket statistics
ss -tln
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 5 0.0.0.0:8080 0.0.0.0:*
LISTEN 0 5 [::]:8080 [::]:*
...
- The
Localfield,0.0.0.0:8080, shows the IPv4 TCP socket is listening on all available IPv4 interfaces on port8080. A service that is only listening on a specific IPv4 address will show only that IP in that field, e.g.,203.0.113.1:8080. Similarly for the IPv6 TCP socket. - "
::" is IPv6 addresss of all zeros.- Example report at
Localfield if listening to a specific IPv6 address:[2604:a880:400:d1::3d3:6001]:8080
- Example report at
Use
-4and-6flags to examine only one (IPv4 or IPv6).ss -4 -tlntflag filters out all but for TCP sockets.lflag filters out all but for listening sockets. Without this flag, all TCP connections would be displayed, which would include things like SSH, clients that may be connected to a web-server, or connections that your system may have to other servers.nflag reports port numbers instead of service names, e.g.,8080ishttp-alt.
Connecting to TCP-Based Stream Sockets
Connect to the IPv4 socket, created to listen on all interfaces, over the local loopback address.
nc -4 -vz 127.0.0.1 8080
Connection to 127.0.0.1 8080 port [tcp/http-alt] succeeded!
-4flag tells netcat to use IPv4.-vflag is used to print verbose output to your terminal.-zoption ensures thatnetcatconnects to the socket without sending any data.The local loopback
127.0.0.1IP address is used since your system will have its own unique IP address. If you know the IP for your system you can test using that as well. For example, if your system’s public or private IP address is 203.0.113.1 you could use that in place of the loopback IP.nc -4 -vz 10.0.100.52 8080
Similarly for IPv6 connection
nc -6 -vz ::1 8080
::1is IPv6 loopback.
Cleanup : Disconnect/Delete Sockets
Bring each background socket process (job) to the foreground and kill it;
first display all by number (jobs),
then bring each to foreground (fg %$n), killing each in turn (CTRL-C) .
/mnt/shared # jobs
[2]+ Running socat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null
[1]- Running socat TCP4-LISTEN:8080,fork /dev/null
/mnt/shared # fg %2
socat TCP6-LISTEN:8080,ipv6only=1,fork /dev/null # CTRL-C
/mnt/shared # fg %1
socat TCP4-LISTEN:8080,fork /dev/null # CTRL-C
/mnt/shared # jobs
/mnt/shared #
Datagram Sockets
Datagram sockets are connectionless, which means that packets sent and received from a socket are processed individually by applications. Network-based datagram sockets typically use the User Datagram Protocol (UDP) to encapsulate and transmit data.
UDP does not encode sequence information in packet headers, and there is no error correction built into the protocol. Programs that use datagram-based network sockets must build in their own error handling and data ordering logic to ensure successful data transmission.
UDP sockets are commonly used by Domain Name System (DNS) servers. By default, DNS servers use port 53 to send and receive queries for domain names. An example UDP socket address for a DNS server would be similar to 203.0.113.1:53.
Note: The protocol (TCP/UDP) is not included in the human-readable version of the socket address, but operating systems differentiate socket addresses by including TCP and UDP protocols as part of the address. So a human-readable socket address like
203.0.113.1:53could be using either protocol. Tools likess, and the oldernetstatutility, are used to determine which kind of socket is being used.
The Network Time Protocol (NTP) uses a UDP socket on port 123 to synchronize clocks between computers. An example UDP socket for the NTP protocol would be 203.0.113.1:123.
Creating Datagram Sockets
Emulate an NTP server listening for requests on UDP port 123 using sockets. Then examine them using the ss and nc commands.
First create two UDP sockets that are listening for connections on port 123,
using IPv4 and IPv6 interfaces:
socat UDP4-LISTEN:123,fork /dev/null &
socat UDP6-LISTEN:123,ipv6only=1,fork /dev/null &
- Privileged user (
sudo) required to create ports0-1024.
Examining Datagram Sockets
Show socket statistics
ss -uln |grep 123
UNCONN 0 0 0.0.0.0:123 0.0.0.0:*
UNCONN 0 0 [::]:123 [::]:*
Testing Datagram Sockets
Connect
nc -4 -u -vz 127.0.0.1 123
Connection to 127.0.0.1 123 port [udp/ntp] succeeded!
-uto connect per UPD instead of (default) TCP- See TCP section for explanation of other options.
Cleanup using same method as with TCP Sockets
Unix Domain Socket | Wikipedia
About
A Unix domain socket aka UDS or IPC socket (inter-process communication socket) is a data communications endpoint for exchanging data between processes executing on the same host operating system; UDS data is exchanged between programs directly in the OS kernel via files on the host filesystem; programs read and write to their shared socket file, bypassing network based sockets and protocols entirely. It is also referred to by its address family
AF_UNIX. UDS may be stream-based or datagram-based. Valid socket types in the UNIX domain are:
SOCK_STREAM(compare to TCP) – for a stream-oriented socketSOCK_DGRAM(compare to UDP) – for a datagram-oriented socket that preserves message boundaries (as on most UNIX implementations, UNIX domain datagram sockets are always reliable and don't reorder datagrams)SOCK_SEQPACKET(compare to SCTP) – for a sequenced-packet socket that is connection-oriented, preserves message boundaries, and delivers messages in the order that they were sent
The Unix domain socket facility is a standard component of POSIX operating systems.
The API for Unix domain sockets is similar to that of an Internet socket, but rather than using an underlying network protocol, all communication occurs entirely within the operating system kernel.
UDS is used widely by database systems that do not need to be connected to a network interface; MySQL on Ubuntu defaults to using a file named /var/run/mysqld/mysql.sock for communication with local clients. Clients read from and write to the socket, as does the MySQL server itself.
PostgreSQL is another database system that uses a socket for local, non-network communication. Typically it defaults to using /run/postgresql/.s.PGSQL.5432 as its socket file.
Creating Unix Domain Sockets
Create both stream-based and datagram-based Unix Domain Sockets without using TCP or UDP to encapsulate data to send over networks.
# Create stream-based UDS
socat UNIX-LISTEN:/tmp/stream.sock,fork /dev/null &
# Create datagram-based UDS
socat UNIX-RECVFROM:/tmp/datagram.sock,fork /dev/null &
- Both commands specify a filename after the "
:" separator. The filename is the address of the socket itself. The name of a socket is arbitrary but it helps if it is descriptive when you are troubleshooting. forkoption prevents thesocatprocess from termating after it handles a connection./dev/nullpath is used here in place of what would be the remote socket address; prints (cat) incoming input to that file, which silently discards it.&character instructs the shell to run the command (process) in the background, so we can invoke other commands on this terminal to examine the socket.
Examining Unix Domain Sockets
ss -xln
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
u_str LISTEN 0 5 /tmp/stream.sock 269122 * 0
u_dgr UNCONN 0 0 /tmp/datagram.sock 269288 * 0
...
-xflag to filter out all but for domain sockets.u_strindicates the UDS is stream-based.u_dgrindicates the UDS is datagram-based.
Since UDSs are files, the usual Linux user and group permissions and access controls can be used to restrict who can connect to the socket. You can also use filesystem tools like ls, mv, chown and chmod to examine and manipulate UDS files. Tools like SELinux can also be used to label UDS files with different security contexts.
To check if a file is a UDS socket, use the ls, file or stat utilities. However, it is important to note that none of these tools can determine if a UDS is stream or datagram-based. Use the ss tool for the most complete information about a Unix Domain Socket.
@ ls
/mnt/shared # ls /tmp
...
srwxr-xr-x 1 root root 0 Dec 8 14:34 datagram.sock
srwxr-xr-x 1 root root 0 Dec 8 14:33 stream.sock
@ stat
/mnt/shared # stat /tmp/stream.sock /tmp/datagram.sock
File: /tmp/stream.sock
Size: 0 Blocks: 0 IO Block: 4096 socket
Device: 9eh/158d Inode: 1366937 Links: 1
Access: (0755/srwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2022-12-08 14:33:03.611342000 -0500
Modify: 2022-12-08 14:33:03.611342000 -0500
Change: 2022-12-08 14:33:03.611342000 -0500
File: /tmp/datagram.sock
Size: 0 Blocks: 0 IO Block: 4096 socket
Device: 9eh/158d Inode: 1366942 Links: 1
Access: (0755/srwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2022-12-08 14:34:06.231657000 -0500
Modify: 2022-12-08 14:34:06.231657000 -0500
Change: 2022-12-08 14:34:06.231657000 -0500
Connecting to Unix Domain Sockets
# Connect to stream-based UDS
nc -U -z /tmp/stream.sock
# Connect to datagram-based UDS
nc -uU -z /tmp/datagram.sock
Cleanup using same method as with TCP Sockets
File Descriptors
In Unix and Unix-like computer operating systems, a file descriptor (FD, less frequently fildes) is a process-unique identifier (handle) for a file or other input/output resource, such as a pipe or network socket.
File descriptors typically have non-negative integer values, with negative values being reserved to indicate "no value" or error conditions.
File descriptors are a part of the POSIX API. Each Unix process (except perhaps daemons) should have three standard POSIX file descriptors, corresponding to the three standard streams:
| # | Name | symbolic constant <unistd.h> |
file stream <stdio.h> |
|---|---|---|---|
0 |
Standard input | STDIN_FILENO |
stdin |
1 |
Standard output | STDOUT_FILENO |
stdout |
2 |
Standard error | STDERR_FILENO |
stderr |
File Descriptor 3
# Needn't exist
☩ ls /dev/tcp
ls: cannot access '/dev/tcp': No such file or directory
# Create
☩ exec 3<>/dev/tcp/google.com/80
# Not seen as either a file or directory
☩ ls /dev/tcp
ls: cannot access '/dev/tcp': No such file or directory
# Send GET request
☩ echo -e "GET / HTTP/1.1\n\r" >&3
# Read response
☩ cat <&3
HTTP/1.1 200 OK
...
Content-Type: text/html; charset=ISO-8859-1
...
Transfer-Encoding: chunked
539e
<!doctype html><html ...