Hi,
I recently had a great deal of problems getting connectivity working as required with squeezeboxserver on my Ubuntu 18.04 LTS installation. The problem being that although the server was responding to internal HTTP requests on my private LAN, it refused to respond as when it configures itself at install. It picked the first network interface it found (My public Internet link) and wrote this address into its config files. Trying to change this was not successful. It refused to make any such change and essentially due to the lack of documentation around such configuration I went ahead and built a more appropriate environment for the server daemon.
What this does is to force the daemon to run within a named network namespace, which are supported by the Linux kernel. This means that when the server starts it can only see 1 interface. The one defined in this network namespace. It can not see the public internet interface. It binds to this interface and so long as this interface is bridged into the root network namespace, and an appropriate default route is made available also in the named network namespace, then it can see the internal and public internet as required.
This is not a particularly simple thing to do. But I am happy that the server now runs where I want it with the connectivity I want it to have. See
https://github.com/systemd/systemd/issues/2741
I am posting a solution below. It uses systemd to start the squeezebox server in a stack of netns and bridge services. If anyone else would like they can pick it apart and take the same approach. Good luck. Enjoy.
Aidan
I took the approach of using the following three service definitions:
netns@.service
netns-bridge@.service
squeezeboxserver_in_netns.service
And to initiate the service stack first run systemctl daemon-reload and then:
service squeezeboxserver_in_netns start
This is responsible for nameing the netns instance. Care needs to be taken here as interface names are limited in length (16 chars I think) and they will be generated by appending this name to the interface name suffix as defined in the .conf file in ./network/netns/netns-[service-name]-bridge.conf. It works nicely and if the daemon dies it removes all the config.
See here is the code:
A netns creation file: /etc/systemd/system/netns@.service
[Unit]
Description=Named network namespace %I
Documentation=https://github.com/systemd/systemd/issues/2741#issuecomment-336736214
StopWhenUnneeded=true
[Service]
Type=oneshot
RemainAfterExit=yes
# Ask systemd to create a network namespace
PrivateNetwork=yes
# Ask ip netns to create a named network namespace
# (This ensures that things like /var/run/netns are properly setup)
ExecStart=/sbin/ip netns add %I
# Drop the network namespace that ip netns just created
ExecStart=/bin/umount /var/run/netns/%I
# Re-use the same name for the network namespace that systemd put us in
ExecStart=/bin/mount --bind /proc/self/ns/net /var/run/netns/%I
# Clean up the name when we are done with the network namespace
ExecStop=/sbin/ip netns delete %I
A netns bridge configuration service file: /etc/systemd/system/netns-bridge@.service
[Unit]
Description=Named network namespace "%i" network config
BindsTo=netns@%i.service
After=netns@%i.service
StopWhenUnneeded=true
[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/etc/systemd/network/netns/netns-%i-bridge.conf
# Configure network
ExecStart=/sbin/ip link add ${ROOT_NS_INTF_NAME}-%i type veth peer name ${IN_NS_INTF_NAME}-%i
ExecStart=/sbin/ip link set ${IN_NS_INTF_NAME}-%i netns %i
ExecStart=/sbin/ip link set ${ROOT_NS_INTF_NAME}-%i up
ExecStart=/sbin/brctl addif ${ROOT_NS_BRIDGE} ${ROOT_NS_INTF_NAME}-%i
ExecStart=/sbin/ip netns exec %i ip addr add ${IN_NS_INTF_IP} dev ${IN_NS_INTF_NAME}-%i
ExecStart=/sbin/ip netns exec %i ip link set ${IN_NS_INTF_NAME}-%i up
ExecStart=/sbin/ip netns exec %i ip link set lo up
ExecStart=/sbin/ip netns exec %i ip route add default via ${IN_NS_DEFAULT_GW}
# Clean up when we are done with the network namespace
ExecStop=/sbin/ip link del veth0-%i
A squeezeboxserver daemon service file: /etc/systemd/system/squeezeboxserver_in_netns.service
[Unit]
# Ensure network is configured
BindsTo=netns-bridge@squeeze.service
After=netns-bridge@squeeze.service
# Join the "squeeze" named network namespace that netns@ created
JoinsNamespaceOf=netns@squeeze.service
[Service]
PrivateNetwork=yes
# Your service is now running inside the "squeeze" named network namespace!
ExecStart=/bin/bash /usr/sbin/squeezeboxserver_safe /usr/sbin/squeezeboxserver --prefsdir /var/lib/squeezeboxserver/prefs
A network configuration file: /etc/systemd/network/netns/netns-squeeze-bridge.conf
#Bridge configuration for test netns
IN_NS_INTF_NAME=veth1
IN_NS_INTF_IP=10.0.0.11/24
IN_NS_DEFAULT_GW=10.0.0.10
ROOT_NS_INTF_NAME=veth0
ROOT_NS_BRIDGE=int_br0