0

I want to use my Pi as a fully fledged wifi and ethernet router. I'll connect an external modem/phone with tethering to it and want to share that internet connection with all devices connected to the same ethernet switch as the Pi as well as to all devices connected to the Pi via its own wifi hotspot. The devices also need to be able to communicate amongst each other and the Pi still needs to be online itself. I know that this has to work, but I keep failing when taking different approaches:

I'm using a Pi 3B with the latest Debian Stretch image, fully updated.

  1. USB tethering works out of the box - the Pi is online.
  2. Using a slightly modified version of this script (basically using usb0 instead of wlan0) allows me to share the connection with other systems on the same network - great!
  3. Now comes the difficult part. I have managed to successfully set up an access point using the many instructions online and hostapd, however I still need a dhcp server without messing up the dhcp client that gets the IP from the tethered phone initially. For example, when preparing to set up the dhcp server, I need to set wlan0 interface to be configured with a static IP, but once I do that, the dhcp client refuses to work and I lose the internet connection.
  • Are you connecting the PI to the phone via USB or via WLAN? You write that USB tethering works and brings the PI online, but changing the wlan0 configuration breaks your connection. You may want to set up an Ethernet Bridge and leave the DHCP to the phone. – RalfFriedl Jun 13 at 20:34
  • I'm connecting the phone using USB. The problem I found is a general one, that the DHCP client dhcpcd will refuse to get an IP address from the phone once ANY interface ist configured to use a static IP (“Not running dhcpcd because /etc/network/interfaces defines some interfaces that will use a DHCP client or static address”), and I have to give the wlan0 interface a static IP so that it can act as an access point. If I understand correctly, you are suggesting to let the phone be the DHCP for the entire network, which sounds fine, but how to do that? – Andreas Hartmann Jun 13 at 20:45
  • Have you tried searching for that message? I found unix.stackexchange.com/questions/501309/… and raspberrypi.stackexchange.com/questions/49502/…. – RalfFriedl Jun 13 at 20:59
1
+50

Seems there are to many components that have to play together: dhcpcd, ifupdown, hostapd and maybe dnsmasq and bridge-utils. I have a suggestion to reduce complexity with using systemd-networkd. It is available by default on Raspbian and has everything built-in, no need to install any additional helpers. Here is a setup with a bridge that I have tested for you:

     (dhcp
    from RPi)       bridge
      ╱    wifi    ┌───────┐
station <~.~.~.~.> │(wlan0)│          usb tether              wan
                   │    br0│RPi(usb0) <--------> modem/phone <───> INTERNET
 laptop <────────> |(eth0) │╲       ╲
      ╲    wired   └───────┘╱      (dhcp
    (dhcp           192.168.50.60  from modem/phone)
   from RPi)

Here in short the steps. First switch over to systemd-networkd:

# disable classic networking
rpi ~$ sudo -Es
rpi ~# systemctl mask networking.service dhcpcd.service
rpi ~# mv /etc/network/interfaces /etc/network/interfaces~
rpi ~# sed -i '1i resolvconf=NO' /etc/resolvconf.conf

# enable systemd-networkd
rpi ~# systemctl enable systemd-networkd.service systemd-resolved.service
rpi ~# ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf

Configure wpa_supplicant as access point. Create this file with your settings for country=, ssid=, psk= and maybe frequency=. You can just copy and paste this in one block to your command line beginning with cat and including both EOF (delimiter EOF will not get part of the file):

rpi ~# cat > /etc/wpa_supplicant/wpa_supplicant-wlan0.conf <<EOF
country=DE
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="RPiNet"
    mode=2
    key_mgmt=WPA-PSK
    proto=RSN WPA
    psk="password"
    frequency=2437
}
EOF

rpi ~# chmod 600 /etc/wpa_supplicant/wpa_supplicant-wlan0.conf
rpi ~# systemctl disable wpa_supplicant.service
rpi ~# systemctl enable wpa_supplicant@wlan0.service

Configure interfaces by creating these files:

rpi ~# cat > /etc/systemd/network/02-br0.netdev <<EOF
[NetDev]
Name=br0
Kind=bridge
EOF

rpi ~# cat > /etc/systemd/network/04-br0_add-eth0.network <<EOF
[Match]
Name=eth0
[Network]
Bridge=br0
EOF

rpi ~# cat > /etc/systemd/network/10-usb0.network <<EOF
[Match]
Name=usb0
[Network]
DHCP=yes
EOF

rpi ~# cat > /etc/systemd/network/12-br0_up.network <<EOF
[Match]
Name=br0

[Network]
Address=192.168.50.60/24
DHCPServer=yes
IPForward=yes

[DHCPServer]
DNS=84.200.69.80 84.200.70.40
EOF

Please ensure that the ip address(range) 192.168.50.60/24 (or whatever do you use) does not match the same subnet that you get from your USB tethering device.

Now we have to tell wpa_supplicant to use a bridge. We do it by modifying its service with:

rpi ~# systemctl edit wpa_supplicant@wlan0.service

In the empty editor insert these statements, save them and quit the editor:

[Service]
ExecStartPre=/sbin/iw dev %i set type __ap
ExecStartPre=/bin/ip link set %i master br0

ExecStart=
ExecStart=/sbin/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -Dnl80211,wext -i%I -bbr0

ExecStopPost=-/bin/ip link set %i nomaster
ExecStopPost=-/sbin/iw dev %i set type managed

At last we need a NAT (network address translation) for the usb0 interface. For this we create a service that is exactly bound to the general network service. Create it with:

rpi ~# systemctl --full --force edit nat.service

In the empty editor insert these statements, save them and quit the editor:

[Unit]
Description=NAT for USB tethering interface
After=systemd-networkd.service
BindsTo=systemd-networkd.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/iptables -t nat -A POSTROUTING -o usb0 -j MASQUERADE
ExecStopPost=-/sbin/iptables -t nat -D POSTROUTING -o usb0 -j MASQUERADE

[Install]
WantedBy=systemd-networkd.service

Enable the new service:

rpi ~# sudo systemctl enable nat.service

Reboot and it should do.


References:
Setting up a Raspberry Pi as an access point - the easy way
Access point as WiFi repeater, optional with bridge

  • Wow, thanks for the effort! I'll try it and report back. – Andreas Hartmann Jun 14 at 14:53
  • @AndreasHartmann It is mostly copy and paste and a bit testing :-) Look at the references. – Ingo Jun 14 at 14:55
  • Thanks, it worked perfectly. I didn't even know systemd could do that. Will reward an extra bounty for this in 24 hours when it's possible. – Andreas Hartmann Jun 16 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.