Automate network configurations with dispatcher scripts

Dispatcher

© Lead Image © Hannu Viitanen, 123RF.com

© Lead Image © Hannu Viitanen, 123RF.com

Article from Issue 239/2020
Author(s):

Use dispatcher scripts to mount a different network drive depending on the location or automatically start a VPN connection without lifting a finger.

Yesterday at a conference, today at a downtown office, tomorrow at a home office, the next day at an Internet cafe: Working life is no longer limited to a single desk. For many employees, a reliable Internet connection is all that is needed for a productive work day.

Although working from the road sounds simple, life on a laptop is often full of pitfalls and complications. On your home LAN, you will want to mount the file shares from your NAS, and on the open WiFi network of a cafe, you need a firewall to block all access. In the secure office, services that run locally are allowed to broadcast.

These different network-access use cases require continual adjustments. If a computer only connects to the network via a single wired Ethernet port, you can still mount a network drive via /etc/fstab, or you will want to use autofs if the desired server is not always connected to the network. But to start and stop services automatically depending on the situation, or to have certain configurations created automatically, you need an intelligent network manager.

You don't have to search long for this kind of smart network management: Most distributions have the right tool on board in the form of NetworkManager (Figure 1). As a user, you only have to configure dispatcher scripts for the service. Depending on the currently active network connection, the automatic setup does the rest and executes any scripts automatically when you open or close a connection. However, setting up these functions requires some know-how, and there is no graphical user interface (see the "Configuration Note" box).

Configuration Note

Depending on the distribution you use, the /etc/NetworkManager/dispatcher.d/ folder might already contain dispatcher scripts. Ubuntu, for example, comes with the 01-ifupdown script in place. These files should never be deleted or modified in order to avoid interfering with NetworkManager's functions.

Figure 1: The console program nmcli acts as the central control tool for NetworkManager.

Writing Dispatcher Scripts

The NetworkManager dispatcher function searches in the /etc/NetworkManager/dispatcher.d/ folder for scripts it should process. It then executes the scripts in alphabetical order when a connection is established and in reverse alphabetical order when a network connection is terminated. (If you want NetworkManager to process a script independently, see the "Impatient" box.) For better organization, your own scripts' file names should ideally be preceded by a number, like 30-mount-diskstation. You also need to ensure that the scripts belong to the root user and the root group and are executable. For example, you could create a script like the one shown in Listing 1.

Impatient

The no-wait.d/ folder in /etc/NetworkManager/dispatcher.d/ is for dispatcher scripts that you want NetworkManager to process independently of the order. NetworkManager will execute the scripts stored there immediately after a change in the network status, no matter which other scripts are still active.

Listing 1

Dispatcher Script

$ cd /etc/NetworkManager/dispatcher.d
$ sudo touch 30 mount diskstation
$ sudo chown root:root 30-mount-diskstation
$ sudo chmod 755 30 mount diskstation

A simple script like the one in Listing 2 then mounts the network shares configured in /etc/fstab when you connect the computer to a wired Ethernet port. The CONNECTION_UUUID required for the connection can be determined in the NetworkManager console front end by typing nmcli connection show (Listing 3). Please note that the UUIDs of previously configured WiFi networks will change. However, the Ethernet interface always gets the same UUID, regardless of whether you connect the computer to the network via cable in the office, at the university, or at home.

Listing 2

Mounting a Share

01 #!/bin/bash
02 if [ "$2" = "up" ]; then
03   if ["$CONNECTION_UUUID" = "<I>2911db45-3eff-3b74-9c87-4c36e0290693<I>" ]; then
04     mount /mnt/diskstation/music &
05     mount /mnt/diskstation/data &
06     mount /mnt/diskstation/photo &
07   fi
08 fi

Listing 3

Finding the UUID

