Welcome to the new FlexRadio Community! Please review the new Community Rules and other important new Community information on the Message Board.
If you are having a problem, please refer to the product documentation or check the Help Center for known solutions.
Need technical support from FlexRadio? It's as simple as Creating a HelpDesk ticket.

L3 VPN Remote Solution with WireGuard

Options
tzmitch
tzmitch Member
I operate my station remotely only. Currently it is installed at my parents house about 6 miles away from my own, but I am considering moving it to a second home in the mountains of western North Carolina where the only Internet service is a Wireless ISP using Carrier Grade NAT. The router there is owned and controlled by the ISP. The goal of this exercise was to develop a remote solution that is not dependent on SmartLink. SmartLink does not work with CGNAT. Outside of SmartLink, SmartSDR requires broadcasts from the radio to find available radios. This is a design decision they’ve made and, like their approach to remote CW, it’s something I have to figure out how to work around. As much as I don’t like those decisions, I still think the Flex solution is still easier to use than the Elecraft KX3 & RemoteRig solution I used for years before.

There are multiple users and devices at each location so I was unwilling to use one of the L2 bridged VPNs as the filtering and micromanagement of addresses and broadcasts introduced overhead I didn’t want to deal with. Judging from comments, there are plenty of people who have solved this problem before but I had a hard time finding any of those people who thoroughly documented what they did. This is my attempt at documenting how I enabled access to my Flex Radio without SmartLink and without resorting to a layer two VPN. It is based on a WireGuard VPN, a tiny app from HB9FXQ that forwards the UDP broadcasts that enable radio discovery, a couple of static routes and a little bit of TCP tweaking. All of those things run on the Raspberry Pi. The remote site also houses a Windows machine used for radio stuff and with AnyDesk, gives me an alternate method of connecting into the remote network.

I’m using two Rasperry Pi devices:
radiopi, 192.168.1.126, lives at the remote site with the radio
pi-hole, 192.168.86.239, lives at my home and will function as the “server” side

These devices are using reserved DHCP addresses because I find that easier than statically assigning addresses. Each site also has a dynamic DNS entry. Where possible I use hostnames rather than IP addresses.

I installed PiVPN on each Raspberry Pi:
https://www.pivpn.io/

I largely followed the instructions here:
https://pimylifeup.com/raspberry-pi-WireGuard/
and here:
https://www.youtube.com/watch?v=yc9PEM1ovg0

Since I have a reserved IP addresses in the DHCP scope configured on the routers for each Raspberry Pi, I selected Yes when prompted.

I opted for WireGuard rather than OpenVPN when prompted

I used the default 51820 port for WireGuard. On the server/home site router I forwarded this port to the Raspberry Pi at my house.

I am using Pi-hole for DNS on the same Raspberry Pi at my house. The installer recognized that and used it for DNS resolution. I used Cloudflare at the remote site.

After enabling automatic upgrades and such, I rebooted both Raspberry Pi’s

I ran “pivpn add” on the server side Pi and created a profile called “radio.” This doesn’t do a whole lot besides put the correct keys in.

I added a number of things to the radio.conf profile after copying the contents to radio.conf on the remote Pi. 10.6.0.0/24 is the address of the tunnel. This doesn’t exist anywhere. 192.168.86.0/24 is the “server” side. 192.168.1.0/24 is the remote side where the radio lives. This file tells WireGuard to send traffic to 192.168.86.0/24 over the tunnel. The file /etc/WireGuard/radio.conf on radiopi looks like this:

[Interface]
PrivateKey = <private key is here>
Address = 10.6.0.2/24
DNS = 10.6.0.1
MTU = 1420

PostUp = iptables -A FORWARD -i wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

PostDown = iptables -D FORWARD -i wg0 -m state --state RELATED,ESTABLISHED -j ACCEPT; iptables -D FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

[Peer]
PublicKey = <public key>
PresharedKey = <Preshared key>
Endpoint = <remote public address/name>:51820
AllowedIPs = 10.6.0.0/24, 192.168.86.0/24
PersistentKeepalive = 25

