Sometimes it can be useful to have an out of band way to monitor and/or SSH into your Raspberry Pi - for example when the normal internet connection has issues.
Waveshare has an interesting NB-IoT / Cat-M Pi Hat using a SIM7000E module for LTE wireless connectivity. While this doesn't give you amazing data rates, it is enough to perform some monitoring and do manual SSH debugging.
The setup I wanted to go for is a Wireguard tunnel that can use the LTE connection
if available. The way this works is via a PPP connection like any other modem. For this,
we need to apt install ppp pppconfig wireguard
. You can run pppconfig
to set up some
default config - it doesn't really matter what settings you choose as we will overwrite
them again.
PPP Config
First up is /etc/ppp/options
. My provider does not require any authentication (if yours does,
you can find plenty of PPP config examples on the internet):
ttyAMA0
115200
lock
nocrtscts
modem
passive
novj
nodefaultroute
noipdefault
noauth
hide-password
persist
holdoff 10
maxfail 0
debug
We'll also change /etc/ppp/peers/provider
to use these options and a chatscript:
file /etc/ppp/options
connect "/usr/sbin/chat -v -f /etc/chatscripts/provider"
The chatscript goes in /etc/chatscripts/provider
:
# Abortstring - responses that indicate errors
ABORT BUSY ABORT 'NO CARRIER' ABORT VOICE ABORT 'NO DIALTONE' ABORT 'NO DIAL TONE' ABORT 'NO ANSWER' ABORT DELAYED
# Send AT so the modem autobauding can detect the baud rate
'' AT
# Set result mode
'OK' 'ATQ0'
# Reset settings to defaults
'OK-AT-OK' 'ATZ'
# Query some modem and network debug info for the log
OK ATI;+CSUB;+CSQ;+COPS?;+CGREG?;&D2
# Set Cat-M mode
OK AT+CMNB=1
# Set LTE only
OK AT+CNMP=38
# Set the APN
OK AT+CGDCONT=1,"IP","internet",,0,0
# Dial
OK ATD*99#
Since my provider only supports Cat-M but not NB-IoT, I'm forcing the modem to use it. You can also remove the corresponding line or change it to NB-IoT (see the SIM7000E datasheet for valid values)
You should now be able to run pon
to establish a connection. Log messages appear in
/var/log/messages
. After the connection is established, you should see a ppp0
interface.
Test your connection:
# ping -I ppp0 8.8.8.8
PING 8.8.8.8 (8.8.8.8) from 10.4.73.208 ppp0: 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=58 time=297 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=58 time=82.9 ms
Transfer Speed
The configuration above is relatively simple and just uses the maximum autobaud speed of 115200 baud. This will likely limit your throughput below what LTE can do. The SIM7000E supports higher baud rates, but you have to manually switch the rate through AT commands.
For example, you could send AT+IPR=921600
to the modem and update /etc/ppp/options
accordingly to achieve higher speeds. You can't do this through the chatscript though as it
would have to switch speeds in the middle.
Autostart on Boot
You can for example use a custom systemd unit to start the connection on boot.
Wireguard
The wireguard setup is pretty much standard with the addition of an FwMark
, so my
configuration looks something like this in /etc/wireguard/wg0.conf
:
[Interface]
PrivateKey = YOURKEY
Address = 192.168.2.2/24
FwMark = 51821
[Peer]
PublicKey = YOUR_SERVER_PUB_KEY
AllowedIPs = 192.168.2.1/32
Endpoint = YOUR_SERVER_IP:51821
PersistentKeepalive = 600
What the FwMark
lets us do is selectively route the encrypted Wireguard packets
through ppp0
when it's up (and via the normal gateway otherwise) by using a
new kernel routing table and sending packets with the mark there.
PPP has hooks we can use to activate the config when the interface goes up/down.
/etc/ppp/ip-up.d/wireguardroute
:
#!/bin/sh
# Reset routing table 10 to empty
ip route flush table 10
# Table 10 should send per default via ppp0
ip route add default table 10 dev ppp0
# And we'll use the fwmark to send wireguard traffic there
ip rule add fwmark 51821 table 10
/etc/ppp/ip-down.d/wireguardroute
:
#!/bin/sh
ip rule del fwmark 51821 table 10
ip route flush table 10
Use wg-quick
as usual to manage the interface.
Resetting the SIM7000E
If you have issues during testing or want to do some sort of watchdog reset, you can avoid having to unplug the whole thing by using the on/off control pin wired through to the Pi. For example in Python:
#!/usr/bin/env python
import time
import RPi.GPIO as G
G.setmode(G.BCM)
G.setup(4, G.OUT)
G.output(4, True)
time.sleep(2)
G.output(4, False)