Skip to content

Instantly share code, notes, and snippets.

@kentbrew
Last active May 21, 2025 03:29
Show Gist options
  • Select an option

  • Save kentbrew/776580 to your computer and use it in GitHub Desktop.

Select an option

Save kentbrew/776580 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.

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:

@sahanDissanayake

Copy link
Copy Markdown

@kentbrew I'm facing the same hard time of getting the nodejs ( SailsJS ) app to run on EC2. IP forwarding works perfectly. But breaks when I need to access the phpmyadmin.

Please let me know if you have a solution.

Thank you

@ccerrato147

Copy link
Copy Markdown

Thanks! Worked like a charm!!!

@dvidsilva

Copy link
Copy Markdown

<3 I fought for hours with this stupid nginx, thanks for this!

@silveur

silveur commented May 15, 2015

Copy link
Copy Markdown

thanks so much

@eladnava

Copy link
Copy Markdown

Excellent work, thanks for your post!

Here's my take on this using nginx as a reverse proxy:
https://eladnava.com/binding-nodejs-port-80-using-nginx/

@Dinesh1991

Copy link
Copy Markdown

When I use the below command, I am able to redirect from port 3000 to port 80, but I need to redirect to port 80 when a request is for any other port.

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3000

@baodinh

baodinh commented Mar 10, 2016

Copy link
Copy Markdown

Thanks so much, i want to know what is disadvantage of this solution ?

@Alagarasan

Copy link
Copy Markdown

Thanks man. A great solution. I was breaking my head. Wonderful 👍

@peturh

peturh commented Jun 7, 2016

Copy link
Copy Markdown

Yup, this did it for me. Tried getting the load balancer up, men feels overkill for my solution.

@nobodhi

nobodhi commented Sep 2, 2016

Copy link
Copy Markdown

This solution works partially, but will not allow the node server to see the /CSS folder, so all formatting is lost. Same with images, etc.

@JustinWinthers

JustinWinthers commented Sep 29, 2016

Copy link
Copy Markdown

If you're using AWS, a preferred way is to use cloudfront or an elastic load balancer. You can easily create a cloudfront distribution or classic elastic load balancer that will forward traffic to the port of your choice on your ec2 server. You can even create load balancers with only one ec2 instance if you don't want to use cloudfront. This in my opinion should be preferred as you can also quickly add a ssl certificate to your distribution or load balancer using the AWS certificate manager without any server configuration. Then just simply point your A record(s) to the public DNS for your distribution or load balancer. No code, no hacks, easy as pie.

@rohitarjunagi

Copy link
Copy Markdown

Worked! Thanks much!

@stavarengo

stavarengo commented Nov 19, 2016

Copy link
Copy Markdown

Its important to notice that these configurations will be lost after system restarts.
@kentbrew, I added the instructions to make it persistent between restarts. What you think to add it here?
Checkout the updated .MD code.

@artforlife

Copy link
Copy Markdown

This came useful. Much appreciated!

@thaiMao

thaiMao commented Nov 30, 2016

Copy link
Copy Markdown

Very useful. Many thanks

@rcarl94

rcarl94 commented Dec 2, 2016

Copy link
Copy Markdown

Awesome stuff, thank you sir.

@andfinally

Copy link
Copy Markdown

Thanks! Very handy.

@FoxxMD

FoxxMD commented Jun 19, 2017

Copy link
Copy Markdown

Thanks @JustinWinthers classic ELB is exactly what I needed 👍

@suman1459

Copy link
Copy Markdown

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
Copy Markdown

awesome! thx a lot

@imneil24

Copy link
Copy Markdown

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

Thanks

@sombek

sombek commented Sep 19, 2017

Copy link
Copy Markdown

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

@sombek

sombek commented Sep 19, 2017

Copy link
Copy Markdown

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

@DecentM

DecentM commented Sep 20, 2017

Copy link
Copy Markdown

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

marwanmakm commented Nov 16, 2020

Copy link
Copy Markdown

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
Copy Markdown

Works even in 2021. You're a legend!

@ravish1729

Copy link
Copy Markdown

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

@Ravencore-Project

Copy link
Copy Markdown

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

@jonbel16

jonbel16 commented Oct 7, 2022

Copy link
Copy Markdown

Works in 2022. Thank you

@andrei-coelho

Copy link
Copy Markdown

Very nice! Is still relevant!

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