Port-forwarding Helium port via VPN (fixing the Relayed issue)
Everybody involved in the Peoples’ network at some point in time struggled with this topic. Some managed to get this through fairly easily by fixing their gateway’s settings or following simple tutorials, but some others haven’t managed till today due to network or ISP restrictions. As a bonus feature, following this tutorial will also allow you to see and manage your device remotely!
In order for the router/miner to be able to communicate with its peers and serve its duty consistently it has to be reachable from the “outside” using the port 44158. Normally, this only requires a static IP and a port-forwarding rule in the router. There are various tutorials and manuals available online for all major router manufacturers.
However, there are cases that the ISPs restrict access to specific ports, or there is a NAT setup in front of your Helium device’s network. This includes of course remote installations that operate using mobile networks. In that case, port-forwarding is either not working, or not an option.
I faced this problem myself when relocated my Helium device into a different location and managed to solve it by port-forwarding the port 44518 through a VPN tunnel. In my specific setup I had the OpenVPN server setup at home, but the same can be done on a remote virtual server (EC2/ Azure/ gCloud/ etc). On the miner side I had a Raspberry Pi routing the traffic through the tunnel. My current configuration looks as follows:
Below are the instructions on how to achieve a similar setup. In my case I had to port-forward 44158/TCP and 1194/UDP (OpenVPN port) from my home router to the VPN server. In case you deploy this on a Cloud server you should configure the managed firewall instead and use the instance’s public IP or a TCP load balancer.
Setting up PKI and OpenVPN
In order for our Raspberry Pi to authenticate against the OpenVPN server we would need to set up our PKI (Public Key Infrastructure). Let’s install the packages and go ahead with configuration.
## Server
## first of all let's high up our privileges$ sudo su
Install the required packages:
## Installing the packages # apt update && apt install -y git openvpn openssl
Set up PKI with easy-RSA:
# cd /etc/openvpn/
# git clone https://github.com/OpenVPN/easy-rsa
# cd easy-rsa/easyrsa3# ./easyrsa init-pki
# ./easyrsa build-ca nopass ## (press enter to all prompts)# ./easyrsa gen-req myserver nopass ## (press enter to all prompts)
# ./easyrsa sign-req server myserver ## (type yes and press enter)
# ./easyrsa build-client-full pi nopass
# ./easyrsa gen-dh# openvpn --genkey --secret ta.key
OpenVPN server config as follows:
## /etc/openvpn/server/myserver.conf port 1194
proto udp
dev tun
ca /etc/openvpn/easy-rsa/easyrsa3/pki/ca.crt
cert /etc/openvpn/easy-rsa/easyrsa3/pki/issued/myserver.crt
key /etc/openvpn/easy-rsa/easyrsa3/pki/private/myserver.key
dh /etc/openvpn/easy-rsa/easyrsa3/pki/dh.pem
topology subnet
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
keepalive 10 120
tls-auth /etc/openvpn/easy-rsa/easyrsa3/ta.key 0
cipher AES-256-CBC
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
log-append /var/log/openvpn.log
verb 3
explicit-exit-notify 1
client-config-dir ccd
This config has the following important properties:
- OpenVPN server listening at port 1194/UDP
- The VPN subnet will be 10.8.0.0/24
- All traffic will be routed through the VPN tunnel (including access to the internet)
Last but not least on that, we would need our client (pi) to have a static IP thus we create a rule on the VPN server:
## Setting a static IP for our client (raspberry pi)# mkdir /etc/openvpn/server/ccd && cd /etc/openvpn/server/ccd/
# echo "ifconfig-push 10.8.0.100 255.255.255.0" > pi
The above means that every time our Raspbery Pi will connect it will get the static IP 10.8.0.100
. We should not forget to enable ip_forward
on the VPN server:
# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# sysctl -p
Finally starting up the VPN server and making sure it starts on boot:
# systemctl enable --now openvpn-server@myserver.service
## Server external static IP configuration
This step can be skipped in case the VPN server deployment is in the cloud. In that case the server or load balancer will have a static IP by default which will be accessible over the internet and can then be used by our raspberry pi openvpn config.
If you deployed the OpenVPN server in your home computer/server, then the external/internet IP provided by your ISP might change over time. Depending the ISP policy, it can change once a week/month/day. It’s unpredictable. Thus we need a way to reach our VPN server regardless. For this we are going to create a Dynamic DNS entry on one of the popular DDNS free services. I am not going into details here, but I recommend using a service like ddns.net. They also provide windows, linux and mac packages for updating your IP automatically using a pre-defined interval.
## Client
Now let’s move at the client side (Raspberry Pi). We would need to install openvpn and configure it.
Again, I won’t go into a lot of details on first setup of the rPi. There are tons of manuals on the internet on how to get started with the Raspbian OS. What I really recommend is to connect the pi to your WiFi and also include the WPA credentials for allowing you access to the target location. I use wpa_supplicant
for this and worked great with the latest versions of rPi. Example as follows:
## put this at the bottom of /etc/wpa_supplicant/wpa_supplicant.confnetwork={
ssid="FRITZ!Box 7560 BD"
psk="***********"
key_mgmt=WPA-PSK
}
After restarting the service or the device itself it should connect to your wifi. You can have multiple networks defined there and the pi will connect to the one it finds. Let’s now continue with the rest of the installation.
$ sudo su
# apt update && apt install -y openvpn openssl
Next, we need to move the following files from the PKI directory (the one we just created on the server) to the client (rPi) in /etc/openvpn/client/
.
- /etc/openvpn/easy-rsa/easyrsa3/ta.key
- /etc/openvpn/easy-rsa/easyrsa3/pki/ca.crt
- /etc/openvpn/easy-rsa/easyrsa3/pki/issued/pi.crt
- /etc/openvpn/easy-rsa/easyrsa3/pki/private/pi.key
And put the following client config in /etc/openvpn/client/pi.conf
:
## /etc/openvpn/client/pi.confclient
dev tun
proto udp
remote myserverpi.ddns.net 1194 ## CHANGE ME!!
resolv-retry infinite
nobind
user nobody
group nogroup
persist-key
persist-tun
ca ca.crt
cert pi.crt
key pi.key
remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-CBC
verb 3
Note that the myserverpi.ddns.net
is the free DNS name we registered in the dynamic DNS service.
Finally we start the VPN service on the client and we enable it to start on boot:
# systemctl enable --now openvpn-client@pi.service
After successfully starting the service we have our VPN tunnel created and all the traffic originating from the raspberry PI goes through there.
Port Forwarding through the tunnel
Now the tricky part. This requires a lot of iptables
magic but I will put here what is required — so don’t worry.
## IPTables on server
We first need to tell to our OpenVPN hosting-server that whatever traffic comes to port 44158/TCP
should be forwarded through the VPN tunnel to our rPi. As we defined in the server’s config, the pi should have the static IP of 10.8.0.100
. For the server part I assume that the primary interface of the server (the one that is giving it internet access) is eth0
and the tun interface of the VPN tunnel is tun0
. Feel free to change it as needed:
iptables -A INPUT -i eth0 -m state --state NEW -p udp --dport 1194 -j ACCEPTiptables -A INPUT -i tun0 -j ACCEPTiptables -A FORWARD -i tun0 -j ACCEPTiptables -A FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPTiptables -A FORWARD -i eth0 -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPTiptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADEiptables -A OUTPUT -o tun0 -j ACCEPTiptables -t nat -A PREROUTING -d <vpn-server-IP> -p tcp --dport 44158 -j DNAT --to-dest 10.8.0.100:44158iptables -t nat -A POSTROUTING -d 10.8.0.100/32 -p tcp -m tcp --dport 44158 -j SNAT --to-source 10.8.0.1iptables -I FORWARD 1 -d 10.8.0.100 -p tcp --dport 44158 -j ACCEPT
Very good, so far all traffic reaching our server to the Helium port 44158 it will be pushed to the Raspbery pi which is located at the other side of the VPN tunnel. One more thing we need to do is to save the iptables configuration so it persists reboots:
# apt install -y iptables-persistent ## (select "save" on prompt)
Let’s move now to the rPi side.
## Raspberry Pi as router
Now that we are finished with the VPN tunneling, we need to configure the pi to route traffic to and from the Helium miner.
The rPi has two network interfaces and the connections we must currently have are:
- pi connects to the internet via WiFi
- pi connects to helium miner via Ethernet cable
In our target scenario the miner will get its internet access from the rPi. The rPI then will forward the traffic through the internet to the VPN tunnel. This means we need to set up our pi as a router.
Let’s start by enable IP forwarding:
## Enable IP forwarding# echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
# sysctl -p
Then we should add a static IP to its wired interface. Add the following in /etc/dhcpcd.conf
:
## /etc/dhcpcd.conf (append to the end) interface eth0
static ip_address=192.168.200.1/24
static domain_name_servers=1.1.1.1 8.8.8.8
Then we need the pi to act as a DHCP server itself. For this we are using dnsmasq
:
# apt install -y dnsmasq
And add/change the following configuration in /etc/dnsmasq.conf
:
## /etc/dnsmasq.confinterface=eth0
dhcp-range=192.168.200.50,192.168.200.99,12h
server=1.1.1.1
server=8.8.8.8
dhcp-host=XX:XX:XX:XX:XX:XX,192.168.200.10 ## CHANGE ME!!
The last line is extremely important, as we say that our miner should get a static IP, which we then can use for our port forwarding. You should replace the XX:XX:XX:XX:XX:XX
with the MAC address of the ethernet interface of your miner. It can be found on the diagnostics page.
After that, do not forget to restart the dhcpd and dnsmasq services:
# systemctl restart dhcpcd.service
# systemctl enable --now dnsmasq.service
## IPTables on client (Raspberry Pi)
So far we got our port forwarded up to the rPi through the tunnel, let’s now push it further to our miner:
# iptables -F # iptables -t nat -F # iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE# iptables -A FORWARD -i tun0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT# iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT# iptables -t nat -A PREROUTING -d 10.8.0.100 -p tcp --dport 44158 -j DNAT --to-dest 192.168.200.10:44158# iptables -I FORWARD 1 -d 192.168.200.10 -p tcp --dport 44158 -j ACCEPT
And again, save the iptables configuration:
# apt install iptables-persistent ## (select "save" on prompt)
Now you can connect your Helium miner in the ethernet port of the rPi. All traffic should go through the VPN tunnel, and most importantly, the port 44158
will be open and your miner won’t be relayed anymore!
Bonus point — health checking
I have noticed that the tunnel some times shuts down on the client side and since I am located far away I lose access. I did a simple trick for this; I have installed a web server on the VPN server box which is being called every 5 minutes from the pi through the VPN. In case the pi can’t reach the server anymore it simply reboots.
## on the server# apt install -y nginx
# systemctl enable --now nginx.service
## on the rPi# sudo crontab -e ## add the following line to the root user's crontab
*/5 * * * * /usr/bin/curl --connect-timeout 5 http://10.8.0.1/ && echo "up" || /usr/sbin/reboot
And that was it! Let me know if I forget anything or did not explain something good enough, and of course for possible mistakes or issues you might have found!
Cheers!
If you liked my post I would appreciate a small tip to pay for my coffee when writing the next one :)
HNT: 14oW65UwN3BbDQk1jJPTUNtVo14VUvkXkA9wXDQRERhEJegVRNz
BTC: 31k9WwhbsuZAsnNuAuyq43jE3jHZ5G9XMB
ETH: 0xF9342A946FFD75ecA0AA0AC19a844980e9dCC072