Introduction
Since a friend required this - this is a short write-up on how to use your
RaspberryPi (with FreeBSD) with an UMTS/LTE modem to provide internet
connectivity to your local network. Note that I still do not believe that
itās a good idea to use mobile networks as any way of internet connectivity
(to be fair I donāt see them as being internet connections in most cases
at all). But there might be reasons to do this - for example if youāre
really running a mobile node (If youāre running a system at a fixed
location you should really use a fixed landline - no matter what medium - instead
of a radio based system).
First off. This is of course an do-it-yourself solution and there are plenty
of buy-able ready to use devices out there. The main advantage of doing such
things for by oneself is the flexibility one gains. One can run arbitrary
software on the RaspberryPi (as long as it compiles on the OS thatās going
to be used), one can do fancy network configurations, etc. And one can keep
it up to date by oneself.
Iām going to use FreeBSD as the operating system even on the RaspberryPi. Iām
choosing this over Linux mainly because of personal preference - I like the
long term consistency, the development approach and the adherence to
Unix specifications when implementing base commands. And I like the simplicity
of FreeBSD compared with other platforms - even on the RaspberryPi where the
boot process is done using U-Boot.
Required hardware
Note: Links provided are Amazon affiliate links. Qualified purchases will lead
to some profit for the author of this page (it doesnāt change the price for you).
- Your own computer
- An RaspberryPi including an SD card and an power
supply.
- An LTE modem like the Huawei E3372-LTE. Iām personally
using the E303 in my setups but thatās not available any more.
- An network cable to connect the RaspberryPi to
your network.
- If you want to run your RaspberryPi as a simple WiFi access point you
are currently required to use an external USB WiFi module like
the TP-Link TL-WN725N Nano which is suited for
compact setups or like the Alfa Network, AWUS036NHR
because the internal WiFi module of the RaspberryPi is currently not supported
on FreeBSD (due to lack of documentation for the particular chipset by
the manufacturer - a common problem with WiFi hardware).
Installing FreeBSD on your SD-Card
First one has to install the operating system. One can download the
latest FreeBSD release. One can locate the release on the
FreeBSD download page. Be sure to
use either RPI-B
, RPI2
or RPI3
depending on the hardware
youāre using.
First simply download the image. It comes as an .xz
archive that has
to be uncompressed first. On FreeBSD you can do this with
for the 12.1 Release one could for example simply do
fetch https://download.freebsd.org/ftp/releases/arm64/aarch64/ISO-IMAGES/12.1/FreeBSD-12.1-RELEASE-arm64-aarch64-RPI3.img.xz
unxz FreeBSD-12.1-RELEASE-arm64-aarch64-RPI3.img.xz
On Windows one might use use a tool like 7-Zip. On
Mac OS X one also has the unxz
command (or xz -d IMAGE.xz
) command
available.
After that one has to flash the image onto the SD card. On most Unices this
is done using dd
. This might require root privileges since raw disk
access (i.e. use sudo
) is required because dd destroys potential file system
data on the SD card. Be sure to write to the correct disk. On Unices you can look
into dmesg
output, insert the SD card and immediately look at dmesg
again. Youāll see the device name of the newly attached device (for example adaN
or similar). Now one can use dd
to write the image to the disk:
dd if=IMAGE.img of=/dev/adaN
for the previously mentioned image that would be
dd if=FreeBSD-12.1-RELEASE-arm64-aarch64-RPI3.img of=/dev/adaN
On Windows a tool like Win32DiskImager
might be used to write onto the specific SD card. Be sure to select the
right one again!
On any OS - beware that if you write onto the wrong disk there is no way
of recovering your data!
Now you can insert the SD card into your RasberryPi and do the remaining
configuration either with a local monitor and keyboard or via a (trusted) network.
If you initially boot your RaspberryPi using FreeBSD as operating system it will
use DHCP to get an IP address if this is supported on your network and start
sshd to allow access using either
- The username
raspberry
and password raspberry
- The username
freebsd
and password freebsd
The default root
password (who is not allowed to login via SSH) is
normally set to root
Operating system configuration
Passwords
If you do setup via network please set all passwords to non default values
using the passwd
command first (this is also a good idea when setting
up without a network connection). Once for the user you log in with:
And once for root
after youāve elevated into the root
account:
Setting current date and time
The most simple way of setting date and time is using the network time
protocol. This step is required as soon as some data is downloaded from the
network and signatures or an revision control system is used. If your
system has been attached to an ethernet based network configured via
DHCP you can directly use:
If note one can set the current date and time using date
(note that
the raspberry will loose this information on every reboot since it doesnāt
contain a RTC. Itās possible of attaching one but as long as youāre using
it as internet gateway one can also use ntpdate
automatically on
boot and then itās a good idea to track the current time using ntpd
anyways)
To use the NTP daemon one has to edit /etc/ntpd.conf
. A typical
minimal configuration would look like the following:
tos minclock 3 maxclock 6
server 0.at.pool.ntp.org
server 1.at.pool.ntp.org
server 2.at.pool.ntp.org
server 3.at.pool.ntp.org
restrict default limited kod nomodify notrap noquery nopeer
restrict source limited kod nomodify notrap noquery
restrict 127.0.0.1
restrict ::1
leapfile "/var/db/ntpd.leap-seconds.list"
After that one can launch ntpd using
One can also make that change permanent by adding to /etc/rc.conf
:
Note that ntpd
only adjusts the time if the offset is small enough (i.e.
it only compensates clock drift). To run ntpdate
on bootup after
networks have been configured one can also add
to ones rc.conf
. This should be done on RaspberryPi without an external
realtime-clock since ntpd
wonāt adjust the initial time due to too large
time differences. Note that this requires one to have an network connection
up and running already.
If one wants to set the date and time during normal operation using ntpdate
one has to stop a running ntpd
:
/etc/rc.d/ntpd stop
ntpdate
/etc/rc.d/ntpd start
Also note that that ntpd
is loading a kernel module to deploy a
mandatory access control module that allows ntpd to set the date and time
without running with root privileges at any time.
Connecting to networks
Now itās a good idea to connect yourself to a network. How you do this depends
on your current networking situation. If you have a wired network with internet
connectivity available it might be convenient to use the existing internet
connection to perform the setup steps. If youāve connected your PaspberryPi
to your network during bootup and your network performs auto configuration
it should already be configured using DHCP
(IPv4, DNS servers)
and SLAAC
(IPv6). If not we should first setup the required LTE connection.
In already connected cases you can of course do this later so that you donāt
have to mess around with default routes to perform setup via your faster
landline.
LTE Connection
Preparing your USB dongle
Some USB modems like the one Iām using are announcing themselves as USB
CD devices to allow āeasyā installation of drivers on some operating systems
and are required to be reinitialized so that they can be used as a modem
permanently. This can be done using the usb_modeswitch
utility. To install
that utility one has to have some kind of network connection before doing
the UMTS/LTE setup. Then one can install the tool using
$ su
$ pkg install sysutils/usb_modeswitch
After installation and attachment of the modem one
can use usb_modeswitch
to permanently force the device into
modem mode instead of virtual CD-ROM mode - there is also the possibility
of doing this on every attachment by adding usb_modeswitch into devd or devfs
rules but I wonāt cover this here.
To switch the device into modem mode for Huawei modems temporarily one can use
$ usb_modeswitch -v 12d1 -p 1c0b -M '55534243123456780000000000000011062000000100000000000000000000'
Note that the product and vendor ID might be different. One can list all attached
usb devices using usbconfig
Instead of using some cryptic command one can also look into /usr/local/share/usb_modeswitch/
using ls -l
- if there is a matching vendor and product ID for oneās own
USB modem one can simply use
$ usb_modeswitch -v 12d1 -p 1c0b -c /usr/local/share/usb_modeswitch/12d1:1c0b
to permanently disable virtual CD mode.
On my systems Iām currently using a short rc.init
script - i.e. a file
in /usr/local/etc/rc.d/usbmodeswitch
that performs the modeswitch on
every boot:
#!/bin/sh
# PROVIDE: usbmodeswitch
# REQUIRE: FILESYSTEMS
# BEFORE: ppp
# usb modeswitch script for Huawei modem
# with sysutils/usb_modeswitch
. /etc/rc.subr
name="usbmodeswitch"
start_cmd="usbmodeswitch_start"
stop_cmd=":"
rcvar="usbmodeswitch_enable"
usbmodeswitch_start()
{
/usr/local/sbin/usb_modeswitch -v 0x12d1 -p 0x1f01 -V 0x12d1 -P 0x14dc -M "55534243123456780000000000000011063000000100010000000000000000"
/bin/sleep 10
}
load_rc_config $name
run_rc_command "$@"
This is enabled by the following /etc/rc.conf
entry:
usbmodeswitch_eable="YES"
Setting up PPP
To setup the LTE connection one has to configure pppd
. This daemon
is capable of connecting to various PPP
services (not through
PPTP for DSL Modems, this can be done using mpd5
as described
in one of my previous articles).
Note that you have to do most modifications with root privileges so first
elevate yourself to root
:
First one has to determine which device one is going to use. All devices
that are used to communicate with modems (any many more) will be listed in the
device filesystem at /dev/
. To list the currently available files
one can use
Since we know that our device will be emulating an UART device
via USB we can look only at cuaU
devices.
Most of the USB 3G/4G/5G modems expose multiple serial interfaces for different
functionality so one might have to do some experimentation. In my case itās
the /dev/cuaU0.0
device that is going to be used (and my modem also
exposes the interfaces cuaU0.1
and cuaU0.2
for short message system
and voice communications). Normally these files should already belong to
the uucp
user and dialer
group with read and write permissions
for user and group.
The configuration of pppd
happens primarily via /etc/ppp/ppp.conf
.
Itās segmented into various profiles. To edit the file one can use one
of the many editors available (vi
for more advanced users, ee
might be a better choice for beginners).
Then you can simply use the editor to edit PPP configuration:
On most setups Iām currently using a default configuration like the following:
default:
set log Phase Chat Connect LCP IPCP CCP command Warning Error Alert tun
ident user-ppp VERSION
Without going into to much default this configures the steps taken during
buildup of a PPP session and describes which optional features are supported
and should be used. Now there is a single profile for every network provider
that oneās going to use. For example Iāve configured one for Drei in Austria
using the following settings:
drei:
disable ipv6cp
disable mppe lqr deflate deflate24 acfcomp vjcomp pred1 protocomp
set device /dev/cuaU0.0
# set speed 921600
set speed 115200
set timeout 300
nat enable yes
set dial "ABORT BUSY ABORT \"NO\\sCARRIER\" ABORT \"ERROR\" TIMEOUT 10 \
\"\" \
AT OK-AT-OK \
AT+CFUN=1 OK-AT-OK \
AT+CMEE=2 OK-AT-OK \
AT+CSQ OK \
AT+CGDCONT=1,\\\"ip\\\",\\\"drei.at\\\" OK \
ATD*99***1# CONNECT"
enable dns
resolv writable
set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.255 0.0.0.0
add default HISADDR
This configuration is rather complex:
- It disables the IPv6 control protocol for PPP (since this is not supported
by this specific network provider - as far as I know none of the major providers
in Austria has good IPv6 deployment and the ones who have to use CGN even
there and donāt delegate /48 prefixes to my knowledge up to the day of this
writing).
- It disables compression using deflate since there way a bug with the given
endpoint as well as a bunch of other features that triggered bugs in some
other endpoints of different providers (updated 2022).
- The device is selected to be
/dev/cuaU0.0
with a baud rate of 921600.
- The timeout is set to 5 minutes.
- Then NAT is enabled. This will be required when attaching multiple devices
to the network and when no external NAT logic is used.
pppd
can do this
directly for us. If one needs more fancy configuration like port forwards, etc.
one should of course continue to use natd
and set this property to no.
- Then a dial script is given .This is a sequence of AT commands thatās somewhat
specific to the modem and the network provider but looks similar for nearly
every provider. The only difference for Austrian providers is the domain
name that should be used used in the PDP context (
CGDCONT
). The domain
specifies sets the APN
that is used by your network provider. At the
end ATD
starts the dialing process
- Then we enable
dns
and update the /etc/resolv.conf
file so
local application use the DNS server supplied by the provider and
are capable of resolving domain names.
- At the end the tunnel interface interface gets and ā¦
- ⦠the network provider is added as default route
After this configuration has been saved one can edit /etc/rc.conf
and
add appropriate lines:
ppp_profile="drei"
ppp_nat="YES"
ppp_mode="auto"
If one wants to run pppd
as root:
After saving rc.conf
and leaving the editor one can test the PPP
connection using
If one can connect to the outside world (for example trying to ping www.google.com
)
and everything works one can make the startup of pppd
permanent and
launch it on boot by adding the following to /etc/rc.conf
Now the internet connection is working.
Static ethernet configuration (if needed)
If the gateway box will also be the DHCP server one need to configure the ethernet
interface with a static address. This is again done in /etc/rc.conf
.
To set a static IP address of 10.5.0.1
with an 24 bit netmask (255.255.255.0
)
one might include:
ifconfig_ue0="inet 10.5.0.1 netmask 255.255.255.0"
If one also has an static IPv6 address one should add this (of course with the
correct IPv6 prefix specified):
ipv6_ifconfig_ue0="FFFF:FFFF:FFFF:FFFF::1 prefixlen 64"
Providing DHCP service to the local network (IPv4)
If one wants to use the RaspberryPi also as DHCP server (i.e. the server
that distributed IP addresses and configures DNS servers) to the local network
one should run isc-dhcpd
. This is provided in the net/dhcpd
package
and can be installed using
$ su
$ pkg install net/dhcpd
The configuration is rather simple and happens in /usr/local/etc/dhcpd.conf
The main options Iām normally setting is:
option domain-name
should supply the local domain name (if any). This has
to be a domain name youāre controlling. You should never ever be tempted
to use a suffix like .local
or a domain that youāre not controlling
since that might lead to major problems later on (.local
is for example
used by mDNS)
option domain-name-servers
points to one or more DNS servers. One might
specify public DNS servers here if one doesnāt run a local DNS cache or one
might specify the RaspberryPiās own address - then all clients will
use the RaspberryPi as DNS resolver.
default-lease-time
and max-lease-time
specify the duration
in seconds that an IP address is by default delegated to a client and
of course the maximum time it can be renewed without being re-assigned.
- One has to specify if the server is
authoritative
(if one doesnāt know
what this means this should be the case ā¦)
- And an subnet declaration is required
For example the configuration might look like the following:
option domain-name "example.com";
option domain-name-servers 10.5.0.1;
default-lease-time 1440;
max-lease-time 10080;
ddns-update-style none;
authoritative;
log-facility local7;
subnet 10.5.0.1 netmask 255.255.255.0 {
range 10.5.0.100 10.5.0.200;
option routers 10.5.0.1;
option subnet-mask 255.255.255.0;
option ntp-servers 86.59.113.124;
option time-offset 2;
option broadcast-address 10.5.0.255;
}
As one can see the sample configuration not only configures the range from
which DHCP addresses are assigned but also the default gateway (routers
)
as well as an ntp-server
and an time-offset
(i.e. Timezone).
There are of course many more options one might set - depending on ones own
network (automatic configuration for SMTP servers, domain names, etc.).
One can also add static host declarations for hosts that always should
get the same address assigned (for example when theyāre providing servers).
Itās a nice idea to do this using DHCP too so one only has one central
configuration store:
host hostwithsamplename {
hardware ethernet AA:BB:CC:DD:EE:FF:00;
fixed-address 10.5.0.201;
}
Note that the fixed-address
has not to be included in the DHCP range
specified above! The hardware-ethernet
address is the MAC address of
the device that should be assigned that static address. If oneās also
running an own DNS zone (might be interesting too) one can also use symbolic
names instead of IP addresses for the host configuration - and of course also
for NTP servers, etc.
Then one can add automatic launch of dhcpd to /etc/rc.conf
:
dhcpd_enable="YES"
dhcpd_flags="-q"
dhcpd_conf="/usr/local/etc/dhcpd.conf"
dhcpd_ifaces="ue0"
dhcpd_withumask="022"
dhcpd_chuser_enable="YES"
dhcpd_withuser="dhcpd"
dhcpd_withgroup="dhcpd"
dhcpd_chroot_enable="YES"
dhcpd_devfs_enable="YES"
dhcd_rootdir="/var/db/dhcpd"
Advanced configuration
See for example
If I get some more time Iāll also add either here or (more likely) as separate
posts:
- How to configure a local DNS cache and an recursive resolver
- How to configure the
ipfw
firewall
This article is tagged: