The problem: CGNAT and remote access
I have a lot of applications running locally on a server located in my house, and I want to be able to use them when I go on a trip, but obviously I can only use them with my home wifi.
This is a very common problem among people like you and me who have our own NAS or simply a shoddy computer that we had left over, running some self-hosting application.
This has a very easy solution, it is solved with a VPN, but watch out, be careful if your operator works under CGNAT, you will lose all control of your IP and it will make having a VPN to your home very complicated. But calm down, Iâm here to solve it.
The youtube video where I talk about this topic:
What is a VPN?
A VPN (Virtual Private Network) is a method to create a secure connection between your device and a private network over the Internet. It is used, for example, to connect to your companyâs network or in our case we are going to do it to connect to home as if we were physically there.
Do not think that a VPN serves only so that suddenly your location appears in another country, that is the function of commercial VPNs, but in the end what they do is the same thing we want: pass our connection to a specific place.
The function of VPNs is basically to encrypt data, pass it through a secure tunnel and redirect traffic so that it passes through the server we want.

What is CGNAT?
CGNAT (Carrier-Grade NAT) is a technology used by Internet Service Providers (ISPs) to manage the shortage of IPv4 addresses. Basically, instead of assigning you a unique public IP address, they put you in a system where multiple users share the same public IP. They do this because, with the lack of IPv4 addresses, they cannot give an exclusive IP to each client.
This would be solved if they started working with IPv6, which are the super long chunks that I donât know if you have ever seen, but since not all companies do it yet, we have to swallow this botchâŠ
The big drawback is that, by sharing the IP with other users, you cannot open ports or access your network directly from outside. This affects:
- Home servers (games, NAS, security cameras, etc.).
- Remote access to your network (for example, with a home VPN, although we are going to solve that today).
- P2P services or anything that needs direct incoming connections.
How do I know if I am under CGNAT?
Knowing if you are under CGNAT is very simple, and you have several methods to know, a very common and quick one is first to find out your IP. To not complicate things, if you put âwhat is my ipâ in Google, hundreds of results will appear where they indicate the IP.
Well, now that you have it, write it down, and go to the router settings. These are usually at 192.168.1.1 or 192.168.1.0 depending on your gateway.
You can also find out, if it doesnât appear, by opening a console, typing ipconfig (in Windows) or ifconfig (in Linux/Mac) and looking for the phrase that says âdefault gatewayâ.
Once in your router panel you log in with the user that surely puts behind the little paper of your router and look for something similar to âInternetâ or âWANâ until you find an IP.
In my case it was the Internet section, and further down two WANs appeared. Both, just by looking at them reveal that I am under CGNAT. How? Look closely, one starts with 10 and another with 100. Not only are they different from the IP that appeared on the web we saw before, which with that already tells us everything, but the one starting with 10 indicates that it is a private IP, and not public, and the other is within the range of CGNAT IPs which are between 100.64.x.x and 100.127.x.x.

This is the way to do it if you more or less understand the subject and put some effort into it, but if you donât want to complicate things there is a faster option, and that is to call your company and ask them. In my case they told me in the first call, and it is true that some, if you ask, assign you a public IP without CGNAT, but in my case if I asked for it they raised the monthly bill to double what I pay. Crazy, right?
The solution: create a Wireguard tunnel with a VPS
This can be done in many ways. There is software like Tailscale or Zerotier that allow doing the same thing we are going to do, but they limit the devices unless we pay and also it is not 100% private like this that we are going to do. And besides, in this channel we like to tinker, right?
For our solution, we need:
- A device at home (Raspberry Pi, PC, etc.) that will always be on.
- A VPS (cloud server) with public IP that will act as a bridge.
The idea is simple: we establish a VPN tunnel between our home device and the VPS, and then we connect to the VPS from anywhere to access our home network.

