2

Background: Linux is moving inexorably toward systemd for better or worse, and the challenge here is to create a local area network of two or more raspberry pis, and give them all access to the internet. The primary issue is that "access to the internet" can mean several things. The system I have in mind has several use-cases:

use-case 1: I have a headless rpi that is hard to get to - in the back of a cupboard or on a robot say - and I want to be able to ssh to it from another raspberry pi which has a screen and a gui. Let's call the headless machine robotNo7, and the second machine robotBase. Although I know what an IP address is, it would be nice to be able to ssh or VNC using the machine's name. For instance ssh pi@robotNo7.

use-case 2: I want to up date raspbian on the headless pi or perhaps download pigpio to it.

use-case 3: similarly I want to browse the internet from robotBase or perhaps upgrade robotBase.

Note that I do not need, or want, to be able to ssh to the headless pi from some arbitrary machine on the internet. Also the headless machine might or might not be accessible from another machine connected to robotBase. Note also that it is essential that I can connect from robotBase to robotNo7 without robotBase connected to the internet.

I have set this up before based on the instructions on the rpi foundation website for setting up an access point. These instructions are a little confusing and in need of an update, and for the life of me I cannot figure out what I need to change on the old robotBase so that I can use a usb tether from my mobile phone rather than the ethernet cable. Starting again, how would this be done today? Should be easy no?

Setting this up with systemd

I have worked through all of the alternatives listed here and concluded that what I need is a accesspoint with eth0 (usb0) and NAT. This does not give me a DNS service on the local network (I am running raspbian buster on a pi 3 B). I thought it would, and I thought all the bits were there to do it. How can I set it up so I can ping robotNo7 from the robotBase?

Petr
  • 117
  • 1
  • 9
  • 1
    As @Milliways said, you can do it by a lot of network managers. However, you can follow the procedure of this answer. It's easy than the way you have done. https://raspberrypi.stackexchange.com/a/106878/44221 – M. Rostami Jan 06 '20 at 00:04
  • 1
    I do not understand your problem. You have already read my tutorial. Just follow section ♦ Setting up a stand alone access point there for robotNo7 and you are done. Then just connect to it by WiFi from robotBase. – Ingo Jan 06 '20 at 21:33
  • 1
    Nearly all setups silently assume that you have an internet router available that connects you to your internet provider. All of this router are working as hotspot so you can connect to it by WiFi. Most of them also have additional wired ports. The access points we are talking about are intended to extend the range of the internet hotspot. They are connected to the hotspot either by wire (eth0) or using the wireless path. Therefore they are also called repeater. Do you have an internet router available? If not how do you want to connect to the internet? – Ingo Jan 08 '20 at 17:30
  • 1
    M.Rostami yes, and as I said I have done it before using the official approach, but I wanted to try the systemd approach. – Petr Jan 09 '20 at 11:34
  • 1
    Ingo your original post was really good, but unless the reader knows what an "access point," a "NAT" and other networking terms actually are, it is quite hard to decide which set-up is required. I have given three use-cases describing what I want to do (in terms of ssh, ping, vnc etc - things I, your reader, know about) and the stand alone access point with WiFi from the robotBase doesn't satisfy use-case 2. In this use-case there is no internet router available. Editing /etc/hosts seems to me to be cludge, and my question is whether there is a better way with systemd. – Petr Jan 09 '20 at 11:44
  • 1
    Please address me with @Ingo, otherwise I won't see your reply. Again: do you have an internet router available? If not how do you want to connect to the internet? – Ingo Jan 10 '20 at 10:15
  • 1
    @Ingo sorry for the delay - still not sure I have successfully merged my accounts. Most of the time I do not have internet access as all I want is robotBase to provide a screen and GUI for my headless robot. When I do want internet access, the phone is (presumably) the router. However, when the phone is not connected, I still want to "network" the two machines. – Petr Jan 16 '20 at 10:16

3 Answers3

3

The easy way to make this work is to bypass the domain name server and simply use

 # arp -a

