En liten oppdatering med tv-løsningen jeg endte opp med. Jeg innser at jeg nok har litt andre mål enn de fleste andre, så dette passer antageligvis ikke så mange. Men uansett, for underholdningens skyld...
Vedlig forenklet har jeg et nettverk med en sentral switch tilkoblet fiber, dekoder og en Linux server/router. Målet mitt er å la TV (VLAN101) være isolert til fiber + dekoder, og Internett (VLAN102) være isolert til fiber + router. Men med ny TV-løsning var det ikke lenger mulig å kun ha switchen mellom fiber og dekoder, ettersom Altibox nå blokkerer dekoder fra å få IP-adresse på VLAN101.
Løsningen min er å flytte dekoder-porten på switchen til et annet VLAN (vilkårlig, men jeg valgte 103) og trunke alle VLANene 101, 102 og 103 til routeren. Der tar jeg VLAN-interfacene 101 og 103 inn i en egen "network namespace", med dhcp klient på 101, dhcp server på 103 og igmpproxy for å route multicast mellom de to VLANene. Jeg prøvde meg først med en VRF-løsning, men "namespace" er mye nærmere den totale isolasjonen jeg ønsker meg. Det gir samme effekt som å ha en helt egen router med kun de to interfacene. iptables, routing-tabller og prosesser som lytter på en socket er alle helt isolert fra resten av routeren.
Jeg laget meg et script for å konfigurere opp alt som tilhørere "TV-routeren", inkludert egne iptables-regler og konfig-filer for dhcp klient og server samt igmpproxy:
Kode
#!/bin/sh
# $Id: altiboxtv,v 1.1 2020/02/13 21:17:58 bjorn Exp $
### BEGIN INIT INFO
# Provides: altiboxtv
# Required-Start: $network $remote_fs $syslog
# Required-Stop: $network $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Setup Altibox TV network
# Description: Setup Altibox TV network.
### END INIT INFO
NAME=altiboxtv
DESC="Altibox TV networking"
PIDFILE=/run/$NAME.pid
NETNS=tvnet
DEV=br0
VID_U=101
VID_D=103
MAC_U=b8:d5:26:00:de:ad
PREFIX=10.$VID_D.0
DIR=/var/lib/altiboxtv
[ ! -f /etc/default/altiboxtv ] || . /etc/default/altiboxtv
. /lib/lsb/init-functions
set -e
mk_conf()
{
[ -d $DIR ] || mkdir -p $DIR
cat <<EOF >$DIR/igmpproxy.conf
quickleave
phyint $DEV.$VID_U upstream
altnet 0.0.0.0/0
phyint $DEV.$VID_D downstream
EOF
cat <<EOF >$DIR/dhclient.conf
option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;
send host-name = gethostname();
request subnet-mask, broadcast-address, time-offset, routers,
domain-name, domain-name-servers, host-name,
interface-mtu, rfc3442-classless-static-routes;
EOF
}
mk_dhcpd_conf()
{
touch $DIR/dhcpd.leases
grep domain-name-servers $DIR/dhclient.leases |tail -1 >$DIR/dhcpd.conf
cat <<EOF >>$DIR/dhcpd.conf
authoritative;
default-lease-time 86400;
max-lease-time 86400;
use-host-decl-names on;
shared-network "tv" {
subnet $PREFIX.0 netmask 255.255.255.0 {
range $PREFIX.2 $PREFIX.253;
option routers $PREFIX.1;
option subnet-mask 255.255.255.0;
option broadcast-address $PREFIX.255;
}
}
EOF
}
setup_iptables()
{
/sbin/ip netns exec $NETNS /sbin/iptables -tnat -A POSTROUTING -o $DEV.$VID_U -s $PREFIX.0/24 -j MASQUERADE
/sbin/ip netns exec $NETNS /sbin/iptables -N tv-inout
/sbin/ip netns exec $NETNS /sbin/iptables -A tv-inout -p udp --sport 67 --dport 68 -j ACCEPT
/sbin/ip netns exec $NETNS /sbin/iptables -A tv-inout -p udp --dport 67 --sport 68 -j ACCEPT
/sbin/ip netns exec $NETNS /sbin/iptables -A tv-inout -p igmp -j ACCEPT
/sbin/ip netns exec $NETNS /sbin/iptables -A INPUT -j tv-inout
/sbin/ip netns exec $NETNS /sbin/iptables -A OUTPUT -j tv-inout
/sbin/ip netns exec $NETNS /sbin/iptables -A FORWARD -o $DEV.$VID_U -j ACCEPT
/sbin/ip netns exec $NETNS /sbin/iptables -A FORWARD -o $DEV.$VID_D -m pkttype --pkt-type multicast -j ACCEPT
/sbin/ip netns exec $NETNS /sbin/iptables -A FORWARD -o $DEV.$VID_D -m state --state ESTABLISHED,RELATED -j ACCEPT
/sbin/ip netns exec $NETNS /sbin/iptables -P INPUT DROP
/sbin/ip netns exec $NETNS /sbin/iptables -P OUTPUT DROP
/sbin/ip netns exec $NETNS /sbin/iptables -P FORWARD DROP
}
do_start()
{
mk_conf
[ -e /run/netns/$NETNS ] || /sbin/ip netns add $NETNS
/sbin/ip netns exec $NETNS /sbin/ip link set lo up
/sbin/ip link add link $DEV name $DEV.$VID_U type vlan id $VID_U
/sbin/ip link add link $DEV name $DEV.$VID_D type vlan id $VID_D
/sbin/ip link set $DEV.$VID_U address $MAC_U
/sbin/ip link set $DEV.$VID_U netns $NETNS
/sbin/ip link set $DEV.$VID_D netns $NETNS
/sbin/ip netns exec $NETNS /sbin/dhclient -4 -v -i -cf $DIR/dhclient.conf -pf $DIR/dhclient.pid -lf $DIR/dhclient.leases $DEV.$VID_U
/sbin/ip netns exec $NETNS /sbin/ip addr add $PREFIX.1/24 dev $DEV.$VID_D
/sbin/ip netns exec $NETNS /sbin/ip link set $DEV.$VID_D up
mk_dhcpd_conf
/sbin/ip netns exec $NETNS /usr/sbin/dhcpd -4 -q -cf $DIR/dhcpd.conf -pf $DIR/dhcpd.pid -lf $DIR/dhcpd.leases $DEV.$VID_D
/sbin/ip netns exec $NETNS /usr/sbin/igmpproxy $DIR/igmpproxy.conf
setup_iptables
}
do_stop()
{
pids=$(/sbin/ip netns pids $NETNS)
[ -n "$pids" ] && kill -TERM $pids
/sbin/ip netns del $NETNS
}
case "$1" in
start)
do_start
;;
stop)
do_stop
;;
restart)
do_stop
sleep 1
do_start
;;
*)
echo "Usage: $N {start|stop|restartr}" >&2
exit 1
;;
esac
exit 0
Et par forklaringer:
br0 er navnet på det felles trunk-interfacet til switchen. Oppsett av dette interfacet med VLAN102 og annet som går over samme trunk ligger andre steder. De tre første bytene av MAC_U matcher mac-adressen til hjemmesentralen, men resten er nokså vilkårlig valgt av meg.
Jeg kan se på resultatet av det ovenstående ved f.eks å starte et shell i min
tvnet namespace:
Kode
canardo:/tmp# ip netns exec tvnet /bin/bash
canardo:/tmp# ifconfig
br0.101: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.171.174.108 netmask 255.255.254.0 broadcast 255.255.255.255
inet6 fe80::bad5:26ff:fe00:beef prefixlen 64 scopeid 0x20<link>
ether b8:d5:26:00:be:ef txqueuelen 1000 (Ethernet)
RX packets 734671425 bytes 995397971253 (927.0 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 207381 bytes 28278263 (26.9 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
br0.103: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.103.0.1 netmask 255.255.255.0 broadcast 0.0.0.0
inet6 fe80::21b:21ff:fea7:98bc prefixlen 64 scopeid 0x20<link>
ether 00:1b:21:a7:98:bc txqueuelen 1000 (Ethernet)
RX packets 877351 bytes 59463186 (56.7 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 733198848 bytes 1005491876633 (936.4 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (Local Loopback)
RX packets 129 bytes 10329 (10.0 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 129 bytes 10329 (10.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
canardo:/tmp# netstat -eanp
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
udp 0 0 0.0.0.0:67 0.0.0.0:* 0 40947157 8703/dhcpd
udp 0 0 0.0.0.0:68 0.0.0.0:* 0 40942024 8661/dhclient
raw 0 0 0.0.0.0:1 0.0.0.0:* 7 0 40947153 8703/dhcpd
raw 213504 0 0.0.0.0:2 0.0.0.0:* 7 0 40948399 8705/igmpproxy
raw 0 0 0.0.0.0:2 0.0.0.0:* 7 0 40948398 8705/igmpproxy
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node PID/Program name Path
unix 2 [ ] DGRAM 40947150 8703/dhcpd
unix 2 [ ] DGRAM 41382007 8705/igmpproxy
unix 2 [ ] DGRAM 40950855 8661/dhclient
canardo:/tmp# ip mroute
canardo:/tmp# ip route
default via 10.171.174.1 dev br0.101
10.103.0.0/24 dev br0.103 proto kernel scope link src 10.103.0.1
10.171.174.0/23 dev br0.101 proto kernel scope link src 10.171.174.108
canardo:/tmp# iptables -nvL
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
733M 994G tv-inout all -- * * 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
171K 24M ACCEPT all -- * br0.101 0.0.0.0/0 0.0.0.0/0
733M 994G ACCEPT all -- * br0.103 0.0.0.0/0 0.0.0.0/0 PKTTYPE = multicast
203K 907M ACCEPT all -- * br0.103 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
Chain OUTPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
339K 11M tv-inout all -- * * 0.0.0.0/0 0.0.0.0/0
Chain tv-inout (2 references)
pkts bytes target prot opt in out source destination
57 19956 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:67 dpt:68
60 19683 ACCEPT udp -- * * 0.0.0.0/0 0.0.0.0/0 udp spt:68 dpt:67
696K 22M ACCEPT 2 -- * * 0.0.0.0/0 0.0.0.0/0
canardo:/tmp# iptables -tnat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
30881 5023K MASQUERADE all -- * br0.101 10.103.0.0/24 0.0.0.0/0
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Her var dessverre ikke dekoderen aktiv så ingen multicast-routing. Men igmproxy virker helt som den skal og legger til multicast-ruter lokalt kun i denne "namespacen". Merk også den usannsynlig enkle routing-tabellen etttersom jeg egentlig bare forwarder fram og tilbake mellom to interface.
For meg gjør dette nytten, og jeg har igjen et helt isolert TV-nett med kun dekoder og fiber, samt denne minimale og enkle routeren.
Tro meg, resten av router- og server-konfigurasjon er på ingen måte så enkelt hos meg