Skip to content

Instantly share code, notes, and snippets.

@stavarengo
Forked from kentbrew/node-on-ec2-port-80.md
Last active December 8, 2016 09:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stavarengo/ac2034fd2064c169f79d522f1213ecc5 to your computer and use it in GitHub Desktop.
Save stavarengo/ac2034fd2064c169f79d522f1213ecc5 to your computer and use it in GitHub Desktop.
How I Got Node.js Talking on EC2's Port 80

The Problem

Standard practices say no non-root process gets to talk to the Internet on a port less than 1024. How, then, could I get Node talking on port 80 on EC2? (I wanted it to go as fast as possible and use the smallest possible share of my teeny tiny little micro-instance's resources, so proxying through nginx or Apache seemed suboptimal.)

The temptingly easy but ultimately wrong solution:

Alter the port the script talks to from 8000 to 80:

}).listen(80);

.. and run it as root:

sudo /usr/local/bin/node foo.js

This is a Bad Idea, for all the standard reasons. (Here's one: if Node has access to the filesystem for any reason, you're hosed.)

One possibly-right way:

Add a port forwarding rule via iptables.

Oh dear familiar feeling: you are a total n00b and know not one thing about iptables.

First, I listed the rules currently running on the NAT (Network Address Translation) table:

[ec2-user@ip-XX-XXX-XX-X ~]$ sudo iptables -t nat -L

Chain INPUT (policy ACCEPT)
target     prot opt source    destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source    destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source    destination

I saw nothing, so I felt free to add a rule forwarding packets sent to external port 80 to internal port 8000:

[ec2-user@ip-XX-XXX-XX-X ~]$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8000

When I listed again, I saw a new PREROUTING chain:

[ec2-user@ip-XX-XXX-XX-X ~]$ sudo iptables -t nat -L

Chain PREROUTING (policy ACCEPT)
target     prot opt source     destination         
REDIRECT   tcp  --  anywhere   anywhere     tcp dpt:http redir ports 8000 

I checked my Node script, which was running on port 8000, and (yes!) it was responding on port 80.

Persisting iptables after system restart

The above steps go over how to setup a PREROUTING, but all of the settings will be lost after the system restarts. If you want to have your iptables PREROUTING saved everytime you reboot, use one of these two options.

  1. First option (recomended)
    It is how the official ipttable's documentation teach us. See here
    Add these two lines in /etc/network/interfaces:
    pre-up iptables-restore < /etc/iptables.rules
    post-down iptables-save > /etc/iptables.rules
    The line "post-down iptables-save > /etc/iptables.rules" will save the rules to be used on the next boot.

  2. Second option
    You can add those PREROUTING commands to /etc/rc.local, so it will be executed automatically after reboot.
    It is not recomended since firewall rules should never go into rc.local script. The rc.local is the last thing to be executed. If a block rule has been placed into rc.local there is a small time frame where an attacker can exploit a rule not being in place.
    While it probably doesn't matter with this situation, it is still best to not get into a bad habit that may bite you later. (Take from here)

Fumbling

During my early attempts I screwed up a bunch of times. I removed busted rules by specifying the right table, the right chain, and the right line number, like so:

[ec2-user@ip-XX-XXX-XX-X ~]$ sudo iptables -t nat -D PREROUTING 1

This removed the first line from the PREROUTING chain in my nat table.

Careful, now....

I did not do this myself but throughout this process I had a very strong feeling I should be very careful not to screw up port 22, which was my only way in.

Acknowledgements:

@Scimonster
Copy link

My EC2 instance (Amazon Linux) doesn't seem to have an /etc/network/interfaces file, or even the directory. I just see /etc/networks (file).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment