Md at debian.org

tales of a debian maintainer

Run an Ansible playbook in a chroot

Running a playbook in a remote chroot or container is not supported by Ansible, but I have invented a good workaround to do it anyway.

The first step is to install Mitogen for Ansible (ansible-mitogen in Debian) and then configure ansible.cfg to use it:

[defaults]
strategy = mitogen_linear

But everybody should use Mitogen anyway, because it makes Ansible much faster.

The trick to have Ansible operate in a chroot is to make it call a wrapper script instead of Python. The wrapper can be created manually or by another playbook, e.g.:

  vars:
  - fsroot: /mnt

  tasks:
  - name: Create the chroot wrapper
    copy:
      dest: "/usr/local/sbin/chroot_{{inventory_hostname_short}}"
      mode: 0755
      content: |
        #!/bin/sh -e
        exec chroot {{fsroot}} /usr/bin/python3 "$@"

  - name: Continue with stage 2 inside the chroot
    debug:
      msg:
        - "Please run:"
        - "ansible-playbook therealplaybook.yaml -l {{inventory_hostname}} -e ansible_python_interpreter=/usr/local/sbin/chroot_{{inventory_hostname_short}}"

This works thanks to Mitogen, which funnels all remote tasks inside that single call to Python. It would not work with standard Ansible, because it copies files to the remote system with SFTP and would do it outside of the chroot.

The same principle can also be applied to containers by changing wrapper script, e.g:

#!/bin/sh -e
exec systemd-run --quiet --pipe --machine={{container_name}} --service-type=exec /usr/bin/python3 "$@"

After the wrapper will have been installed then you can run the real playbook by setting the ansible_python_interpreter variable, either on the command line, in the inventory or anywhere else that variables can be defined:

ansible-playbook therealplaybook.yaml -l {{inventory_hostname}} -e ansible_python_interpreter=/usr/local/sbin/chroot_{{inventory_hostname_short}}

My resignation from freenode

As it is now known, the freenode IRC network has been taken over by a Trumpian wannabe korean royalty bitcoins millionaire. To make a long story short, the former freenode head of staff secretly "sold" the network to this person even if it was not hers to sell, and our lawyers have advised us that there is not much that we can do about it without some of us risking financial ruin. Fuck you Christel, lilo's life work did not deserve this.

What you knew as freenode after 12:00 UTC of May 19 will be managed by different people.

As I have no desire to volunteer under the new regime, this marks the end of my involvement with freenode. It had started in 1999 when I encouraged the good parts of #linux-it to leave ircnet, and soon after I became senior staff. Even if I have not been very active recently, at this point I was the longest-serving freenode staff member and now I expect that I will hold this record forever.

The people that I have met on IRC, on freenode and other networks, have been and still are a very important part of my life, second only to the ones that I have known thanks to Usenet. I am not fine, but I know that the communities which I have been a part of are not defined by a domain name and will regroup somewhere else.

