Project

General

Profile

Serving applications as TCP sockets » History » Revision 3

Revision 2 (manawyrm, 05/01/2022 11:44 PM) → Revision 3/4 (manawyrm, 05/01/2022 11:45 PM)

h1. Serving applications as TCP sockets 

 systemd has become the standard init system on most Linux machines.  
 One lesser known feature is ability to serve TCP sockets and launch arbitrary services on connection. 
 This was usually done using inetd/xinetd in the past. 

 More information about inetd-replacement of systemd can be found at:  
 http://0pointer.de/blog/projects/inetd.html 

 h2. Hello World example 

 Create <code>/etc/systemd/system/octoi-helloworld.socket</code> with the following content:<pre><code class="ini"> 
 [Unit] 
 Description=OCTOI HelloWorld Socket for Per-Connection Servers 

 [Socket] 
 ListenStream=31337 
 Accept=yes 

 [Install] 
 WantedBy=sockets.target 
 </code></pre> 
 <code class="ini">ListenStream=</code> is the TCP port on which the service should run. 
 <code class="ini">Accept=yes</code> causes systemd to accept() incoming connections directly. This could also be done by the service later on.   
  
 Create <code>/etc/systemd/system/octoi-helloworld@.service</code> with the following content:<pre><code class="ini"> 
 [Unit] 
 Description=OCTOI HelloWorld Socket Per-Connection Server 

 [Service] 
 ExecStart=-/opt/octoi-helloworld.sh 
 StandardInput=socket 
 StandardError=null 
 DynamicUser=true 
 </code></pre> 

 <code class="ini">ExecStart=</code> is the program that will be executed. Notice the - at the beginning, which will get systemd to ignore any non-zero return codes. 
 <code class="ini">StandardInput=socket</code> will redirect any input from the socket to the program. 
 <code class="ini">StandardError=null</code> will redirect any error output to /dev/null. 
 <code class="ini">DynamicUser=true</code> is a very useful feature that will _dynamically create a new system user and group_ , with a new PID/GID for each incoming connection. This is done internally without touching the /etc/passwd file.  
 If the application allows for this, it can be a powerful tool for security (by isolating the processes and minimizing permissions). 
 +Warning: Applications with <code>DynamicUser</code> enabled run with their own private <code>/tmp</code> directories. Don't try to exchange files/sockets with other processes there.+ 

 systemd can also drop permissions in the usual way, by specifying a fixed user and group: 
 <pre><code class="ini"> 
 User=helloworld 
 Group=helloworld 
 </code></pre> 

 Create <code>/opt/octoi-helloworld.sh</code>: 
 <pre><code class="shell"> 
 #!/bin/bash 
 echo "Hello World" 

 # Sleep before closing the session to give PortMaster time to flush 
 # all data onto the connection. 
 sleep 5 
 </code></pre> 

 Don't forget to set +x permissions on the shell script. 

 Reload systemds configuration, then enable and start the socket: 
 <pre><code class="shell"> 
 systemctl daemon-reload 
 systemctl enable --now octoi-phonebook.socket 
 </code></pre> 

 systemd is now listening to the TCP port: 
 <pre><code class="shell"> 
 # netstat -tulpen 
 Active Internet connections (only servers) 
 Proto Recv-Q Send-Q Local Address             Foreign Address           State         User         Inode        PID/Program name     
 tcp6         0        0 :::13063                  :::*                      LISTEN        0            2674600      1/systemd            
 </code></pre> 

 You can check the status (and the number of past connections) with: 
 <pre><code class="shell"> 
 # systemctl status octoi-helloworld.socket octoi-phonebook.socket 
 ● octoi-helloworld.socket - OCTOI HelloWorld Socket for Per-Connection Servers 
      Loaded: loaded (/etc/systemd/system/octoi-helloworld.socket; enabled; vendor preset: enabled) 
      Active: active (listening) since Mon 2022-05-02 01:11:11 CEST; 29min ago 
    Triggers: ● octoi-phonebook@8-123.123.123.85:31337-123.123.123.123:1091.service 
      Listen: [::]:31337 (Stream) 
    Accepted: 8; Connected: 1; 
       Tasks: 0 (limit: 1131) 
      Memory: 4.0K 
         CPU: 4ms 
      CGroup: /system.slice/octoi-helloworld.socket 

 Mai 02 01:11:11 communityisdn systemd[1]: Listening on OCTOI HelloWorld Socket for Per-Connection Servers. 
 </code></pre> 

 For each open connection, you can see the "Triggers:" line, with the service which has been started for that connection. 
Add picture from clipboard (Maximum size: 48.8 MB)