Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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.

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:

@suman1459
Copy link

When I use the below command, I am able to redirect from port 443 to port 8000, but I also want to redirect my port 80 to 8000 .

sudo iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 8000

@FerreiraRaphael
Copy link

awesome! thx a lot

@imZEH
Copy link

imZEH commented Sep 12, 2017

Is there a command that rerouting port from 8000 to 80 upon restart the instance ?
some says use UFW ?

Thanks

@sombek
Copy link

sombek commented Sep 19, 2017

Working!!
Thank you it's really helpful.
spent the last night searching for this problem!

@sombek
Copy link

sombek commented Sep 19, 2017

@imZEH
Why you don't use the elastic IP instead?

@DecentM
Copy link

DecentM commented Sep 20, 2017

I usually just give the node binary permission to open a service port with sudo setcap 'cap_net_bind_service=+ep' $(which node)
(or replace $(which node) with wherever your node binary is if that returns a symlink)

@marwanmakm
Copy link

marwanmakm commented Nov 16, 2020

Excellent bro, It works perfectly!!. Now I can access without problems to my Node.js Server running in my EC2 instance and configure a Domain.

Thank you

@CameronHonis
Copy link

Works even in 2021. You're a legend!

@ravish1729
Copy link

You saved me a ton of time thank you!!!

@TomO2015
Copy link

to save the change in ubuntu
sudo /sbin/iptables-save

@jonbel16
Copy link

jonbel16 commented Oct 7, 2022

Works in 2022. Thank you

@andrei-coelho
Copy link

Very nice! Is still relevant!

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