Create a portable VPN box

Ok here is what I'm aiming for:

I have a RPi 3B, and I want to use a USB WiFi card (MediaTek MT7612U) WiFi to connect as a client to random AP's including ones that have captive portals. I then want to have WireGuard connect to my server and route all traffic. I also want to use the builtin WiFi to generate an AP that my devices connect to and then go across WG for all traffic.

I had it working where I could plug into the Pi via ethernet and was able to connect to WiFi that didn't have any captive portals, but it was finicky and I suspect that was related to WG not liking me moving from network to network.

I have seen the travelmate package as an option to help handle captive portals, but I've also read that just simply trying to browse would also trigger the prompt and I could login that way. However I also think if I can get travelmate working it will help with the changing WiFi networks and wireguard.

I am currently using a 19.0.7 build, I was going to try a snapshot but there is a bug in today's build that isn't applicable to this issue, and I couldn't use uci as a result, so if I need to use a version 20 build, then I'm up for trying that but I will need to get a good build first.

I may have this solved, I will update this in the morning after doing a field test.

Ok, here is what I ended figuring out to get the VPN box working for portable use. I am presuming you have some basic understanding of OpenWRT and WireGuard.
If you are not familiar with how to get WireGuard going, or how to navigate LuCi, then I recommend reading this twice, and be prepared to re-flash the SD card to clean slate.
Also, Google is your friend when it comes to getting WireGuard going, it really does help a lot, and it can be very specific to your needs.

The goal of this project was to make it so I could connect any of my devices back to my WireGuard network at any time.

  1. Connect RPi to a wifi network that is unfiltered, since that can interfere with package acquisition.
  2. Get the travelmate package and all necessary USB adapter packages, mine was the kmod-mt76x2u package which also grabbed all dependencies.
    • I have the Alfa AWUS036ACM USB adapter (Mediatek MT7612u), which as of 1/04/2021 went for ~$40 on Amazon.
  3. After getting the packages, confirm that the adapter is showing up properly in OpenWRT.
    • SSH into the RPi using ssh root@rpiipaddress and once logged in, plug in the adapter and type dmesg.

You will see similar output if it's working:

[ 3287.954678] usb 1-1.4: new high-speed USB device number 5 using dwc_otg
[ 3288.085490] usb 1-1.4: New USB device found, idVendor=0e8d, idProduct=7612
[ 3288.094785] usb 1-1.4: New USB device strings: Mfr=2, Product=3, SerialNumber=4
[ 3288.104463] usb 1-1.4: Product: Wireless
[ 3288.110756] usb 1-1.4: Manufacturer: MediaTek Inc.
[ 3288.117836] usb 1-1.4: SerialNumber: 000000000
[ 3288.224680] usb 1-1.4: reset high-speed USB device number 5 using dwc_otg
[ 3288.355343] mt76x2u 1-1.4:1.0: ASIC revision: 76120044
[ 3288.384375] mt76x2u 1-1.4:1.0: ROM patch build: 20141115060606a
[ 3288.555634] mt76x2u 1-1.4:1.0: Firmware Version: 0.0.00
[ 3288.562120] mt76x2u 1-1.4:1.0: Build: 1
[ 3288.567152] mt76x2u 1-1.4:1.0: Build Time: 201507311614____

  1. Once you've confirmed it can see the adapter, remove all wifi configurations from the RPi.

    • Go to Network, Wireless. In there you should see two WiFi adapters and two configuration settings.
    • The first setting will most likely be the WiFi network you originally connected to, and that needs removed.
    • The second setting will be the USB adapter creating a basic OpenWRT wifi network, but it will be disabled. Also remove that.
  2. At this point, we need to go to Services, travelmate.

    • It will ask to do a one time configuration, do that.
    • Once done, go to Wireless Stations. Pick your original network and configure it.
    • I had to restart travelmate, so go back to the Overview tab and scroll down, hit the red Restart button. May need to repeat a couple of times.
  3. Once you have confirmed that Travelmate is connected to your WiFi, all that is left is setting up WireGuard.

    • I recommend setting this up on a different network than the one that is hosting because you can't test it otherwise.
    • I'm not going to explain the finer points of WireGuard in this guide, that you will need to search for yourself.
    • That said, install the luci-app-wireguard package, and it will grab all dependencies.
    • Reboot.
    • Go to Network, Interfaces. Add a new Interface, select WireGuard VPN. Name it accordingly, make a wg firewall zone, and save it.
    • It should then ask for all the relevant info to get connected. Under Peers, AllowedIPs, I recommend 0.0.0.0/0 and ::0/0 so it will route most traffic across the WG tunnel.
      • I say most traffic because when at my home network I was still able to ping internal LAN IPs, which shouldn't happen but it did.
    • I also went back and deselected "Bring up on boot" because I think it will interfere with getting connected to captive portals, but I will test that.
  4. Last step: Go to Network, Firewall, and for the wg Zone click Masquerading. I also set it to accept Input, Output, and Forwarding since I have appropriate measures in place for wg.

  5. Crack open a beverage of choice, and do a What Is My Ip test. If you have Linux on your computer, use the following in a terminal: dig +short myip.opendns.com @resolver1.opendns.com

    • Up to this point everything should indicate that it's working, and this is the final step to make sure.

