Door Anoniem: Linux Systemd werkt met een context, zodanig dat je niet elk proces volledige root rechten hoeft te geven. Je kunt vergaand beveiligen. Kijk met
systemd-analyze security
of
systemd-analyze security php7.4-fpm
. Elk proces wat vanuit de daemon wordt gestart heeft daarmee ook de environment met de geselecteerde set permissies en blokkeringen van die service.conf.
Ben je ervan op de hoogte dat daemons als apache2 en exim4 hun werk helemaal niet als root doen? Ze starten weliswaar als root, maar dat dient om naar gepriviligeerde poorten (poortnummers onder 1024) te kunnen luisteren. Ik zie dat exim4 na allocatie van die poorten van root overstapt op de user Debian-exim. Apache2 maakt een fork (kloon) van zichzelf die terugvalt naar user www-data, die de poort(en) om naar te luisteren erft en (via verder geforkte worker-processen) requests afhandelt. Het proces dat nog onder root blijft draaien dient om als er iets goed misgaat, als bijvoorbeeld de netwerkverbinding opnieuw gealloceerd moet worden, de zaak helemaal opnieuw op te starten. Voor dat soort dingen heeft systemd ook faciliteiten, maar apache2 (en trouwens ook exim) zijn ouder dan systemd en kunnen ook draaien op systemen zonder systemd.
Dat bijvoorbeeld apache2 op Debian in de defaultconfiguratie een hele dikke UNSAFE van 'systemd-analyze security' krijgt wil daarom niet zeggen dat het ook echt zo droevig gesteld is ermee, systemd-analyze pikt niet op wat apache2 zelf al doet. Daarmee wil ik niet beweren dat de toegevoegde mogelijkheden van systemd onzin zijn, je kan je met systemd bijvoorbeeld onafhankelijk maken van de vraag of het in de daemon-software zelf wel goed is geïmplementeerd.
Misschien kan ik voor dit geval sendmail/exim4 overslaan en rechtstreeks het bericht in de lokale IMAP structuur (Maildir/new) plaatsen. Dat is een hack, daarvoor zou ik de code van de Contact Form plugin moeten aanpassen. Dat is lastig met updaten.
Niet doen, dat wordt veel te getruukt. Als je de neiging hebt om dat soort dingen te gaan doen is dat een signaal dat je de verkeerde weg inslaat of al ergens de verkeerde weg in bent geslagen. Dat laatste los je niet op door verder te gaan op de verkeerde weg en te proberen de gevolgen te bestrijden, dat los je op door terug te gaan naar het punt waar je verkeerd ging en daar de goede weg te nemen.
Je noemde dat naast sendmail ook exim4 als commando wordt aangeroepen vanuit php7.4-fpm, voor locale bezorging via LMTP. Als ik het goed begrijp ondersteunt exim4 dat als manier om via unix sockets (die je ook noemt) mail aan te leveren aan een ander proces. Begrijp ik goed dat je niet alleen sendmail uitvoert om mail te bezorgen maar ook exim4 om het vanuit je php7.4-fpm-container door te geven aan de eigenlijke exim4-service, omdat dat niet vanzelf blijkt te werken?
Ik heb in de verste verte niet genoeg kennis van zowel exim4 als van de mogelijkheden van systemd die je gebruikt, maar als ik me niet vergis is sendmail dezelfde executable als exim4 en gebruikt die de suid-bit om met andere/hogere rechten te draaien dan de gebruiker die hem aanroept. Het lijkt me dan heel waarschijnlijk dat de container die je via systemd hebt ingericht blokkeert dat sendmail de aangeleverde berichten nog kan plaatsen waar de exim4-daemon ze kan oppakken, omdat de suid-user binnen een container alleen maar binnen die container rechten heeft en niet daarbuiten. En dan vermoed ik dat de LMTP-oplossing bedoeld was om die beperking te omzeilen, maar dat je er tegenaan loopt dat dat om een (nog) onduidelijke reden ook niet werkt.
Overweeg of het volstaat om, in plaats van alle netwerktoegang te blokkeren, php7.4-fpm alleen localhost toe te staan. Dat kan je in de servicedefinitie met IPAddressAllow=localhost en IPAddressDeny=any regelen (zie "man systemd.resource-control"), en dan kan je de suggestie van Anoniem van gisteren om 19:47 volgen: lever aan de exim4-daemon aan via SMTP en zonder ingewikkelde constructies waar je het overzicht over kwijtraakt.
Als het per se op poortniveau moet worden dichtgetimmerd is het mogelijk om systemd-services van een eigen firewall te voorzien die ook op poortniveau kan filteren, maar helaas wordt dat weer knap ingewikkeld, je moet er zogenaamde BPF-programma's voor schrijven en daaraan refereren met de opties IPIngressFilterPath en IPEgressFilterPath. Zie bijvoorbeeld hier voor een indruk van wat die BPF-programma's om het lijf hebben:
https://kailueke.gitlab.io/systemd-custom-bpf-firewall/Je zou in plaats daarvan ook met iptables of nftables een firewall-regel kunnen maken die blokkeert dat vanaf de server zelf verbinding wordt gemaakt met andere dan toegestane poorten op localhost. Dat is minder specifiek (je regelt zo niet welk proces welke poort mag benaderen) maar ook veel simpeler dan geklooi met BPF-programma's, en iemand die jou ooit moet vervangen zal vermoedelijk eerder bekend zijn met Netfilter-interfaces dan met die BPF-programma's.
Ik kan niet voor jou invullen wat nodig is voor dit systeem, maar sla niet door in complexiteit, want het is heel makkelijk om dingen ingewikkelder te maken dan je zelf nog aankan, zeker als je middenin worstelingen zit om iets aan de praat te krijgen. Dan ga je fouten maken, en fouten leveren risico's op, voor de beveiliging en voor de continuïteit. Probeer het zo simpel mogelijk te houden, liefst beduidend simpeler dan je op dit moment denkt aan te kunnen, want de werkelijkheid heeft de vervelende neiging om een beroep te doen op je kennis en overzicht op momenten dat je met heel andere puzzels zit te worstelen en er eigenlijk geen ruimte voor hebt.