The “server” side uses /etc/WireGuard/wg0.conf edited to look like this:

[Interface]
PrivateKey = <private key>
Address = 10.6.0.1/24
MTU = 1420
ListenPort = 51820
### begin radio ###
[Peer]
PublicKey = <public key>
PresharedKey = <presharedkey>
AllowedIPs = 10.6.0.2/32, 192.168.1.0/24
### end radio ###


<end part 1>
Tagged:

Comments

  • tzmitch
    tzmitch Member
    edited November 2021
    Options
    The PostUp and PostDown lines (those are each single lines) fiddle with the TCP Maximum Segement Size and drive it down to match the Path MTU. From what I understand, the MTU setting on the Flex Radio only affects the UDP broadcasts and not the TCP flows. Without this I could discover the radio and connect to it, but would not send me audio or paint the waterfall and would disconnect after several seconds. Packet dumps showed the TCP connections being set up, so I had connectivity but it didn’t last. HB9FXQ also mentioned this being necessary, but his understanding of iptables far surpasses mine to the point that it was difficult for me to know how to apply it (I can adjust MSS on a Cisco device, but not iptables). Fortunately I found someone else doing this with WireGuard and learned that it will apply those lines when the tunnel goes up and down.

    I brought the WireGuard tunnels down and up.
    Radio side:
    wg-quick down radio
    wg-quick up radio

    Server side:
    wg-quick down wg0
    wg-quick up wg0

    The routers at the remote sites needed static route entries that route the remote site via the Raspberry Pi local to it. For example, the router at the radio location needed a static route for 192.168.86.0/24 (my home network) pointing to the address of radiopi, 192.168.1.126.

    At this point I had end to end connectivity. I could, for example, hit the inside address of the router at the radio site from my home PC. It also means that I can connect to Elecraft KAT500 ATU using the internal 192.168.x.x address and do away with the port forwarding on the remote router.

    I used HB9FXQ’s flex6k-discovery-util-go program to forward those pesky UDP broadcasts from the radio:
    https://github.com/hb9fxq/flex6k-discovery-util-go

    This utility will pick up UDP 4992 packets from the radio and forward them to the server side where another copy of the utility dumps them out as broadcasts on the local network where I’m running SmartSDR.

    Radio side:
    ./flex6k-discovery-util-go --SERVERIP=192.168.1.126 --SERVERPORT=7777

    192.168.1.126 is the local ethernet interface of the Raspberry Pi at the radio site.

    On the server/home side:

    pi@pi-hole:~ $ ./flex6k-discovery-util-go --REMOTES=192.168.1.126:7777 --LOCALIFIP=192.168.86.239 --LOCALPORT=7788

    192.168.86.239 is the Raspberry Pi at the house/server site.

    Start both sides and the radio will show up in the chooser without using SmartLink. It only needs to run to find the radio. You can stop it after you connect. You can also do this with socat, but I like Frank’s little program because you get some good feedback from it. It looks like this when it’s working. The radiopi side was started first and receives several broadcasts before the home side registered with it. Once that happens you can see the radio side start forwarding packets to it.


    pi@radiopi:~ $ ./flex6k-discovery-util-go --SERVERIP=192.168.1.126 --SERVERPORT=7777
    APP Identified local IPs: 0.0.0.0 127.0.0.1 127.0.0.1 ::1 192.168.1.126 fe80::864:e4cc:5b46:f278 10.6.0.2
    SRV listening for registrations on: 192.168.1.126:7777
    SRV BROADCAST RECEIVED [192.168.1.10:4992]
    SRV BROADCAST RECEIVED [192.168.1.10:4992]
    SRV BROADCAST RECEIVED [192.168.1.10:4992]
    SRV BROADCAST RECEIVED [192.168.1.10:4992]
    REGISTRATION R;192.168.86.239;7788 from 192.168.86.239:55197
    SRV: Number of regs: 1
    SRV BROADCAST RECEIVED [192.168.1.10:4992]
    ==> Notifying remote [R;192.168.86.239;7788]
    SRV BROADCAST RECEIVED [192.168.1.10:4992]
    ==> Notifying remote [R;192.168.86.239;7788]
    SRV BROADCAST RECEIVED [192.168.1.10:4992]



    pi@pi-hole:~ $ ./flex6k-discovery-util-go --REMOTES=192.168.1.126:7777 --LOCALIFIP=192.168.86.239 --LOCALPORT=7788
    APP Identified local IPs: 0.0.0.0 127.0.0.1 127.0.0.1 ::1 192.168.86.239 2603:6080:280a:6ba8:189e:43f8:5d4f:8ac fe80::3a69:dfc5:5289:98db 10.6.0.1
    ==> Notifying remote [192.168.1.126:7777]
    CLT RECEIVED PKG FROM SRV @ 192.168.1.126
    broadcasting in local subnet
    CLT RECEIVED PKG FROM SRV @ 192.168.1.126
    broadcasting in local subnet
    CLT RECEIVED PKG FROM SRV @ 192.168.1.126
    broadcasting in local subnet
    CLT RECEIVED PKG FROM SRV @ 192.168.1.126
    broadcasting in local subnet
    CLT RECEIVED PKG FROM SRV @ 192.168.1.126

    I need to automate running this program. I haven’t decided how I will do this yet.

    Lastly, configure WireGuard to start the tunnel on the remote side. The wg0 interface comes up automatically on the server side.

    pi@radiopi:~ $ sudo systemctl enable wg-quick@radio
    Created symlink /etc/systemd/system/multi-user.target.wants/wg-quick@radio.service → /lib/systemd/system/wg-quick@.service.
    pi@radiopi:~ $

    With this solution the audio to and from the radio is not compressed like it would be with SmartLink. Still, it’s better than not working at all. A layer two VPN between the sites with many more broadcasts crossing the tunnel would only exacerbate that bandwidth problem. In running it for a day I still get drops with about the same regularity that I do with SmartLink. I think this is largely due to my parents' ISP. It comes and goes. I’ll get a more thorough test with CW Sweepstakes this weekend.

    I hope this helps someone looking to do the same thing.
    73
    Tommy WZ4M
  • Frank, HB9FXQ
    Frank, HB9FXQ Member ✭✭
    edited November 2021
    Options

    To automate the discovery tool on both sides to start on boot, just use systemd.

    I've copied mine to https://gist.github.com/hb9fxq/f4a51f0b3db496792ae02ccb2a038bfb for reference.

  • tzmitch
    tzmitch Member
    Options
    Frank, once again you have been super helpful. I have this on radiopi:

    pi@radiopi:~ $ cat /etc/systemd/system/flexi.service
    [Unit]
    Description=flex radio discovery
    Wants=network-online.target
    After=network-online.target

    [Service]
    ExecStart=/home/pi/flex6k-discovery-util-go --SERVERIP=192.168.1.126 --SERVERPORT=7777
    Restart=always
    RestartSec=10
    StandardOutput=null

    [Install]
    WantedBy=multi-user.target
    pi@radiopi:~ $

    And this on pi-hole at the house:

    pi@pi-hole:~ $ cat /etc/systemd/system/flexi.service
    [Unit]
    Description=flex radio discovery
    Wants=network-online.target
    After=network-online.target

    [Service]
    ExecStart=/home/pi/flex6k-discovery-util-go --REMOTES=192.168.1.126:7777 --LOCALIFIP=192.168.86.239 --LOCALPORT=7788
    Restart=always
    RestartSec=10
    StandardOutput=null

    [Install]
    WantedBy=multi-user.target
    pi@pi-hole:~ $

    I've set these to start automatically using the guide Frank pointed me to here:
    https://www.shubhamdipt.com/blog/how-to-create-a-systemd-service-in-linux/

Leave a Comment

Rich Text Editor. To edit a paragraph's style, hit tab to get to the paragraph menu. From there you will be able to pick one style. Nothing defaults to paragraph. An inline formatting menu will show up when you select text. Hit tab to get into that menu. Some elements, such as rich link embeds, images, loading indicators, and error messages may get inserted into the editor. You may navigate to these using the arrow keys inside of the editor and delete them with the delete or backspace key.