Test results:
McDonald's Free WiFi - Had to manually login, didn't bother with scripting the captive portal.
Taco Bell WiFi - Same results as the McDonald's wifi.
Was able to connect to an EAP network and roam from one location to another with a 5-7 minute gap without a reboot. Did not test traveling further going to a third building to see if it glitched.

Final notes:
It appears that switching between ESSID's requires a reboot or a fresh startup. Since in most situations the box will not be on until arrival, this is fine for me. It also appears that just having the WG interface come up at boot up is fine, without any issues. I have tried adding a new AP after a reboot and it worked. This means (based on my limited testing) that you can take it to a new location and start it up, with the WG interface starting on boot and it will work.

For my USB Adapter I had to make a cable that moved it's power pins to a different source (Y cable) so the RPi would stay running properly. I did adjust the WiFi adapter power output to 3mW from full power, so maybe that would be enough to run the adapter without needing a second power connection. The battery pack I am using only supplies 5V @ 2.4A to the RPi, and after looking around the RPi only goes to 2.6A anyways. This means if turning down the WiFi AP power to 3mW doesn't work, then I will need to buy a proper Y cable (mine is definitely DIY) to supply the USB adapter with power. That said, I think doing this on an RPi 4 would be better because of the USB-C power being able to go to 3.4A. Mine is currently in use, so unable to confirm.

Also, I'm not sure if setting the USB adapter further away from the Pi will actually help with speed and latency. I didn't do a formal Speedtest, but anecdotally I noticed it was slower, possibly also due to the distance from the WiFi network I was connected to. Since the USB adapter does support BNC style antennas, it would be possible to put beamforming antennas, and pickup a signal from further away.

Update:

I tried running this on my RPi4 since it has a USB-C port and I thought I would get enough power via that to run the WiFi adapter without needing a splitter cable, but that didn't work. Still needed the cable, and the RPi4 was trying to start the adapter using XHCI and failing to load the firmware, and only really worked without the splitter, so I reverted back to the RPi3 B.

That said, I also updated the RPi3 to the newest snapshot because that allowed for installing Travelmate 2.0, and I wanted to see if it would handle ESSID roaming better in a corporate environment. Unfortunately it didn't resolve that issue, but I did create a short ash script that is run every 3 minutes via crontab to help with this, and I will be testing that tomorrow further since today was not optimal for that.

The issue is that WG for some reason is expecting a network device to always exist, and that device is somehow tied to the BSSID of the AP you initially connected to. So I walked from one end of a building to another and it became disconnected on both 19.0.7 and the newest snapshot (1/13/2021). On the newest snapshot I also noticed that Travelmate 2.0 will eventually reject an AP if it is unable to reliably connect to it, which can be an issue if you don't have access to a browser to fix that while on the go. Not sure if that would happen with Travelmate 1.5.5. Anyhoo, so I noticed that if I did a full reboot after switching BSSID's then it would end up working. I dug around and I couldn't find a wireguard service, but I did see that you can restart the network service.

So here's the ash script that runs every 3 minutes: (arbitrary time, I just wanted something fast enough to not be noticed but not so fast that it would cause the Pi to get stuck looping the network in a never-ending state of restarting.)

if ping -c1 wg_peer_ip_address > /dev/null; then
    echo " "
else
	service network reload
fi

crontab entry:

*/3 * * * * /root/reset-wg.sh

The first part is what determines every 3 minutes. Change the number to fit whatever you think is acceptable.

So TL;DR:
Tried using an RPi4, didn't work for various reasons detailed above. Still using RPi3 B. Updated to newest snapshot as of 1/13/2021. Using Travelmate 2.0 and it's working, mostly. Needed a script to resolve BSSID changes when using it in a roaming environment, posted above.

Seems a bit big to carry around as a portable vpn box. Have you consider GL inet

https://www.amazon.com/GL-iNet-GL-AR300M-Pre-installed-Performance-Programmable/dp/B01I92T754/ref=dp_prsubs_1?pd_rd_i=B01I92T754