Skip to main content

Fake web server using bash, netcat

What if you want to serve some simple html to a browser from a linux server, but don't want to bother with installing a real web server?

I've probably found myself in this situation once every couple of years. The first time I investigated this solution (about 15 years ago now), it was to provide a simple HTTP redirect on a server that housed my company's root domain, but not the top level web server. The root domain had to be pointed there for other reasons, and I didn't want a web server running on it for security reasons. So I wrote a little netcat script that responded with an http 302 pointing to the main web page for the company.

Netcat is a very simple network utility commonly used for things like network connectivity testing. Want to see if that firewall rule was opened, but your application isn't installed yet? Netcat can open a listener port on the destination, and can also be used to initiate traffic from the source.

Starting a listener

For our fake web server, we can initialize the port 80 listener with netcat, then once a connection is made, send some html to whatever initiated the connection like this:

nc -l 80 -k < index.html &

The -l flag binds netcat to a port, -k keeps it open after multiple requests (otherwise it closes after a single request), '< index.html' sends the contents of index.html over the connection once established, and '&' makes it run in the background (otherwise it runs in the foreground and information sent across the connection from the source will show up in stdout).

A caveat to this is that web browsers play a little fast and loose with http connections over port 80, but when it is NOT port 80, they suddenly want specific data in the http header. For instance, changing the listener to 8080 and loading the page in Chrome results in ERR_INVALID_HTTP_RESPONSE.

Inserting an HTTP Response

To fix this, we're going to adjust our simple html file to instead be a bash script that fakes an http 200 response then follows up with the HTML, then calling the script using netcat's -e flag.

So here's the bash script:

#!/bin/bash
echo -e "HTTP/1.1 200 OK\r\n$(date)\r\nContent-Type: text/html; charset=utf-8\r\n\r\n"
echo "<html><body><p>Hello world</p></body></html>"


Don't forget to chmod +x the file, then start the fake web server on port 8080.

nc -l 8080 -k -e index.html.sh &

This results in a happier browser.

Additional note, if you just want to respond with a specific http code and not html (like if you just want to respond with a 302), you can remove the Content-Type part and adjust the http code accordingly.

Inserting images into your HTML

What if you want to have images in the html? Netcat doesn't know how to send referenced images like httpd does, it simply sends the file data over the connection made. Fortunately for us, the http specification supports embedding the image in the html itself. We do this by base64 encoding the image, and adding that data to a html img reference in the index.html.sh script like so:

echo "<p><img src=\"data:image/png;base64,`base64 test.png`\"></p>"

The base64 command is wrapped in ticks (on the ~ key), which tells bash to interpret that as a command, not just text. If you load your page and look at the resulting source, you'll see the base64 encoded image data.

Creating sub-pages and links

But what if we want to support a few sub-pages on our fake web server? Again, netcat isn't going to respect html references because it doesn't care about the data being sent across the connection. However, it does send anything that came across the inbound connection to the script. If you run simply "nc -l 80" and connect to it with your browser, you'll see the full request the browser is making to your server. The line we're interested in looks like this:

GET / HTTP/1.1

So we need to find this line in what is sent, extract the page requested, and send unique html based on that value. In the below bash script, I read the incoming lines in a while loop, once the GET is found, it pulls out the request, puts it into the REQPAGE variable, and breaks out of the while loop. Then I start responding with HTML and an if/elif/else section is used to adjust the content displayed. The else statement is used for the root page and any unknown pages in this case.

#!/bin/bash
echo -e "HTTP/1.1 200 OK\r\n$(date)\r\nContent-Type: text/html; charset=utf-8\r\n\r\n"
while read line
do
if echo "$line" | grep --quiet "GET"; then
REQPAGE=`echo "$line" | cut -f 2 -d " "`
break
fi
done
echo "<html><body>"
if [ "$REQPAGE" == "/page1" ]; then
echo "<p>You're on Page 1!</p><p><a href=/>Go Home</a></p>"
elif [ "$REQPAGE" == "/page2" ]; then
echo "<p>You're on Page 2!</p><p><a href=/>Go Home</a></p>"
else
echo "<p>You're Home</p><p><a href=page1>Page 1</a></p><p><a href=page2>Page 2</a></p>"
fi
echo "</body></html>"


One issue is that the while loop will continue until a GET is received. This is more a protection thing, but if it's a concern you can create a timeout condition by grabbing the $SECONDS variable before entering the while loop and create a condition that breaks after a certain duration. (ie., start=$SECONDS then later duration=$SECONDS - $start). For this, even 1 second is an exorbitant amount of time to receive a request once the connection is made.

Thoughts on security

The benefit to doing something like the above instead of installing httpd or nginx is the overhead is extremely low, and security issues with those pieces of software that require regular patching is greatly reduced. However, on the other side of the coin, the security of this is completely in your hands as the scripter. Above I always wrap what was read ($line, $REQPAGE) in quotes so it's read literally (instead of syntactically) and use only string-affecting commands and comparators. At no time am I interpreting anything passed, which could result in commands being run on the system inappropriately. But that would be a very easy trap to fall into if the script was overly-complicated with features.

Comments

  1. europa bet jeetwin jeetwin 카지노 카지노 제왕카지노 제왕카지노 580Bet365 Betting Tips, Predictions & Previews 2021 - Casino of IBC

    ReplyDelete
  2. Newest Online Casino for US Players | Baccarat, Craps, Slots
    Newest Online Casino for US Players 바카라사이트 · $600 Bonus + 150 FS · $500 Bonus + 150 FS · Free Spins - Up to $600 · 100-200 FS 제왕 카지노 · Free Spins · Minimum 1xbet korean Deposit: $20

    ReplyDelete
  3. Slot machine in Vegas: a Vegas-style slot machine, designed to
    Slot machine 울산광역 출장샵 in Vegas: a Vegas-style 시흥 출장안마 slot machine, designed 익산 출장마사지 to simulate real Las Vegas casino slot machine 거제 출장샵 games, to Vegas-style 정읍 출장샵 slot machine.

    ReplyDelete
  4. Best Black Titanium Wedding Band | Titha Designs
    Titha Designs babyliss pro nano titanium hair dryer offers a stunning iron titanium token wedding band micro hair trimmer with a unique look and titanium belly ring charm that will titanium mens rings enhance the perfect wedding ceremony.

    ReplyDelete
  5. Between 1996 and 2008, online gaming operations have been launched into most nations 코인카지노 with governments creating laws and laws because the trade grew ensuring truthful operation and safe transactions. In 1998, online gaming income worldwide totaled under 1 billion Euros. Fast forward twenty-five years, and recent estimates of online gambling progress foresee the market worth over sixty five billion Euros by 2023. Sometimes would possibly be} offered holds, which in concept increases your probabilities.

    ReplyDelete

Post a Comment