Jak pozwolić wbudowanemu DHCP przypisać statyczny adres IP do kontenera LXC na podstawie nazwy, a nie adresu MAC

10

Wiem, że mogę przypisać statyczny adres IP ręcznie, używając /etc/network/interfaces.

Wiem też, że mogę odczytać adres MAC kontenera LXC (np. Szukając lxc.network.hwaddrwpisu /var/lib/lxc/<container-name>/configi przypisując adres IP na podstawie wpisów dhcp-host=<mac-addr>,10.0.3.3w /etc/dnsmasq.d/<some file>.

W pliku, /etc/default/lxc-netktóry przeczytałem

# Uncomment the next line if you'd like to use a conf-file for the lxcbr0
# dnsmasq.  For instance, you can use 'dhcp-host=mail1,10.0.3.100' to have
# container 'mail1' always get ip address 10.0.3.100.
#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

To by pasowało do moich potrzeb; niestety nie przynosi to żadnego efektu.

Adam Ryczkowski
źródło
2
Działa to dla mnie, ale pamiętaj, że musisz ponownie uruchomić lxc-net, aby zadziałało. I jest znany problem, że lxc-net robi restart jeśli pojemnik jest aktualnie uruchomiona. Musisz zatrzymać je wszystkie, a następnie ponownie uruchomić usługę lxc-net.
HRJ,
Ponadto nie byłem w stanie przypisać adresów IP przy użyciu samej nazwy kontenera. Musiałem zakodować na stałe adres MAC kontenera i konfiguracji DHCP.
HRJ,
@HRJ, czy mógłbyś opublikować plik dnsmasq.conf?
tonytony
@HRJ W systemie Ubuntu 14.04 ponowne uruchomienie lxc-netnie pomaga, jeśli nie usuniesz mostu lxcbr0. Zobacz moją odpowiedź.
Adam Ryczkowski

Odpowiedzi:

17

Wpadłem na to ostatnio i myślę, że znalazłem łatwe rozwiązanie. Testowałem (tylko) na Ubuntu 14.04.

Najpierw odkomentuj tę linię / etc / default / lxc-net:

LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

W /etc/lxc/dnsmasq.conf zdefiniuj plik dhcp-hosts:

dhcp-hostsfile=/etc/lxc/dnsmasq-hosts.conf

Następnie dodaj wpisy do pliku /etc/lxc/dnsmasq-hosts.conf w następujący sposób:

mail,10.0.3.16
web,10.0.3.17

Uwaga: zmiany zaczną obowiązywać po ponownym uruchomieniu lxc-net (który ponownie uruchamia dnsmasq):

service lxc-net restart

Następnie możesz zmodyfikować /etc/lxc/dnsmasq-hosts.conf i wysłać sygnał SIGHUP do dnsmasq:

killall -s SIGHUP dnsmasq

Więc tak, musisz zrestartować lxc-net, ale tylko raz. Mam nadzieję że to pomoże.

mtp
źródło
Podoba mi się pomysł delegowania listy hostów do zewnętrznego pliku. Poza tym twoja metoda różni się od mojej z powodu killall -s SIGHUP dnsmasq. Zgadzam się, że samo „SIGHUP-inging” dnsmasq jest bardziej wydajne niż restartowanie całego demona (szczególnie jeśli nie działa bez łatania swoich skryptów startowych).
Adam Ryczkowski
Ponowne uruchomienie usługi lxc-netjest potrzebne tylko po to, aby dnsmasq mógł użyć konfiguracji z /etc/lxc/dnsmasq.conf (i ta informacja jest w niej /etc/default/lxc-netnieznana dnsmasq). Jeśli ustawiłeś go wcześniej, wystarczy SIGHUP.
Adam Ryczkowski
Uwaga: lxc-net nie uruchomi ponownie dnsmasq, jeśli są uruchomione kontenery.
s3v3n
IMO to najlepsza odpowiedź
s3v3n
kill -HUP $(cat /var/run/lxc/dnsmasq.pid)jeśli nie chcesz instalować killallani ponownie ładować innych dnsmasqinstancji
gertas,
4

Działa dobrze w Ubuntu 14.04.1

Odkomentuj tę linię /etc/default/lxc-net

#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

zatrzymaj wszystkie pojemniki, uruchom ponownie lxc-net:

service lxc-net restart

Skonfiguruj adresy IP w /etc/lxc/dnsmasq.conf

dhcp-host={NAME},10.0.3.2

gdzie {NAME}jest nazwa twojego kontenera LXC:

/var/lib/lxc/{NAME}
Tombart
źródło
Działa tylko wtedy, gdy skrypt może zamknąć sieć lxcbr0 , co wyklucza przypadek, gdy działają inne kontenery lxc. Krótko mówiąc, w obecnej postaci nie można przypisywać statycznych dzierżaw dhcp bez ponownego uruchamiania wszystkich kontenerów.
Adam Ryczkowski
Tak, to prawda, jest to dość niewygodne :(. Znalazłem łatwiejsze rozwiązanie do edycji /var/lib/lxc/<container-name>/rootfs/etc/network/interfacespliku i przypisania statycznego adresu IP do kontenera.
Tombart
To prawda, ale nie ma nic, co mogłoby Cię ochronić przed przyznaniem dwóm gościom tego samego adresu IP. Zobacz moją zaakceptowaną odpowiedź - rozwiązuje problem.
Adam Ryczkowski
1

Odpowiedź Tombarta działa, jeśli jesteś wystarczająco cierpliwy, aby czekać na odświeżenie DNS ORAZ chcesz ponownie uruchomić kontener (gość) później.

Poniżej znajduje się przepis, który wymaga, aby wszystkie inne potencjalnie działające kontenery LXC zostały zamknięte . Jeśli nie możesz sobie na to pozwolić, nie widzę sposobu na wymuszenie nowej konfiguracji dnsmasq. (W przypadku niektórych powodów sygnalizacji HUP do pid dnsmasqa znalezionego w /run/lxc/dnsmasq.pidrównież nie działa).

Więc jeśli chcesz mieć coś, co działa natychmiast i nie ma uruchomionych innych kontenerów LXC, skorzystaj z mojej odpowiedzi. $nameto nazwa węzła, dla którego chcemy zresetować przypisanie, i $internalifnazwa mostkowanego adaptera LXC. Możesz uzyskać wartość $internalifz np. augtool -L -A --transform "Shellvars incl /etc/default/lxc-net" get "/files/etc/default/lxc-net/LXC_BRIDGE" | sed -En 's/\/.* = (.*)/\1/p'Jeśli instalujesz, augeas-toolsale zwykle jest to po prostu lxcbr0.

sudo lxc-stop -n $name >/dev/null
sudo service lxc-net stop >/dev/null
if [ -d /sys/class/net/$internalif ]; then
   sudo brctl delbr $internalif >/dev/null #Why? See below.
fi
sudo rm /var/lib/misc/dnsmasq.$internalif.leases
sudo service lxc-net start >/dev/null
sudo lxc-start -d -n $name >/dev/null
sleep 5

Niestety /etc/init/lxc-net.confw Ubuntu 14.04 występuje błąd (funkcja?), Który uniemożliwia ponowne załadowanie, dnsmasqchyba że urządzenie mostkowe jest wyłączone dla hosta.

Adam Ryczkowski
źródło
0

To rozwiązanie działa przez załatanie skryptów startowych lxc. Dzieli złożone zadanie polegające na podniesieniu mostu lxcbr0 i uruchomieniu go dnsmasqna dwa osobne zadania. Teraz nie musisz ponownie uruchamiać całego lxc-netmostu, aby przeładować dnsmasq- przeładowanie sudo service restart lxc-dnsmasqjest wystarczające i nie wymaga wyłączania mostu.

  1. Zatrzymaj usługę lxc-net sudo service lxc-net stopi upewnij się, że nie ma mostka lxcbr0 (lub równoważnego).
  2. Zastąp zawartość /etc/init/lxc-net.confnastępujących treści:

.

description "lxc network"
author "Serge Hallyn <[email protected]>"

start on starting lxc
stop on stopped lxc

env USE_LXC_BRIDGE="true"
env LXC_BRIDGE="lxcbr0"
env LXC_ADDR="10.0.3.1"
env LXC_NETMASK="255.255.255.0"
env LXC_NETWORK="10.0.3.0/24"
env varrun="/run/lxc"
env LXC_DOMAIN=""

pre-start script
    [ -f /etc/default/lxc ] && . /etc/default/lxc

    [ "x$USE_LXC_BRIDGE" = "xtrue" ] || { stop; exit 0; }

    use_iptables_lock="-w"
    iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock=""
    cleanup() {
        # dnsmasq failed to start, clean up the bridge
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
        iptables $use_iptables_lock -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT
        iptables $use_iptables_lock -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT
        iptables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE || true
        iptables $use_iptables_lock -t mangle -D POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
        ifconfig ${LXC_BRIDGE} down || true
        brctl delbr ${LXC_BRIDGE} || true
    }
    if [ -d /sys/class/net/${LXC_BRIDGE} ]; then
        if [ ! -f ${varrun}/network_up ]; then
            # bridge exists, but we didn't start it
            stop;
        fi
        exit 0;
    fi

    # set up the lxc network
    brctl addbr ${LXC_BRIDGE} || { echo "Missing bridge support in kernel"; stop; exit 0; }
    echo 1 > /proc/sys/net/ipv4/ip_forward
    mkdir -p ${varrun}
    ifconfig ${LXC_BRIDGE} ${LXC_ADDR} netmask ${LXC_NETMASK} up
    iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
    iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
    iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
    iptables $use_iptables_lock -I INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
    iptables $use_iptables_lock -I FORWARD -i ${LXC_BRIDGE} -j ACCEPT
    iptables $use_iptables_lock -I FORWARD -o ${LXC_BRIDGE} -j ACCEPT
    iptables $use_iptables_lock -t nat -A POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE
    iptables $use_iptables_lock -t mangle -A POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill

    touch ${varrun}/network_up
end script

post-stop script
    [ -f /etc/default/lxc ] && . /etc/default/lxc
    [ -f "${varrun}/network_up" ] || exit 0;
    # if $LXC_BRIDGE has attached interfaces, don't shut it down
    ls /sys/class/net/${LXC_BRIDGE}/brif/* > /dev/null 2>&1 && exit 0;

    if [ -d /sys/class/net/${LXC_BRIDGE} ]; then
        use_iptables_lock="-w"
        iptables -w -L -n > /dev/null 2>&1 || use_iptables_lock=""
        ifconfig ${LXC_BRIDGE} down
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 67 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 67 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p udp --dport 53 -j ACCEPT
        iptables $use_iptables_lock -D INPUT -i ${LXC_BRIDGE} -p tcp --dport 53 -j ACCEPT
        iptables $use_iptables_lock -D FORWARD -i ${LXC_BRIDGE} -j ACCEPT
        iptables $use_iptables_lock -D FORWARD -o ${LXC_BRIDGE} -j ACCEPT
        iptables $use_iptables_lock -t nat -D POSTROUTING -s ${LXC_NETWORK} ! -d ${LXC_NETWORK} -j MASQUERADE || true
        iptables $use_iptables_lock -t mangle -D POSTROUTING -o ${LXC_BRIDGE} -p udp -m udp --dport 68 -j CHECKSUM --checksum-fill
        pid=`cat ${varrun}/dnsmasq.pid 2>/dev/null` && kill -9 $pid || true
        rm -f ${varrun}/dnsmasq.pid
        brctl delbr ${LXC_BRIDGE}
    fi
    rm -f ${varrun}/network_up
end script
  1. Dodaj kolejny plik /etc/init/lxc-dnsmasqo następującej treści:

.

description "lxc dnsmasq service"
author "Adam Ryczkowski, ispired by Serge Hallyn <[email protected]>"

expect fork

start on started lxc-net
stop on stopped lxc-net

env USE_LXC_BRIDGE="true"
env LXC_BRIDGE="lxcbr0"
env LXC_ADDR="10.0.3.1"
env LXC_NETMASK="255.255.255.0"
env LXC_NETWORK="10.0.3.0/24"
env LXC_DHCP_RANGE="10.0.3.2,10.0.3.254"
env LXC_DHCP_MAX="253"
env LXC_DHCP_CONFILE=""
env varrun="/run/lxc-dnsmasq"
env LXC_DOMAIN=""

pre-start script
    [ -f /etc/default/lxc ] && . /etc/default/lxc

    [ "x$USE_LXC_BRIDGE" = "xtrue" ] || { stop; exit 0; }

    if [ ! -d ${varrun} ]; then
        mkdir -p ${varrun}
    fi
    opts="$LXC_DOMAIN_ARG -u lxc-dnsmasq --strict-order --bind-interfaces --pid-file=${varrun}/dnsmasq.pid --conf-file=${LXC_DHCP_CONFILE} --listen-address ${LXC_ADDR} --dhcp-range ${LXC_DHCP_RANGE} --dhcp-lease-max=${LXC_DHCP_MAX} --dhcp-no-override --except-interface=lo --interface=${LXC_BRIDGE} --dhcp-leasefile=/var/lib/misc/dnsmasq2.${LXC_BRIDGE}.leases --dhcp-authoritative --keep-in-foreground"

    /usr/sbin/dnsmasq $opts &

end script

post-stop script
    if [ -f ${varrun}/dnsmasq.pid ]; then
        PID=`cat ${varrun}/dnsmasq.pid`
        kill $PID
    fi
end script
Adam Ryczkowski
źródło
0

Oto prosty skrypt Pythona, który uwalnia dzierżawę dnsmasq LXC. Możesz uruchomić go z hosta lub wykuć z innego kontenera - tak, to działa !:

#!/usr/bin/env python
from scapy.all import *
conf.checkIPaddr=False
leaseMAC = '00:16:3e:11:71:b0' #container MAC here
releaseIP='10.0.3.33' #container IP here
serverIP='10.0.3.1'
hostname='container-name-here'
rawMAC = leaseMAC.replace(':','').decode('hex')
send(IP(dst=serverIP) / \
     UDP(sport=68,dport=67) / \
     BOOTP(chaddr=rawMAC, ciaddr=releaseIP, xid=RandInt()) / \
     DHCP(options=[('message-type','release'),('server_id',serverIP),('hostname',hostname), ('end')]))

Warunkiem powyższego jest biblioteka pythonowego scapy:

pip install scapy

Po uruchomieniu powinieneś zobaczyć w dzienniku systemowym coś takiego:

dnsmasq-dhcp[3242]: DHCPRELEASE(lxcbr0) 10.0.3.33 00:16:3e:11:71:b0 container-name-here

Aby potwierdzić, sprawdź, czy wpis został usunięty /var/lib/misc/dnsmasq.lxcbr0.leases. Sam kontener zachowa adres IP, dlatego należy go zatrzymać przed uruchomieniem nowego kontenera, który powinien ponownie użyć adresu IP.

gertas
źródło
1
To super! Nawet nie wiedziałem, że DHCP to obsługuje! Będę głosować natychmiast po tym, jak potwierdzę, że działa.
Adam Ryczkowski
0

Zdaję sobie sprawę, że moja odpowiedź jest spóźniona o wiele lat, ale może to pomaga komuś innemu. Problem polegał na tym, że edytowałeś kod specyficzny dla pakietu ( write_lxc_netfunkcji) Ubuntu LXC, który miał być zapisany w innym miejscu docelowym jako ciąg, a nie przetwarzany w samym lxc-netskrypcie!

W rezultacie proces dnsmasq nie otrzymał pliku konfiguracji, który próbowałeś przekazać, pozostawiając cię „bez efektu”, jak mówisz.

Zamiast tego chciałbyś ustawić tę zmienną u góry skryptu, pośród pozostałych:

#!/bin/sh -

distrosysconfdir="/etc/default"
varrun="/run/lxc"
varlib="/var/lib"

# These can be overridden in /etc/default/lxc
#   or in /etc/default/lxc-net

USE_LXC_BRIDGE="true"
LXC_BRIDGE="lxcbr0"
LXC_BRIDGE_MAC="00:16:3e:00:00:00"
LXC_ADDR="10.0.3.1"
LXC_NETMASK="255.255.255.0"
LXC_NETWORK="10.0.3.0/24"
LXC_DHCP_RANGE="10.0.3.2,10.0.3.254"
LXC_DHCP_MAX="253"
LXC_DHCP_CONFILE="/etc/lxc/dnsmasq.conf"   <-- Here for instance
LXC_DOMAIN=""
Adrian
źródło