socket.io is an amazing library which makes it very easy to use websockets. This library gives us real-time communication ability in the browser with very little code.
This article is written for people already familiar with Linux, and Internet networking and security concepts.
We need to perform a man-in-the-middle to get control of the network
Start with a Linux virtual machine. It’s going to need two interfaces – one internal and one external. The internal interface is the one connected to a LAN. If at all possible using bridged mode for this interface and grabbing a DHCP lease from the network the host computer is on.
These interface names will probably be different in your case. For the purpose of this document I will use these interfaces. Replace with yours:
Internal interface __eth3__
External interface __eth2__
Get a DHCP lease from the internal network if you do not have one already
Now your virtual machine should be able to surf the Internet.
Now to deal with the external interface. I’m using a MacBook which does not have any Ethernet plugs so I plug in a USB Ethernet adapter. It asks if I want to connect it to the MacBook or the VMWare Linux host. Choose Linux. tail /var/log/syslog in the linux guest when you plug it in to see which ethernet interface number (ethX) Linux assigns to the interface. We want to hard-code an IP 192.168.2.1 to this new interface so we can run a DHCP server here.
Install dhcp3-server. Here is a copy of the /etc/dhcp3/dhcpd.conf which will serve IP numbers in the range 192.168.2.100-200
# see if a dhcp *client* is running
# kill any DHCP client on the external interface. A DHCP client running on the same interface as the DHCP server can cause this interface to request an IP – breaking things. We need to prevent that.
# assign the static ip 192.168.2.1 to the external interface
# start the dhcp server on the external interface
# enable network address translation (NAT) a.k.a masquerading. the -o option is for the internal interface
# enable ip forwarding – tells Linux that it is allowed to forward traffic between interfaces
Now we want to serve some customers on this USB Ethernet adapter. If you hook this new interface eth2 into a switch, any computer which connects to this switch should get an IP address from the dhcp server running and be able to surf the Internet through your new Linux router. If that is not the case then you need to go back and figure out what is wrong before proceeding.
At this point one could optionally use airbase-ng with Karma or hook a WIFI pineapple to the external interface in Karma mode to catch wireless clients as well. Those wireless clients would get an IP address from the WIFI pineapple and would be double NAT’ted, but that’s OK. I’m not going to get into more details about this piece at this time.
You have a working Linux router. Congratulations. Now to start modifying the traffic. Sergio Proxy is a great tool for this part. It supports code injection, sslstrip. Sergio proxy runs on port 10000 by default.
Download Sergio Proxy and unzip it somewhere.
Right-click and save this injection-code.html file for use with sergio-proxy. It will add the script tags to load socket.io.
You need to get the outbound HTTP/HTTPS requests from the clients to point to sergio proxy. There are some options for this:
– Manually point the proxy settings in the browser to
– Use transparent proxy to force all clients into the proxy
Test with upsidedown internet first to see if sergio-proxy is working alone
If everything looks upside down, Control-C to quit, and launch sergio proxy with html file injection option
Download socket.io and unzip it somewhere.
Right-click and save this app.js for use with socket.io
Right-click and save this socket-script.js for use with socket.io
Start the socket.io server. Make sure app.js and socket-script.js are in the socket.io folder and start it. This requires node.
Connections going through your Linux router should be surfing the Internet successfully before moving on to this step. Sergio proxy should be running on port 10000, but not being used yet. socket.io should be running on port 80 but have no connections yet (unless you had manually set up a browser proxy settings to point there).
Now to enable transparent proxy to force outbound HTTP port 80 (and optionally HTTPS port 443) connections through the proxy.
In the following example, I enable the proxy only for source IP of 192.168.2.102. You probably want to modify this to what makes sense in your configuration. If you mess up, instructions on removing a iptables rule are also below.
transparent proxy multiport for 80 and 443 in one line:
or if you only want to test with HTTP and not HTTPS – transparent proxy just for port 80 (HTTP):
If you need to disable transparent proxy for any reason, here is how to do it. First, list the rules in the PREROUTING chain
find the rule you want to delete and
where # is the rule number to delete
If you have made it this far, now for the fun part – the socket.io command and control page. We create a page which connects to the socket.io server and has administrative functions available to monitor and control the clients.
– Right click and save the socket.io command and control page socket-io-cnc.html
You can just double click on this command and control page and load it up. The page will need to connect to the socket.io server, so it must be able to reach 192.168.2.1, the IP address where the socket.io server is running.
If the page is loaded, and able to reach the socket.io server, you should see active connections listed.
The page running the code on another browser
* Running a socket.io server on a Internet accessible server is much more versatile than running one locally only on a private IP such as 192.168.2.1.
* A SSL-enabled socket.io server is required to control a page using HTTPS
* socket.io security/authentication
* local IP discovery with WebRTC