$ nmcli connection show
NAME                      UUID                                  TYPE       DEVICE
LAN1                      2911db45-3eff-3b74-9c87-4c36e0290693  ethernet   enp0s31f6
Santa                     5e1eb419-9f6a-40e2-ada5-ca6a909bee87  wifi       wlp2s0
G6_SMARTPHONE             d9d63454-329e-4177-a6ef-c92b39fe26af  wifi       --
LAN2                      f38a99ea-48ea-362b-90d3-62a265930f87  ethernet   --
VPN-Netherlands           7b87cee0-3131-4b0c-a659-bb33f4a64dd8  vpn        --
PirateBox - Share Freely  46b124c1-0604-4645-99d6-5c73d200a1e6  wifi       --

The important part is the desired action. Line 2 of Listing 2 stipulates that the network manager should execute the action after successfully opening a connection. There are numerous other actions, such as down, pre-up, or pre-down. Table 1 provides a summary.

Table 1

Dispatcher Actions

Action Description

pre-up

Network device connected to the network, but not yet fully activated. Scripts must either be copied to /etc/NetworkManager/dispatcher.d/pre-up.d or linked there by symlink.

up

Action is executed after completing connection establishment.

pre-down

The network device to be deactivated is still connected to the network. Scripts must either be copied to /etc/NetworkManager/dispatcher.d/pre-down.d or linked there.

down

Action is executed after a network connection is terminated.

vpn-pre-up

Identical to pre-up, but only applies to VPN connections.

vpn-up

Action is executed after a VPN connection has been established.

vpn-pre-down

Identical to pre-down, but only applies to VPN connections.

vpn-down

Action is executed after a VPN connection is closed.

hostname

Registers a change of the hostname.

dhcp4-change

System has received a new IPv4 configuration via DHCP.

dhcp6-change

System has received a new IPv6 configuration via DHCP.

connectivity-change

Network status has changed (see Table 2).

All pre actions (especially [UCC:x20-kl-listing-bold]pre-down[/UCC] and [UCC:x20-kl-listing-bold]vpn-pre-down[/UCC]) are only executed by NetworkManager if the network interface is shut down cleanly. If a VPN connection crashes, this can lead to unintentional disclosure of data under certain circumstances.

Table 2

Network Status

Status Description

none

Network device is not connected

portal

Network device is connected to a "captive portal" (such as a page for authentication in a hotel WLAN) and is not yet connected to the Internet.

limited

The network device is connected to the LAN but has no connection to the Internet.

full

Network connection including Internet access is completely set up.

unknown

Network status of the device cannot be determined.

The pre actions are a bit confusing. For some time now, the subdirectories pre-up.d/ and pre-down.d/ have been available below /etc/NetworkManager/dispatcher.d/. Scripts stored or linked there are executed by NetworkManager without case distinction in the script itself. Listing 4 would, if saved as [...]/pre-down.d/10-umount-cifs, for example, safely unmount the shares previously mounted via Listing 2 before the network connection is terminated.

Listing 4

Unmounting

#!/bin/bash
umount -a -l -t cifs

In order to implement different shares depending on the work configuration, you can extend the Listing 2's principle. If you populate the script with the contents of Listing 5, NetworkManager uses the Netcat command nc -z server_name 139 to check whether the computer entered in the SERVERNAME variable can be found on the network and whether the Samba service is running on port 139. If so, the script mounts the shares listed in the SHARES array.

Listing 5

Conditional Config

#!/bin/bash
SERVERNAME="diskstation"
FOLDER="/mnt/diskstation"
SHARES=(homes music data photo ebooks images video web)
if [ "$2" = "up" ]; then
  if ["$CONNECTION_UUUID" = "2911db45-3eff-3b74-9c87-4c36e0290693" ]; then
    ### Check if $SERVERNAME is online and offers samba shares
    if nc -z $SERVERNAME 139 2>/dev/null; then
      ### If so, then mount shares from array $SHARES
      for SHARE in "${SHARES[@]}"
      do
        ### Only mount if share not yet mounted
        if ! $(mountpoint -q "$FOLDER/$SHARE") ; then
          mount $FOLDER/$SHARE
        fi
      done
    fi
  fi
fi