to list the IP addresses of all connected machines on the local area network (can take a minute or two to find them) and then edit /etc/hosts and add (something like)

192.168.4.32  robotNo7
192.168.4.152 myToshibaLaptop

to the end of the file. Note the names on the right hand side might be the host name on the machine, but it is the network's name for the machine and can be anything (without spaces etc). So far this seems pretty stable over reboots.

Petr
  • 117
  • 1
  • 9
  • You cannot list the IP addresses of all connected machines on the local area network with arp. You can only mange the local arp cache with it that only maps the mac address to the ip address of the connections in the last 5 minutes. – Ingo Jan 16 '20 at 21:59
3

We have to configure name resolution with systemd. I will use this question to show how to use systemd-resolved for this. To match all your conditions (use-case 1 to 3) I will make robotBase the main access point (5) of your local network so robotNo7 and other devices can connect to it and communicate among each other and get access to the internet. To be a bit more generic I will name the uplink to the internet modem/router eth0. It shouldn't make a difference renaming it to usb0 if using usb tethering.

Tested with
Raspbian Buster Lite 2019-09-26 on a Raspberry Pi 4B updated at 2020-01-18.
Updates done with sudo apt update && sudo apt full-upgrade && sudo reboot.

systemd-resolved provides name services by Domain Name System (DNS) (including DNSSEC and DNS over TLS), Multicast DNS (mDNS) and Link-Local Multicast Name Resolution (LLMNR).(1)

systemd-resolved provides network name resolution to local applications via a D-Bus interface, the resolve NSS service (libnss-resolve), and a local DNS stub listener on 127.0.0.53 (1), (2). For all three software interfaces there are also traditional services installed which may conflict with systemd-resolved. On my tests I have seen problems in the order of name resolution: long response time depending on the amount of DNS server to use, queries for the .local domain going to DNS server, no responses to local host names if the internet connection was down and so on. So I will deinstall not needed services instead of only disable them. This should ensure that entries in common used static config files like /etc/nsswitch.conf will also cleaned up.


♦ General setup

Enable systemd-networkd

For detailed information look at (6). Here only in short. Execute these commands:

# deinstall classic networking
rpi ~$ sudo -Es
rpi ~# apt --autoremove purge ifupdown
rpi ~# rm -r /etc/network
rpi ~# apt --autoremove purge dhcpcd5
rpi ~# apt --autoremove purge isc-dhcp-client isc-dhcp-common
rpi ~# rm -r /etc/dhcp

# enable systemd-networkd and systemd-resolved
rpi ~# systemctl enable systemd-networkd.service systemd-resolved.service

Check D-Bus software interface

I haven't found any conflicting issues. The D-Bus should be installed by default and running. Check with:

rpi:~ # systemctl status dbus.service

Configure NSS software interface

There is the avahi service together with the mdns service definitely conflicting, so we have to deinstall them. This will also clean up /etc/nsswitch.conf:

rpi ~# apt --autoremove purge avahi-daemon

Now install the systemd-resolved software interface:

rpi ~# apt install libnss-resolve

Configure DNS stub listener interface

Here we have to symlink /etc/resolv.conf to the stub listener:

rpi ~# ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf

Finished General setup. Go back.


♦ Setup robotBase (access point)

Do ♦ General Setup to configure systemd-resolved name resolution. Then

Configure wpa_supplicant as access point

To 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
    frequency=2437
    key_mgmt=WPA-PSK
    proto=RSN WPA
    psk="password"
}
EOF

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

Setup network interfaces

Create these two files:

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

rpi ~# cat > /etc/systemd/network/08-wlan0.network <<EOF
[Match]
Name=wlan0
[Network]
Address=192.168.4.1/24
MulticastDNS=yes
IPMasquerade=yes
DHCPServer=yes
[DHCPServer]
DNS=84.200.69.80 1.1.1.1
EOF

