Hi,
FWIW. Not sure what exactly we can use this for, but I would not be
surprised if this could help make some parts of Tails safer or the
implementation more elegant :)
This article documents how the traffic of specific Linux processes can be
subjected to a custom firewall or routing configuration, thanks to the magic
of cgroups. We will use the [Network classifier
cgroup](
https://www.kernel.org/doc/Documentation/cgroups/net_cls.txt), which
allows tagging the packets sent by specific processes.
To create the cgroup which will be used to identify the processes I added
something like this to `/etc/rc.local`:
    
    
    mkdir /sys/fs/cgroup/net_cls/unlocator
    /bin/echo 42 > /sys/fs/cgroup/net_cls/unlocator/net_cls.classid
    chown md: /sys/fs/cgroup/net_cls/unlocator/tasks
    
The `tasks` file, which controls the membership of processes in a cgroup, is
made writeable by my user: this way I can add new processes without becoming
root. 42 is the arbitrary class identifier that the kernel will associate with
the packets generated by the member processes.
A command like `systemd-cgls /sys/fs/cgroup/net_cls/` can be used to explore
which processes are in which cgroup.
I use a simple shell wrapper to start a shell or a new program as members of
this cgroup:
    
    
    #!/bin/sh -e
    CGROUP_NAME=unlocator
    
    if [ ! -d /sys/fs/cgroup/net_cls/$CGROUP_NAME/ ]; then
      echo "The $CGROUP_NAME net_cls cgroup does not exist!" >&2
      exit 1
    fi
    
    /bin/echo $$ > /sys/fs/cgroup/net_cls/$CGROUP_NAME/tasks
    
    if [ $# = 0 ]; then
      exec ${SHELL:-/bin/sh}
    fi
    
    exec "$@"
My first goal is to use a _special_ name server for the DNS queries of some
processes, thanks to a second dnsmasq process which acts as a caching
forwarder.
`/etc/dnsmasq2.conf`:
    
    
    port=5354
    listen-address=127.0.0.1
    bind-interfaces
    no-dhcp-interface=*
    
    no-hosts
    no-resolv
    server=185.37.37.37
    server=185.37.37.185
`/etc/systemd/system/dnsmasq2.service`:
    
    
    [Unit]
    Description=dnsmasq - Second instance
    Requires=network.target
    
    [Service]
    ExecStartPre=/usr/sbin/dnsmasq --test
    ExecStart=/usr/sbin/dnsmasq --keep-in-foreground --conf-file=/etc/dnsmasq2.conf
    ExecReload=/bin/kill -HUP $MAINPID
    PIDFile=/run/dnsmasq/dnsmasq.pid
    
    [Install]
    WantedBy=multi-user.target
    
Do not forget to enable the new service:
    
    
    systemctl enable dnsmasq2
    systemctl start dnsmasq2
Since the [cgroup match extension](
https://git.netfilter.org/iptables/plain/ex
tensions/libxt_cgroup.man) is not yet available in a released version of
iptables, you will first need to build and install it manually:
    
    
    git clone git://git.netfilter.org/iptables.git
    cd iptables
    ./autogen.sh
    ./configure
    make -k
    sudo cp extensions/libxt_cgroup.so /lib/xtables/
    sudo chmod -x /lib/xtables/libxt_cgroup.so
The netfilter configuration required is very simple: all DNS traffic from the
marked processes is redirected to the port of the local dnsmasq2:
    
    
    iptables -t nat -A OUTPUT -m cgroup --cgroup 42 -p udp --dport 53 -j REDIRECT --to-ports 5354
    iptables -t nat -A OUTPUT -m cgroup --cgroup 42 -p tcp --dport 53 -j REDIRECT --to-ports 5354
For related reasons, I also need to disable IPv6 for these processes:
    
    
    ip6tables -A OUTPUT -m cgroup --cgroup 42 -j REJECT
I use a different cgroup to force some programs to use my office VPN by first
setting a netfilter packet mark on their traffic:
    
    
    iptables -t mangle -A OUTPUT -m cgroup --cgroup 43 -j MARK --set-mark 43
The packet mark is then used to policy-route this traffic using a dedicate
VRF, i.e. routing table 43:
    
    
    ip rule add fwmark 43 table 43
This VPN VRF just contains a default route for the VPN interface:
    
    
    ip route add default dev tun0 table 43
Depending on your local configuration it may be a good idea to also add to the
VPN VRF the routes of your local interfaces:
    
    
    ip route show scope link proto kernel \
      | xargs -I ROUTE ip route add ROUTE table 43
Since the source address selection happens before the traffic is diverted to
the VPN, we also need to source-NAT to the VPN address the marked packets:
    
    
    iptables -t nat -A POSTROUTING -m mark --mark 43 --out-interface tun0 -j MASQUERADE
URL: 
http://blog.bofh.it/debian/id_457
-- 
intrigeri