What we need
- At home: A Raspberry Pi (recommended for its low consumption) or any PC that can always be on.
- In the cloud: A basic VPS. You can use the free tier of Oracle Cloud or an economical server from DigitalOcean/Vultr/etc.
I am going to use Docker to simplify the installation, so we will need to have it installed on both the VPS and the Raspberry Pi.
Step 1: VPS Configuration
First, we must prepare the server that will serve as a bridge between the internet and our house.
Connect to the VPS via SSH
The first thing we need is to connect to the server via SSH. If you are using a VPS from Oracle Cloud, DigitalOcean or similar, you surely have to use a private key to connect:
ssh -i name_of_your_private_key user@server_ip
Note: The private key is the one you saved when creating the instance. If it gives you permission problems, make sure to give it the correct permissions:
In Linux/Mac:
chmod 600 name_of_your_private_keyIn Windows:
icacls "C:\path\to\your\private_key.pem" /inheritance:r icacls "C:\path\to\your\private_key.pem" /grant:r "%USERNAME%:R"
If it asks for a password instead of a private key, simply use:
ssh user@server_ip
And then enter the password you configured.
Installation of Docker and Docker Compose
# Update the system
sudo apt update
sudo apt upgrade -y
# Install necessary dependencies
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
# Add Docker's official GPG key
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
# Add Docker repository
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
# Update and install Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io
# Add current user to the docker group
sudo usermod -aG docker $USER
# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.15.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# Verify installation
docker --version
docker-compose --version
Prepare Wireguard configuration
Now we are going to clone my repository containing all the necessary files:
git clone https://github.com/edunavajas/wireguard-cgnat.git
cd wireguard-cgnat/vps
Generate Wireguard keys
It is important to generate keys for our server:
# Create config directory if it doesn't exist
mkdir -p config
# Generate keys with appropriate permissions
cd config
umask 077 && sudo sh -c 'wg genkey | tee privatekey | wg pubkey > publickey'
# Verify that the keys have been created correctly
ls -la
Configure the Wireguard server
Now we are going to give execution permissions to the configuration script:
cd ../
sudo chmod +x setup-wireguard-tunnel.sh
We open the necessary ports:
sudo ufw allow 51820/udp
sudo ufw status
And we execute the configuration script:
sudo ./setup-wireguard-tunnel.sh
This script will perform:
- Enable IP forwarding
- Start the Wireguard Docker container
- Configure iptables for routing
- Generate client keys and configurations automatically
Modify client configuration
Now we modify the generated configuration to allow access to our home network:
cd /config/wg_confs/
nano wg0.conf
Find the peer1 section and modify the AllowedIPs line to include your home network:
[Peer] # peer1
PublicKey = ...
...
AllowedIPs = 10.69.69.2/32, 192.168.1.0/24
This allows traffic to the client (10.69.69.2) and to your home network (192.168.1.0/24, adjust this to your subnet).
Restart the Wireguard service to apply the changes:
docker-compose down
docker-compose up -d
Get configuration for the client
Save the client configuration to use on the Raspberry Pi:
cat config/peer1/peer1.conf
Copy all the content that appears, we will need it for the Raspberry Pi.
Step 2: Raspberry Pi Configuration
Now we will configure our Raspberry Pi to connect to the VPS.
Connect to the Raspberry Pi via SSH
To connect to our Raspberry Pi, we need to use SSH. If you are on the same network as the Raspberry, you can connect using:
ssh user@raspberry_ip
The default user on Raspberry Pi OS is usually âpiâ, although you may have changed it. You can find out the IP from your router or using tools like nmap:
nmap -sn 192.168.1.0/24
This will scan your local network for devices. Look for the one corresponding to your Raspberry Pi.
Tip: To make connection easier in the future, you can set a static IP on your Raspberry Pi or add it to your hosts file.
If it asks for a password, by default on Raspberry Pi OS it is âraspberryâ, although it is highly recommended to change it for security.
Docker Installation
If you donât have Docker installed on your Raspberry Pi yet, follow these steps:
# Update the system
sudo apt update
sudo apt upgrade -y
# Install dependencies
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Add user to the docker group
sudo usermod -aG docker $USER
# Install Docker Compose
sudo pip3 install docker-compose
Configure Wireguard on the Raspberry Pi
First, we clone the repository:
git clone https://github.com/edunavajas/wireguard-cgnat.git
cd wireguard-cgnat/raspberry
We give execution permissions to the script:
sudo chmod +x setup-wireguard-client.sh
We create the configuration directory and the configuration file:
mkdir -p config
nano config/wg0.conf
Here we paste the peer1 configuration we copied from the VPS, making sure it has this structure:
[Interface]
PrivateKey = <PRIVATE_KEY>
Address = 10.69.69.2/24
DNS = 1.1.1.1
PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -A FORWARD -o %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -D FORWARD -o %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = <VPS_PUBLIC_KEY>
Endpoint = <VPS_PUBLIC_IP>:51820
PresharedKey = <KEY>
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
Replace the values <PRIVATE_KEY>, <VPS_PUBLIC_KEY>, <VPS_PUBLIC_IP> and <KEY> with the corresponding values from the peer1 configuration.
And finally, we execute the script:
sudo ./setup-wireguard-client.sh
Step 3: Connect from other devices
Now that we have our VPN tunnel established between the VPS and the Raspberry Pi, we can connect from any device.
Configuration for additional devices
In the VPS, we can obtain configurations for other devices:
# For peer2
cat /config/peer2/peer2.conf
Then we must install the Wireguard client on our device:
- Android/iOS: Download the official âWireGuardâ app from the app store.
- Windows/Mac/Linux: Download the official client from wireguard.com.
Once the client is installed, we simply import the configuration file (.conf) or scan the QR code to connect:
# To show the QR code of peer2 (useful for mobile)
docker exec -it wireguard /app/show-peer 2
Checking the connection
To verify that everything works correctly:
On the VPS
docker exec wireguard wg show
You should see your Raspberry Pi connected.
On the Raspberry Pi
docker exec wireguard-client wg show
You should see the connection to the VPS.
Connectivity tests
From the VPS, try pinging your Raspberry Pi:
ping 10.69.69.2
From the Raspberry Pi, try pinging the VPS:
ping 10.69.69.1
To check access to your home network, connect an additional device to the VPS and try to access a service on your local network. For example, if you have a web server at 192.168.1.100, try accessing it.
Troubleshooting
If you encounter connectivity problems:
-
Check firewall configuration Make sure UDP port 51820 is open on your VPS:
sudo ufw status -
Verify Wireguard interface status On both sides:
ip a show wg0 -
Check routing tables
ip route -
Check Wireguard logs
docker logs wireguard docker logs wireguard-client -
Restart Wireguard services On the VPS:
cd wireguard-cgnat/vps docker-compose down docker-compose up -dOn the Raspberry Pi:
cd wireguard-cgnat/raspberry docker-compose down docker-compose up -d
Conclusion
And thatâs it! Now you have a fully functional VPN that allows you to access your home network from anywhere, even if your internet provider has you under CGNAT.
This solution is:
- Secure: Traffic is encrypted end-to-end.
- Private: You donât depend on third-party services that can access your data.
- Flexible: You can add as many devices as you need.
- Economical: You only pay for the VPS, which can be very cheap or even free.
I hope this guide is useful to you and saves you the same headaches it saved me. If you have any questions or suggestions, you can comment below or visit the repository on GitHub for more information.
Until next time! đ



O que vocĂȘ achou?
Deixe sua opiniĂŁo, pergunta ou sugestĂŁo. Os comentĂĄrios sĂŁo sincronizados com GitHub Discussions .