1

I am building a very small http server to control a raspberry pi-based device from a browser using this as a starting point: http://paulbuchheit.blogspot.com/2007/04/webserver-in-bash.html

The core of it is:

#!/bin/bash

RESPONSE=/tmp/webresp
[ -p $RESPONSE ] || mkfifo $RESPONSE

while true ; do
    ( cat $RESPONSE ) | nc -l -p 8080 | (
    REQUEST=`while read L && [ " " "<" "$L" ] ; do echo "$L" ; done`
    REQ="`echo \"$REQUEST\" | head -n 1`"

    echo "[ `date '+%Y-%m-%d %H:%M:%S'` ] $REQ" >>/var/log/http-access.log

    if [[ $REQ =~ ^GET\ /a[\ \/\#?] ]]; then
        # ...
        RESP="<p>You are at A</p><p><a href='/'>Home</a></p>"
    elif [[ $REQ =~ ^GET\ /b[\ \/\#?] ]]; then
        # ...
        RESP="<p>You are at B</p><p><a href='/'>Home</a></p>"
    elif [[ $REQ =~ ^GET\ /c[\ \/\#?] ]]; then
        # ...
        RESP="<p>You are at C</p><p><a href='/'>Home</a></p>"
    else 
        read -r -d '' RESP <<'HTMLDOC'
        <h3>Home</h3>
        <p><a href='/a'>A</a></p>
        <p><a href='/b'>B</a></p>
        <p><a href='/c'>C</a></p>
HTMLDOC

    fi

    cat >$RESPONSE <<EOF
HTTP/1.0 200 OK
Cache-Control: private
Content-Type: text/html
Server: bash/2.0
Connection: Close
Content-Length: ${#RESP}

$RESP
EOF
    )
done

It works great except if I want to run the server on port 80 I have to sudo it. I think it is probably a bad idea to run the server with elevated privileges all the time. How can I un-sudo after it starts listening on port 80? It looks as if the nc command is rerun on each request.

Yes, I know I can run a 'real' lightweight web server but I want to keep the memory footprint as small as possible and I figured bash is already running. Also, I would like to keep the installation limited to adding a few .sh files and running one with a ~/.config/autostart/autorun.desktop file

Mike
  • 2,429
  • 1
  • 27
  • 30
  • 1
    "I think it is probably a bad idea to run the server with elevated privileges all the time." - it's a pretty bad idea to create your own webserver already. Doing so in bash is... fine for toy experiments but not much else. – Mat Mar 17 '13 at 17:42
  • [nginx](http://nginx.org/) or [Python's Simple HTTP Server](http://docs.python.org/2/library/basehttpserver.html) (for an even simple use case) might be a better fit here. They aren't as resource heavy or as Apache, but less headache than doing this manually in Bash : ) – Nick Tomlin Mar 17 '13 at 18:02

2 Answers2

3

All the ports below 1024 are reserved for the super-user (see here). As long as you run the server on another port that is not already in use, you're fine.

michaelmeyer
  • 7,985
  • 7
  • 30
  • 36
2

Problem

You can't drop privileges in Bash scripts the way you're thinking. However, your script doesn't actually need root privileges; it's only netcat that requires them in order to bind to a privileged port.

Solution

Run your script as an unprivileged user, and replace nc -l -p 8080 with sudo nc -l -p 80. This will limit root privileges to the netcat process, rather than providing them to your entire script.

Todd A. Jacobs
  • 81,402
  • 15
  • 141
  • 199