For each Samba server you usually use, you just need to create a script in /etc/NetworkManager/dispatcher.d of the type 30-mount-server_name, which will handle situational mounting of network shares in the future. You only need to adjust the variables in the script header and change the UUID. Should a server be unavailable, the system does not waste time on unsuccessful attempts to find the server on the network.

Environment Variables

NetworkManager fills a number of environment variables in the dispatcher scripts that can be used to control the desired actions. For example, in $IP4_DOMAINS, you will find the domain name assigned by the DHCP server; $IP4_ADDRESS_0 contains the IP and gateway address in the format IP_address/prefix gateway. The Gnome Foundation's developer page explains all the variables in NetworkManager [1]. If necessary, you can write the contents of these variables to the system journal with the printenv >&2 command. You can then use

<C>journalctl -f -u NetworkManager<C>

to view the contents of the variables during the dispatcher script runtime (Listing 6).

Listing 6

Viewing Variables

$ journalctl -f -u NetworkManager
[...]
May 22 23:44:01 ontario NetworkManager[485]: <info> [159...] dhcp4 (enp0s31f6): option domain_name => 'fritz.box'.
May 22 23:44:01 NetworkManager[485]: <info> [159...] dhcp4 (enp0s31f6): option domain_name_servers => '192.168.188.11'.
May 22 23:44:01 ontario NetworkManager[485]: <info> [159...] dhcp4 (enp0s31f6): option ntp_servers => '192.168.188.1'.
[...]

Automating VPN Access

Another popular use case is to automatically start a VPN connection when connecting to a specific WiFi network. For example, if you save Listing 7 as 20-protonvpn in /etc/NetworkManager/dispatcher.d, the NetworkManager calls up a connection to the VPN with the ProtonUS ID via NetworkManager's nmcli text-based front end whenever a connection to the WiFi network with the specified UUID is established. This time, a case distinction using the case command provides the different commands for establishing and terminating the connection (Figure 2).

Listing 7

With VPN

#!/bin/sh
if ["$CONNECTION_UUUID" = "5e1eb419-9f6a-40e2-ada5-ca6a909bee87" ]; then
  case "$2" in
    up)
      nmcli connection up id "ProtonUS" passwd-file /root/protonvpn-passwd-file
    ;;
    pre-down)
      nmcli connection down id "ProtonUS"
    ;;
  esac
fi
Figure 2: Armed with the right dispatcher script, NetworkManager automatically starts a VPN connection when you connect to a specific WiFi network.

Of course, you stored the VPN access password specifically for your user account in the desktop environment's key ring when you configured the VPN connection in the NetworkManager graphical front end. But the NetworkManager service runs as root and has no access to this content, meaning that you have to store the password again separately on the system. Note that this would be considered insecure on many systems, so think of this as a proof of concept and adapt as needed for your environment. The example from Listing 7 accesses a password in the /root/protonvpn-passwd-file file for this purpose. The password file's format is shown in the output of the second command in Listing 8.

Listing 8

Password File Format

# nmcli connection show
NAME UUID TYPE DEVICE
ProtonUS 4610ff84-57d8-4509-a56d-c33a5c7f21c9 vpn --
SantaFAST 5e1eb419-9f6a-40e2-ada5-ca6a909bee87 wifi --
# cat /root/protonvpn-passwd-file
vpn.secrets.password: secret+password

Optionally, you could also directly edit the configuration file responsible for the desired network in /etc/NetworkManager/system-connections/. Working with the right file, you would then have to change the 1 to a   for the option password-flags= in the [vpn] section, and then store the password in [vpn-secrets] with a new password=Password line to be added to the file. This approach lets NetworkManager start the desired VPN connection without user interaction.

Note that establishing a VPN connection does not ensure secure and anonymous surfing on the web. For example, if the VPN were to break down due to transmission errors, NetworkManager would not notice this and would then transmit the data without encryption. It makes sense to add suitable firewall scripts to ensure that the system uses only the encrypted tunnel for data transfers.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

SINGLE ISSUES
 
SUBSCRIPTIONS
 
TABLET & SMARTPHONE APPS
Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More

News