Can Socket.io listen on multiple ports? - node.js

Is it possible for socket.io to listen on multiple ports in one server?
Background - I need to satisfy two problems:
1.Some cooperate & other closed networks block all traffic which does not use port 80.
2.Some anti viruses block websocket traffic on port 80. Port 4000 is the safest port to use.
I therefore need to my node server to be able to use port 80 and 4000 simultaneously. Has anyone experienced similar problems? How did you solve it?
Thank you.

Suppose your process is listening on port 4000, it's my understanding you can use iptables to internally forward requests for port 80.
# iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 4000
/edit got the ports the wrong way around.

Related

How do I access my node.js server via public IP address?

I want to get a response from a remote node.js server by typing my public IP address into my browser. When I type my public IP into my browser on my personal computer, I get "Unable to Connect". My node.js server isn't connected to the World =(
I am running CentOS on a Linode (but I don't think either choice should matter to my question).
Via Terminal on my person computer (a Mac), I can successfully SSH as root into my Linode.
I have installed node.js successfully on my Linode.
I can compile and run a simple server on my Linode.
var http = require('http');//create a server object:
http.createServer(function (req, res) {
res.write('Hello World!'); //write a response
res.end(); //end the response
}).listen(3000, function(){
console.log("server start at port 3000");
});
I've tried:
Setting a hostname.
Changing the "hosts" file on my server.
Changing the port number in my node.js server (3000, 80, 8080, 3001, 0.0.0.0, etc).
Read literally 100 articles today about how to deploy a node.js server.
Searched Google, Stackoverflow, Linode forums, etc for threads that might help me.
I have zero idea what I'm doing wrong and would be so grateful for your help.
I eventually found the answer, thanks to Saddy's suggestion that the problem might be port forwarding.
1. I decided to use ports 3080 and 3443 for my node server.
2. I SSHed into my CentOs instance.
3. I disabled the default firewall, firewalld.
4. I set up port forwarding using iptables with the following commands:
firewalld stop
firewalld disable
iptables -I INPUT 1 -p tcp --dport 80 -j ACCEPT
iptables -I INPUT 1 -p tcp --dport 443 -j ACCEPT
iptables -I INPUT 1 -p tcp --dport 25 -j ACCEPT
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 3080
iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 3443
iptables-save > /etc/sysconfig/iptables
After this, I was able to access my node server via a browser.

Run node app with SSL on 443 port (on 80 is working)

It's my first time when I try configure a server running on Amazon EC2.
I figured out how run my node app on 80 port but now I'm trying to run on 443 port with Letsencrypt SSL. Before to work on 80 port I added
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 3000
and
sudo iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-ports 3000
and everything worked fine. But now after install Letsencrypt I try to do same thing but with 433 port instead 80 and it's not working.
Letsencrypt config automatically for me all files so now redirect from http to https is working fine and when my iptable is empty on https:// I see ubuntu default website. When I run lines mentioned above with 443 port app is still not working (browser can't even load anything). It's only working with http:/...:3000
I've added 443 port to Security Groups on EC2.
What I can do? Thanks.
You need to check your security group Inbound/Outbound rules, you need to see if port 443 is assigned to which host. A valid but dangerous configuration, just for testing, is allow everything on Inbound and Outbound, to see if its a problem on your Security Group.
Beyond that, you need to be sure if the binding port is listening. Are you using Amazon Linux?

Having Apache httpd listen on port 80, but not started as root?

I would like to have my Apache httpd launch as non-route user (httpd) and still listen on port 80/443. This server will be running on a Linux host.
Given that the first 1024 ports are reserved, how would I go about having a reserved port handled by a non-root daemon? Alternatively, can I run my apache on a non-reserved port and have the port's traffic redirect locally to that other port?
You can use iptables for port redirecting:
# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

Listening to EVERY port on a machine

For testing purposes I want to build a server that listens for TCP connections to every port (or at least on most of the ports) on a certain interface (e.g., eth0). The server is accessed via SSH to eth1, so no problem there. (I do not care about UDP or other protocols)
I want to do a special kind of middlebox detection/analysis, therefore I need to be able to fully establish a connection. Having an HTTP connection would be the best, because the "client" could be implemented as JS in the Browser.
I started with a simple jetty server, but had to realize that jetty needs to spawn at least on thread per port it is listening to. This leads to problems when I want to listen to several thousand ports. Or is there a way around that?
My next try was to use iptables:
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp -j DNAT --to-destination 127.0.0.1:8080`
It seemed to work. It allows to connect on every port and the traffic gets routed to the local port 8080 where jetty listens. But now I no longer know which port was used by the client. Because jetty thinks the connection was established via port 8080. Is there a way to determine the real incomming port from jetty? I could send the port as part of the HTTP request, but if the client tries to contact port 1234 .. and a middlebox redirects this to port 5678 .. I am unable to know what port was used.
I also tried userland solutions like socat. The problem was even worse than before. Because now jetty also saw the remote IP as being 127.0.0.1.
Or, is there another way to achieve this?
Oh and btw: I have full control of the machine. So I could change the kernel or whatever is needed. Right now I use Ubuntu 14.04 LTS, but if a solution needs something else I could go with that.
NB: This is a Python solution, because I know Python, but you can accomplish the same thing in any language the exposes the underlying C library getsockopt call.
If you replace your DNAT rule with a REDIRECT rule, you can then
use getsockopt with the SO_ORIGINAL_DST option to retrieve the
original address of a REDIRECT-ed connection.
Consider the following code:
#!/usr/bin/python
import socket
import struct
SO_ORIGINAL_DST = 80
s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('0.0.0.0', 2000))
s.listen(10)
while True:
csock, caddr = s.accept()
orig_dst = csock.getsockopt(socket.SOL_IP, SO_ORIGINAL_DST, 16)
orig_port = struct.unpack('>H', orig_dst[2:4])
orig_addr = socket.inet_ntoa(orig_dst[4:8])
print 'connection from', caddr
print 'connection to', (orig_addr, orig_port)
print
If I have an iptables rule that looks like:
# iptables -t nat -A PREROUTING -p tcp --dport 1500:1600 \
-j REDIRECT --to-port 2000
And while the above Python code is running I connect from another
host to my_ip_address:1500, I see:
connection from ('192.168.1.20', 35790)
connection to ('192.168.1.75', (1500,))
And if I connect to port 1550 I see:
connection from ('192.168.1.20', 42054)
connection to ('192.168.1.75', (1550,))
Which I think is exactly what you were asking for. Note that to my knowledge this will only work for TCP connections; there are other solutions (possibly involving the TPROXY iptables target) that may work with UDP connections as well.

Check if port forwarding worked for node server on AWS machine

I have deployed a node application that listens to port 5000 on a free usage tier ubuntu machine from AWS.
I've followed suggestions from:
How to start node.js on port 80 on a linux server?
and from: Best practices when running Node.js with port 80 (Ubuntu / Linode)
Answers to both these questions suggest port forwarding and I have done the same. But my server still doesn't respond to requests on port 80.
Is there a way I can check if the port forwarding was successful?
The permission settings to listen to HTTP requests have been setup through the AWS console.
Also there is nothing listening to port 80 on the machine as of now. netstat -l | grep :80 comes up empty.
The server runs fine if I access it as: http://<elastic-ip>:5000
You will not see port 80 listening since there is no daemon using that socket; the kernel is performing a packet redirect.
To check how many packets traversed the port forwarding rule you set up, inspect the PREROUTING chain on the nat tables with sudo iptables -t nat -L PREROUTING -n -v. It will show output like:
Chain PREROUTING (policy ACCEPT 15 packets, 1226 bytes)
pkts bytes target prot opt in out source destination
3 180 REDIRECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 redir ports 3000
If you are testing from localhost, you must also redirect on OUTPUT since PREROUTING isn't used by the loopback interface. Do that with
iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 3000
And of course, check that port 80 is open to allow external traffic.

Resources