How to make your web server/NVR/any service behind Carrier Grade NAT accessible from WAN using Socat, ZeroTier

Let’s say that you want to access your home surveillance cameras from anywhere, if you have a public IPv4 address from ISP its as simple as forwarding a port on the router.

However, Carrier Grade NAT makes this complicated. You cannot just forward a port and make web servers accessible from your public IP if you are on a Carrier Grade NAT. ISPs may also charge a ton of money for public IP or straight up refuse to provide one.

In this tutorial I will show you how to very easily relay your web server through a VPS.

Here is a diagram to see the workings:

socat.png


Hardware you will need:

  • A Linux machine within your LAN: This is what we will be using to connect to ZeroTier network. You can use something simple like a Raspberry Pi. In my case I will be using my home server running Ubuntu 20.04.
  • Any Linux VPS with a public IP: You will need a VPS with a public IP running Linux. This is what we will be using to access our local NVR from WAN.
Software needed:

  • Socat Proxy: Socat will be used to forward port from LAN to our ZeroTier network. This way we won’t have to bridge the networks.
  • ZeroTier: ZeroTier can punch through CGN to make direct connection between our VPS and Home Server. This is what allows us to port forward using Socat.

Step 1: Install ZeroTier on both the systems​



You can install ZeroTier pretty easy with:

curl -s https://install.zerotier.com | sudo bash


This works on most Linux distros including Debian, Ubuntu, CentOS, RHEL, Fedora etc.

Step 2: Create a network on my.zerotier.com​



You will need to create the ZeroTier network on my.zerotier.com/network . Register an account if you don’t have one and create a network.

Once you have a network, set it to Public from Private and note down its Network ID.

Step 3: Connect both devices to ZeroTier.​



Next, let’s connect both devices to the network we just created. To do this enter the following command on both the machines:

sudo zerotier-cli join <network_id>

Replace <network_id> with your network ID.

You should see both the devices on: my.zerotier.com/network/<network_id> under Members section. Note down the IP Address of both the devices. For me, local server is on: 10.147.19.37 and VPS is on: 10.147.19.235

socat-1.png


Now that both devices are on ZT, you can set Access Control to Private on same page.

Step 4: Socat​



You will need to install socat on both the systems. Socat is a simple program for forwarding ports across IPs.

On Ubuntu/Debian this is as simple as:

sudo apt install socat

The commands should be similar for other distros as well as Socat is in the package list of most distros.

Now that socat is installed you need to forward the ports on both your systems

Step 5: Forwarding ports using Socat​



My web server is located on 192.168.5.250 on port 80 inside my LAN. Hence we will run the following command on local machine:

socat TCP-LISTEN:45114,fork TCP:192.168.5.250:80

You can replace the 45114 with any high port that won’t be used.

Now, our web server is accessible on our local server at both 192.168.5.240:45114 (which is our LAN) and 10.147.19.37:45114 (ZeroTier IP of local machine).

Step 5: Forwarding the port to WAN​



Now that we have our web server accessible from ZeroTier network. We can forward the port 45114 of our local machine to the internet. To do this we will run the following command:

sudo socat TCP-LISTEN:80,fork TCP:10.147.19.37:45114

Note that in some distros, listening on low ports (such as 80 or 443) needs sudo privileges. You can change TCP-LISTEN to something high like 42142 to not require sudo.

Here 10.147.19.37 is the ZeroTier IP of your local machine and we are making socat listen on Port 80 which is standard port of http. You don’t have to make it listen on port 80, you can use any port you want if you are running something like NVR for better security.

On running this we should be able to access the web server from public IP of VPS with whatever port we made it in listen earlier.

Step 6: socat start on boot​



The problem with running socat like we did earlier is that, we have to keep the SSH/Shell open otherwise socat will stop. In order to prevent this we will setup a service.

We will setup a service on both our systems:

On our home server:​



Find the path of your socat binary using:

which socat

In my case it’s /usr/bin/socat

Enter following command:

sudo nano /etc/systemd/system/socat.service

Type in the following into nano:

[Unit]

Description=Socat Proxy

[Service]

Type=simple
ExecStart=/usr/bin/socat TCP-LISTEN:45114,fork TCP:192.168.5.250:80



[Install]

WantedBy=multi-user.target




Change /usr/bin/socat to whatever your socat binary path is in your system

Change 192.168.5.250:80 to address of your web server



