View Single Post
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