The address 192.168.4.1/24 defines the subnet 192.168.4.0/24 for the WiFi network. Have attention that it is different from the subnet used by the internet modem/router given to eth0 by DHCP.

Reboot.

Check the status with:

rpi ~$ resolvectl status
Global
       LLMNR setting: yes
MulticastDNS setting: yes
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes
--- snip ---

Link 3 (wlan0)
      Current Scopes: LLMNR/IPv4 LLMNR/IPv6 mDNS/IPv4 mDNS/IPv6
DefaultRoute setting: no
       LLMNR setting: yes
MulticastDNS setting: yes
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes

Link 2 (eth0)
      Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
DefaultRoute setting: yes
       LLMNR setting: yes
MulticastDNS setting: no
  DNSOverTLS setting: no
      DNSSEC setting: allow-downgrade
    DNSSEC supported: yes
  Current DNS Server: 84.200.69.80
         DNS Servers: 84.200.69.80
                      1.1.1.1

♦ Setup robotNo7 (station)

Do ♦ General Setup to configure systemd-resolved name resolution. Then

Configure WiFi client connection

Create these two files:

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"
    key_mgmt=WPA-PSK
    proto=RSN WPA
    psk="password"
}
EOF

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

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

Reboot.


♦ Check name services

Now from a network device, here on robotBase, you can check the three name services DNS, MulticastDNS and LLMNR with resolvectl as follows:

rpi ~$ resolvectl query google.com
google.com: 172.217.169.14                     -- link: eth0

-- Information acquired via protocol DNS in 79.9ms.
-- Data is authenticated: no

rpi ~$ resolvectl query robotNo7.local
robotNo7.local: fe80::217:9aff:feb9:6ea9%3         -- link: wlan0

-- Information acquired via protocol mDNS/IPv6 in 124.5ms.
-- Data is authenticated: no

rpi ~$ resolvectl -4 query robotNo7.local
robotNo7.local: 192.168.4.253                      -- link: wlan0

-- Information acquired via protocol mDNS/IPv4 in 205.1ms.
-- Data is authenticated: no

rpi ~$ resolvectl query robotNo7
robotNo7: 192.168.4.253                            -- link: wlan0

-- Information acquired via protocol LLMNR/IPv4 in 123.4ms.
-- Data is authenticated: no

rpi ~$ ping -c3 robotNo7
PING robotNo7 (192.168.4.253) 56(84) bytes of data.
64 bytes from robotNo7.local (192.168.4.253): icmp_seq=1 ttl=64 time=5.47 ms
64 bytes from robotNo7.local (192.168.4.253): icmp_seq=2 ttl=64 time=1.40 ms
64 bytes from robotNo7.local (192.168.4.253): icmp_seq=3 ttl=64 time=2.51 ms

rpi ~$ ssh pi@robotNo7.local hostname
pi@robotNo7.local's password:
robotNo7
rpi ~$


References:
(1) - archlinux - systemd-resolved
(2) - freedesktop - systemd-resolved — Network Name Resolution manager
(3) - freedesktop - What is D-Bus?
(4) - archlinux - Domain name resolution
(5) - Setting up a Raspberry Pi as an access point - the easy way
(6) - Howto migrate from networking to systemd-networkd with dynamic failover

Ingo
  • 42,107
  • 20
  • 85
  • 197
0

Linux is moving inexorably toward systemd

No it isn't - this happened years ago.

Just because an OS uses systemd DOES NOT mean you have to use systemd-networkd - indeed I am unaware of ANY popular distro that does (Ubuntu server does, but not its desktop systems).

There are at least a dozen different network managers in use on Linux.

Raspbian uses dhcpcd - but use whatever is normal for your chosen OS.

Milliways
  • 59,890
  • 31
  • 101
  • 209
  • Thanks Milliways, I have added a reference to the recent decision by the Debian community to support systemd. Note also I did say that I knew about other ways to do it, but wanted to try systemd based on Ingo's excellent original question and answer. – Petr Jan 09 '20 at 11:47