Press Ctrl+O and Enter to save the file and Ctrl+X to exit from Nano



Type in sudo systemctl daemon-reload to reload systemd
Type in sudo systemctl start socat to start socat service

On the VPS:​



Do the same thing to find path of socat binary

Type in:
sudo nano /etc/systemd/system/socat.service

Type in following to nano:

[Unit]

Description=Socat Proxy

[Service]

Type=simple
ExecStart=/usr/bin/socat TCP-LISTEN:42142,fork TCP:10.147.19.37:45114

[Install]

WantedBy=multi-user.target




Change 42142 to whatever port you want your webserver accessible from WAN. Also change 10.147.19.37 to your local machine’s ZeroTier IP



Press Ctrl+O and Enter to save the file and Ctrl+X to exit from Nano


Type in sudo systemctl daemon-reload to reload systemd
Type in sudo systemctl start socat to start socat service


That’s it you should be able to access your webserver/NVR from anywhere on the public IP of VPS with the you set as TCP-LISTEN on the VPS’s service file. In my case its http://25.21.214.2:42142

To make it start on reboot enter:

sudo systemctl daemon-reload
sudo systemctl enable socat


on both the systems
 
Posted on wrong section, please move to Guides @Sushubh
 
Can we have multiple services/ servers on Pi......i.e NVR & webserver etc.... all hosted parallely, at the same time.
 
Socat Proxy: Socat will be used to forward port from LAN to our ZeroTier network. This way we won’t have to bridge the networks.

We could make use of L3 routing as well right? That's what I have done, my main ZeroTier node (well, my router) also acts as router for ZeroTier traffic for my local network, and I have added the route to my local network on my.zerotier.com portal. So any ZeroTier device can reach the devices on my local LAN through my main router.

Code:
root@s1 ~ # mtr -w 192.168.1.163
Start: 2020-09-14T09:51:54+0200
HOST: s1            Loss%   Snt   Last   Avg  Best  Wrst StDev
  1.|-- 172.22.1.3     0.0%    10  194.2 211.1 194.2 223.5  11.0
  2.|-- 192.168.1.163  0.0%    10  206.8 213.9 187.0 255.1  21.2
root@s1 ~ #

This way you can avoid the socat, and I guess you'd just need an iptables rule to do DNAT to the different IP/ports on your local network.
 
@JB701 Thanks for the tutorial guide.
Just a few questions, if you'd be kind enough to help me out here:-

1) Since you're not using SNAT or MASQUERADE on the VPS, the source IP of a connection request remains the same, with the packet simply being forwarded. So this means, if I access my NVR from a public IP, only the initial connect request gets forwarded via the VPS to my home router, whence to my NVR, correct?
The reply and the subsequent stream of data comes back directly to the source IP, bypassing the VPS?

I'm asking this to understand bandwith usage that would be incurred on the VPS?
 


Ah that's an interesting question. I did test it out by only with forwarding the web interface of my AP.

I think both the directions will go through the VPS though as Socat handles it all.
Ill test further to figure that out.

@varkey method of using the ZT device at home as a router/gateway also looks pretty neat.
 
Last edited:
@varkey how to host ZT on router? Do we require some special kind of router or any normal router can do?

Also I have similar kind of problem, My LCO stop giving me static IP since he changed his main line, So my new NVR with platform access works fine (I can access using hik-connect app from 4G) but my older DVR which requires static IP and port forwarding does not work with CG-NAT.

The VPS (with ZT & socat) solution seems fine but for AWS only 15GB/month of bandwidth is free after which you have to pay per GB.
 
@devangpatel You'd need a router running custom firmware like OpenWRT. On factory firmware you wouldn't be able to do that.
Or you'd need a separate device like a Raspberry Pi where ZeroTier can be installed and made to work as a router.

Regarding the VPS, you can look at Oracle Cloud, they give a lifetime free VM, however network throughput is limited to 50 mbps.
 
so then, I can use socat with ZT to access my DVR without VPS. since I usually use my smartphone to access my cameras using Hik-connect app.

basically no need of public IP for me since I can run my home desktop for 24X7 and run ZT node on it. So from that I can fork my DVR port 80 service and can access from my phone where I have ZT. So simply adding my desktop ZT IP (with forked service) in hik connect app I may access DVR.

I'll try this solution and let know the live view performance.
 

Top