I am setting up a captive portal on a Raspberry Pi (latest distro CLI) where my web application will change NFTables rules based on who is logged in. I have a LEMP stack set up; with Laravel 8 as the PHP framework.
Nginx/php user is www-data
, this user has a sudoers file setup with www-data ALL=(ALL) NOPASSWD:/var/www/vportal.getvs.net/app/Python/vportal.py
The following ls -al
for the python script: -rwxr-xr-x 1 pi www-data 765 Dec 21 11:19 vportal.py
In the Laravel Controller code:
$process = new Process(['python3','/var/www/vportal.getvs.net/app/Python/vportal.py']); $process->run(); // executes after the command finishes if (!$process->isSuccessful()) { throw new ProcessFailedException($process); } echo $process->getOutput();
The Python script:
import subprocess #import os #import pwd #print(pwd.getpwuid(os.getuid()).pw_name) subprocess.run("sudo nft add table nat", shell=True) subprocess.run("sudo nft 'add chain nat postrouting { type nat hook postrouting priority 100; }'", shell=True) subprocess.run("sudo nft add rule ip nat postrouting oifname \"wlan0\" masquerade", shell=True) subprocess.run("sudo nft add table ip filter", shell=True) subprocess.run("sudo nft 'add chain ip filter forward { type filter hook forward priority 0; policy accept; }'", shell=True) subprocess.run("sudo nft add rule ip filter forward iifname \"wlan0\" oifname \"wlx000e3b337325\" ct state related,established accept", shell=True) subprocess.run("sudo nft add rule ip filter forward iifname \"wlx000e3b337325\" oifname \"wlan0\" accept", shell=True)
The idea is to have a route in Laravel 8 trigger the python script through the process command from Symfony on a particular route with the controller. I can run commands that don't require sudo without issues, but my scripts dont want anything to do with sudo. Is there a way to allow www-data
to run a specific script "safely" with sudo privileges?
Note: this is only used on a local network and won't touch the internet. Not that it's any less of a risk that way, but I figured I would at least note this.
#!
line so that the kernel knows which interpreter to use to run the script (defaults to/bin/sh
if unspecified). You want www-data to run your script as root, NOT python with your script as an argument. As @roiama mentioned, you really don't want www-data to be able to run python itself as root.