Connecting your Raspberry Pi to 4G is great – until you realize you can’t directly SSH into it because of CGNAT. But don’t worry, I’ve found a simple solution that lets you access your device remotely and log stats to the internet with ease.
I purchased a 4G dongle for my Raspberry Pi so that I could log stats to the internet from my solar shed. I also wanted to be able to connect via SSH in order to make changes and configure things.

My Raspberry Pi Zero with 4G dongle
I use the ZTE MF833U1 https://amzn.to/3jX5jiQ with a SIM card from 1p mobile which I found to be the cheapest for my low data usage https://www.1pmobile.com/
Solution
The solution that found to be the most reliable was to create a reverse SSH tunnel from the Raspberry Pi to my home network. In my case I have another Raspberry Pi in my house which I created the reverse tunnel into. I can then SSH into that Raspberry Pi and then through the SSH tunnel to the Raspberry Pi in my shed over 4G whenever I like.
If you have a server running somewhere on the internet you could use that to establish your tunnel into instead and skip the dynamic DNS and port forwarding steps.
Dynamic DNS
Rather than rely on a particular IP address for my home network I signed up to https://www.noip.com a free dynamic DNS service. I then configured my Netgear router to update my IP address with No-IP.
Port forwarding
The next step was to set up port forwarding on my router from port 22 for SSH to my raspberry Pi inside of my house. I could then connect via SSH to the Raspberry Pi from outside of my house from any device. It is important to set a secure password at this point.
SSH keys
For the SSH tunnel to work without a prompt for a password I set up SSH keys at this point creating a public and private key on my shed’s Raspberry Pi and then adding the public key to my home Raspberry Pi’s authorized keys file. I could test this was working by connecting via SSH from that Pi to my home and checking that there was no prompt for a password.
ssh-copy-id -i ~/.ssh/id_rsa pi@your-no-ip-hostname
Systemd service
At this point I created a service on my shed Raspberry Pi /etc/systemd/system/sshtunnel.service
[Unit]
Description=Service to maintain an ssh reverse tunnel
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=0
[Service]
Type=simple
ExecStart=/usr/bin/ssh -qNn \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
-o ExitOnForwardFailure=yes \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/dev/null \
-i /etc/sshtunnel/id_rsa \
-R 9001:localhost:22 \
-v \
pi@your-no-ip-hostname -p 22
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
I installed this service to run on startup with the command
sudo journalctl -u sshtunnel
The connection now will always re-establish itself if it drops out.
All done!
From this point connecting to the shed Raspberry Pi over SSH is as simple as connecting to my home Raspberry Pi then running
ssh pi@127.0.0.1 -p 9001
And that’s it!
Occasionally the port will get stuck and you will have to kill it to re-establish the connection. You can do this by running on the server being connected to by the tunnel (in my case the Raspberry Pi in my home) the following command to find the process running on port 9001 and then killing that process with the kill command.
sudo lsof -i -P -n | grep LISTEN