April 05, 2021

Hi all, I'm currently moving my server to new hardware and with that I'm porting some of my D applications to be more efficient. For this I have found one cool thing: SystemD .socket files.

SystemD .socket files are basically wrapping any program in a CGI, which is a lot like just having a server running the entire time. You then put the port you assigned to the socket behind a reverse proxy like caddy or nginx and it effectively always spawns the D program whenever there is a request with the raw HTTP request as stdin and expecting an output in stdout.

My last post is an example of something using this.

It requires manual parsing of HTTP, but arsd.cgi could be used to do this task (with the plain CGI version set) - however for simple endpoints like basic loggers this can be really well working.

To set it up you have to create 4 things: a one-shot SystemD service which is executed on every request, a SystemD socket which handles the networking, the CGI app, a reverse proxy handling HTTPS and stuff.

SystemD example files: (with hardened security)

>

/etc/systemd/system/http-org-webfreak-completion.socket

[Unit]
Description = Completion suggestion logger

[Socket]
ListenStream = 2141
Accept = yes

[Install]
WantedBy = sockets.target
>

/etc/systemd/system/http-org-webfreak-completion@.service

[Unit]
Description=Completion server accepter script

[Service]
User=http
Group=http

ExecStart=/srv/http/org.webfreak.completion/log
WorkingDirectory=/srv/http/org.webfreak.completion
StandardInput=socket

InaccessiblePaths=/opt/ /etc/opt/ /boot/ /mnt/ /media/
ProtectSystem=strict
ProtectHome=true
TemporaryFileSystem=/var:ro
BindPaths=/srv/http/org.webfreak.completion

# Device resrictions
PrivateDevices=true
DevicePolicy=closed
#DeviceAllow=/dev/sda r

# Security/permissions
NoNewPrivileges=true
CapabilityBoundingSet=
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
#AmbientCapabilities=CAP_NET_BIND_SERVICE
# Note: PrivateUsers prevents bind on privileged ports!
PrivateUsers=true

# System call filter
SystemCallArchitectures=native
SystemCallFilter=@system-service
LockPersonality=true
RestrictNamespaces=true
RestrictRealtime=true
#RestrictSUIDSGID=true

# Various restrictions (mix of filesystem access and system call restrictions)
ProtectKernelModules=true
ProtectKernelTunables=true
ProtectControlGroups=true
#ProtectKernelLogs=true
#ProtectClock=true
#ProtectHostname=true
#ProtectProc=invisible

# Enforce W^X
# Note: Add /tmp/ if not mounted noexec!
InaccessiblePaths=/dev/shm/ /dev/mqueue/ /dev/pts/ /dev/hugepages/
MemoryDenyWriteExecute=true
SystemCallFilter=~memfd_create

# Cleanup leftover IPC objects
RemoveIPC=true
>

Caddyfile

completion.webfreak.org {
        root * /srv/http/org.webfreak.completion/public
        file_server
        push /index.html /completion.png

        reverse_proxy /submit [::1]:2141
}
>

log.d

curl https://completion.webfreak.org/log.d

April 06, 2021

On Monday, 5 April 2021 at 23:03:14 UTC, WebFreak001 wrote:

>

Hi all, I'm currently moving my server to new hardware and with that I'm porting some of my D applications to be more efficient. For this I have found one cool thing: SystemD .socket files.

[...]

This is actually a bit cozy