The current freenode staff members have resigned with me, these are some of their farewell messages:

  • amdj
  • edk
  • emilsp
  • Fuchs
  • jess
  • JonathanD
  • kline
  • niko
  • mniip
  • Swant
  • Together we have created Libera.Chat, a new IRC network based on the same principles of the old freenode.

    RPKI validation with FORT Validator

    This article documents how to install FORT Validator (an RPKI relying party software which also implements the RPKI to Router protocol in a single daemon) on Debian 10 to provide RPKI validation to routers. If you are using testing or unstable then you can just skip the part about apt pinnings.

    The packages in bullseye (Debian testing) can be installed as is on Debian stable with no need to rebuild them, by configuring an appropriate pinning for apt:

    cat <<END > /etc/apt/sources.list.d/bullseye.list
    deb http://deb.debian.org/debian/ bullseye main
    END
    
    cat <<END > /etc/apt/preferences.d/pin-rpki
    # by default do not install anything from bullseye
    Package: *
    Pin: release bullseye
    Pin-Priority: 100
    
    Package: fort-validator rpki-trust-anchors
    Pin: release bullseye
    Pin-Priority: 990
    END
    
    apt update
    

    Before starting, make sure that curl (or wget) and the web PKI certificates are installed:

    apt install curl ca-certificates
    

    If you already know about the legal issues related to the ARIN TAL then you may instruct the package to automatically install it. If you skip this step then you will be asked at installation time about it, either way is fine.

    echo 'rpki-trust-anchors rpki-trust-anchors/get_arin_tal boolean true' \
      | debconf-set-selections
    

    Install the package as usual:

    apt install fort-validator
    

    You may also install rpki-client and gortr on Debian 10, or maybe cfrpki and gortr. I have also tried packaging Routinator 3000 for Debian, but this effort is currently on hold because the Rust ecosystem is broken and hostile to the good packaging practices of Linux distributions.

    RPKI validation with OpenBSD's rpki-client and Cloudflare's gortr

    This article documents how to install rpki-client (an RPKI relying party software, the actual validator) and gortr (which implements the RPKI to Router protocol) on Debian 10 to provide RPKI validation to routers. If you are using testing or unstable then you can just skip the part about apt pinnings.

    The packages in bullseye (Debian testing) can be installed as is on Debian stable with no need to rebuild them, by configuring an appropriate pinning for apt:

    cat <<END > /etc/apt/sources.list.d/bullseye.list
    deb http://deb.debian.org/debian/ bullseye main
    END
    
    cat <<END > /etc/apt/preferences.d/pin-rpki
    # by default do not install anything from bullseye
    Package: *
    Pin: release bullseye
    Pin-Priority: 100
    
    Package: gortr rpki-client rpki-trust-anchors
    Pin: release bullseye
    Pin-Priority: 990
    END
    
    apt update
    

    Before starting, make sure that curl (or wget) and the web PKI certificates are installed:

    apt install curl ca-certificates
    

    If you already know about the legal issues related to the ARIN TAL then you may instruct the package to automatically install it. If you skip this step then you will be asked at installation time about it, either way is fine.

    echo 'rpki-trust-anchors rpki-trust-anchors/get_arin_tal boolean true' \
      | debconf-set-selections
    

    Install the packages as usual:

    apt install rpki-client gortr
    

    And then configure rpki-client to generate its output in the the JSON format needed by gortr:

    echo 'OPTIONS=-j' > /etc/default/rpki-client
    

    You may manually start the service unit to immediately generate the data instead of waiting for the next timer run:

    systemctl start rpki-client &
    

    gortr too needs to be configured to use the JSON data generated by rpki-client:

    echo 'GORTR_ARGS=-bind :323 -verify=false -checktime=false -cache /var/lib/rpki-client/json' > /etc/default/gortr
    

    And then it needs to be restarted to use the new configuration:

    systemctl restart gortr
    

    You may also install FORT Validator on Debian 10, or maybe cfrpki with gortr. I have also tried packaging Routinator 3000 for Debian, but this effort is currently on hold because the Rust ecosystem is broken and hostile to the packaging practices of Linux distributions.

    Debian support for libxcrypt

    glibc 2.29-7 and libxcrypt 1:4.4.10-10 today entered Debian testing: crypt(3) and the other related library functions in libcrypt from now on will be provided by libxcrypt instead of glibc.

    After 18 months of packaging work, Debian finally supports modern password hashing methods like yescrypt: the details about them are documented in crypt(5).

    For the time being there is still no support for libxcrypt in our release of PAM, but hopefully the Debian maintainer will update the package soon and this will allow using yescrypt by default.

    If you want to test now the new algorithms then you can generate a password using my mkpasswd program and copy it to /etc/shadow:

    # echo "marco:$(echo 12345 | mkpasswd --stdin)" | chpasswd --encrypted
    

    Per-process netfilter rules

    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, 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 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

    Hacking Team and a case of BGP hijacking

    After just a few hours the Hacking Team emails archive has already provided many tasty leaks. I want to focus on a routing security issue since this is my main research activity for this year.

    Short summary: if these emails are true, and so far nobody has found any credible reason to believe that they are not, then some major italian ISPs hijacked the IP addresses of a foreign ISP on request of the section of the Carabinieri which investigates terrorism and organized crime.

    The goal was to recover access to some copies of the Hacking Team malware which were controlled by "anonymizer" VPSes hosted on the hijacked network and that were abruptly disabled by their provider.

    Thanks to the great RIPEstat service I have been able to verify that indeed the network 46.166.163.0/24 was announced by (elided) (a large italian hosting company) in 2013, from august 15 to 22.

    Then I downloaded from the RIPE RIS archive a BGP table dump for august 20 2013 and processed it with my zebra-dump-parser software to extract the relevant routes. It shows that (elided) did not just advertise the hijacked network to the two italian ISPs mentioned in the emails, but apparently to all their other peers since the announce was also accepted by Hurricane Electric at MIX-IT. This means that the hijacking was not limited to a couple of local networks but involved many others all over the world.

    As an italian network operator I am seriously concerned that some of my BGP peers appear to be involved in what would usually be considered a criminal activity.

    As all operators know, there is still too much mutual trust involved in global BGP routing, and in some cases it is misplaced: we need better best practices, tools and protocols to make this kind of things impossible in the future.

    (Some of the relevant leaked emails: 1 2 3 4 5 6 7 8 9.)

    L'inaffidabile rete di Telecom Italia

    Da venerdì mattina fino almeno a tutto oggi pomeriggio è ricomparso il solito problema che impedisce a certi clienti di Telecom Italia di accedere a certi siti: per esempio un utente con una ADSL Alice non riesce a scaricare la posta dal proprio server in un data center.

    Ho visto questo tipo di guasto molte volte, la prima il 5 febbraio 2014: si manifesta sempre con un cliente di Telecom Italia che non riesce a raggiungere uno specifico IP "esterno", ma non ha problemi per esempio a raggiungere l'IP adiacente attivo sullo stesso server. Allo stesso modo l'IP "esterno" è normalmente raggiungibile dagli altri clienti di Telecom Italia.

    In tutti i casi che ho analizzato, confrontando i traceroute fatti verso un IP funzionante e uno non raggiungibile, si vede sempre che il traffico in uscita si ferma al confine tra la rete nazionale di Telecom Italia (AS3269) e il loro carrier globale Telecom Italia Sparkle (AS6762). Lo stesso comportamento mi è stato confermato dai colleghi di almeno tre altri operatori, quindi so che non dipende da specificità della mia rete. La rete nazionale di Telecom Italia è interconnessa al mondo esterno solo mediante Telecom Italia Sparkle, quindi il problema si verifica anche comprando direttamente transito da TIS.

    Considerando la frequenza e la durata di questi guasti, a quanto pare non esiste un modo per avere connettività affidabile verso le ADSL di Telecom Italia, cioè il 51% degli utenti consumer italiani, che non sia comprare transito o peering dallo stesso AS3269. Sarei felice di essere smentito.

    Per approfondire questi temi segnalo la mia presentazione sulle interconnessioni tra le reti italiane, disponibile anche in una versione per gli stranieri con qualche aggiornamento recente.

    My position on the "init system coupling" General Resolution

    I first want to clarify for the people not intimately involved with Debian that the GR-2014-003 vote is not about choosing the default init system or deciding if sysvinit should still be supported: its outcome will not stop systemd from being Debian's default init system and will not prevent any interested developers from supporting sysvinit.

    Some non-developers have recently threatened of "forking Debian" if this GR will not pass, apparently without understanding well the concept: Debian welcomes forks and I think that having more users working on free software would be great no matter which init system they favour.

    The goal of Ian Jackson's proposal is to force the maintainers who want to use the superior features of systemd in their packages to spend their time on making them work with sysvinit as well. This is antisocial and also hard to reconcile it with the Debian Constitution, which states:

    2.1.1 Nothing in this constitution imposes an obligation on anyone to do work for the Project. A person who does not want to do a task which has been delegated or assigned to them does not need to do it. [...]

    As it has been patiently explained by many other people, this proposal is unrealistic: if the maintainers of some packages were not interested in working on support for sysvinit and nobody else submitted patches then we would probably still have to release them as is even if formally declared unsuitable for a release. On the other hand, if somebody is interested in working on sysvinit support then there is no need for a GR forcing them to do it.

    The most elegant outcome of this GR would be a victory of choice 4 ("please do not waste everybody's time with pointless general resolutions"), but Ian Jackson has been clear enough in explaining how he sees the future of this debate:

    If my GR passes we will only have to have this conversation if those who are outvoted do not respect the project's collective decision.

    If my GR fails I expect a series of bitter rearguard battles over individual systemd dependencies.

    There are no significant practical differences between choices 2 "support alternative init systems as much as possible" and 3 "packages may require specific init systems if maintainers decide", but choice 3 is more explicit in supporting the technical decisions of maintainers and upstream developers.

    This is why I think that we need a stronger outcome to prevent discussing this over and over, no matter how each one of us feels about working personally on sysvinit support in the future. I will vote for choices 3, 2, 4, 1.

    The Italian peering ecosystem

    I published the slides of my talk "An introduction to peering in Italy - Interconnections among the Italian networks" that I presented today at the MIX-IT (the Milano internet exchange) technical meeting.

    About

    This is the blog of Marco d'Itri.

    S M T W T F S
            1 2 3
    4 5 6 7 8 9 10
    11 12 13 14 15 16 17
    18 19 20 21 22 23 24
    25 26 27 28 29 30 31

    See also:

    My blogroll:


    W3C HTML 4.01
    W3C CSS 2.0     

    Powered by Bryar.pm.