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: