Cómo permitir que DHCP incorporado asigne una IP estática al contenedor LXC en función del nombre, no de la dirección MAC

10

Sé que puedo asignar IP estática manualmente, usando /etc/network/interfaces.

También sé que puedo leer la dirección MAC del contenedor LXC (por ejemplo, buscando la lxc.network.hwaddrentrada /var/lib/lxc/<container-name>/configy asignando la IP utilizando las entradas dhcp-host=<mac-addr>,10.0.3.3en /etc/dnsmasq.d/<some file>.

En el archivo /etc/default/lxc-netleí

# 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

Eso satisfaría mis necesidades; desafortunadamente hacerlo no tiene efecto.

Adam Ryczkowski
fuente
2
Funciona para mí, pero tenga en cuenta que debe reiniciar lxc-net para que surta efecto. Y existe un problema conocido de que lxc-net no se reinicia si actualmente se inicia algún contenedor. Debe detenerlos todos y luego reiniciar el servicio lxc-net.
HRJ
Además, no pude asignar direcciones IP usando solo el nombre del contenedor. Tuve que codificar una dirección MAC para el contenedor y para la configuración de DHCP.
HRJ
@HRJ, ¿podría publicar su archivo dnsmasq.conf por favor?
tonytony
@HRJ En Ubuntu 14.04 reiniciar lxc-netno ayuda si no quitas tu puente lxcbr0. Mira mi respuesta.
Adam Ryczkowski

Respuestas:

17

Me encontré con esto recientemente y creo que encontré una solución fácil. (Solo) lo probé en Ubuntu 14.04.

Primero, descomente esta línea / etc / default / lxc-net:

LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

En /etc/lxc/dnsmasq.conf, defina un archivo dhcp-hosts:

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

Luego agregue entradas en /etc/lxc/dnsmasq-hosts.conf así:

mail,10.0.3.16
web,10.0.3.17

Cuidado: los cambios se harán efectivos después de reiniciar lxc-net (que reinicia dnsmasq):

service lxc-net restart

Luego puede modificar /etc/lxc/dnsmasq-hosts.conf y enviar la señal SIGHUP a dnsmasq:

killall -s SIGHUP dnsmasq

Entonces sí, necesita reiniciar lxc-net, pero solo una vez. Espero que esto ayude.

mtp
fuente
Me gusta la idea de delegar la lista de hosts a un archivo externo. Además de eso, su método difiere del mío debido a killall -s SIGHUP dnsmasq. Estoy de acuerdo, que solo "SIGHUP-ing" dnsmasq es más eficiente que reiniciar todo el demonio (especialmente si no funciona sin parchear sus scripts de inicio).
Adam Ryczkowski
Reiniciar el servicio lxc-netsolo es necesario para que dnsmasq use la configuración de /etc/lxc/dnsmasq.conf (y esta información está presente en lo /etc/default/lxc-netque es desconocido para el dnsmasq). Si lo configuró antes, solo bastará con otro SIGHUP.
Adam Ryczkowski
Cuidado: lxc-net no reiniciará dnsmasq si hay contenedores en ejecución.
s3v3n
OMI, esta es la mejor respuesta
s3v3n
kill -HUP $(cat /var/run/lxc/dnsmasq.pid)si no desea instalar killallo volver a cargar otras dnsmasqinstancias
gertas
4

Funciona bien en Ubuntu 14.04.1

Descomenta esta línea /etc/default/lxc-net

#LXC_DHCP_CONFILE=/etc/lxc/dnsmasq.conf

Detenga todos los contenedores, reinicie lxc-net:

service lxc-net restart

Configurar direcciones IP en /etc/lxc/dnsmasq.conf

dhcp-host={NAME},10.0.3.2

donde {NAME}está el nombre de su contenedor LXC:

/var/lib/lxc/{NAME}
Tombart
fuente
Solo funciona si el script puede cerrar la red lxcbr0 , lo que excluye el caso cuando hay otros contenedores lxc ejecutándose. En resumen, tal como está ahora, no puede asignar arriendos estáticos de dhcp sin reiniciar todos los contenedores.
Adam Ryczkowski
Sí, es cierto, es bastante inconveniente :(. Encuentro una solución mucho más fácil para editar el /var/lib/lxc/<container-name>/rootfs/etc/network/interfacesarchivo y asignar una dirección IP estática al contenedor.
Tombart
Es cierto, pero no hay nada que lo proteja contra dar a dos invitados la misma IP. Vea mi respuesta aceptada: resuelve el problema.
Adam Ryczkowski el
1

La respuesta de Tombart funciona si tiene la paciencia suficiente para esperar la actualización de DNS Y está dispuesto a reiniciar el contenedor (el invitado) después.

Lo que sigue es la receta que requiere que todos los demás contenedores lxc que se estén ejecutando estén cerrados . Si no puede permitirse eso, entonces no veo forma de forzar una nueva configuración de dnsmasq. (Para algunos HUP de señalización razonable al pid de dnsmasq que se encuentra /run/lxc/dnsmasq.pidtampoco funciona).

Entonces, si desea tener algo que funcione instantáneamente y no hay otros contenedores lxc ejecutándose, siga mi respuesta. $namees el nombre del nodo para el que queremos restablecer la asignación y $internalifes el nombre del adaptador puenteado de LXC. Puede obtener el valor de $internalifcon, por ejemplo, augtool -L -A --transform "Shellvars incl /etc/default/lxc-net" get "/files/etc/default/lxc-net/LXC_BRIDGE" | sed -En 's/\/.* = (.*)/\1/p'si instala, augeas-toolspero generalmente es justo 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

Desafortunadamente, hay un error (¿característica?) En /etc/init/lxc-net.confUbuntu 14.04 que impide la recarga a dnsmasqmenos que el dispositivo puente esté inactivo para el host.

Adam Ryczkowski
fuente
0

Esta solución funciona parcheando los scripts de inicio lxc. Divide la compleja tarea de levantar el puente lxcbr0 y comenzar un dnsmasqen dos trabajos separados. Ahora no necesita reiniciar todo el lxc-netpuente para volver a cargarlo: la dnsmasqrecarga sudo service restart lxc-dnsmasqes suficiente y no requiere cerrar el puente.

  1. Detenga el servicio lxc-net sudo service lxc-net stopy asegúrese de que no haya un puente lxcbr0 (o equivalente).
  2. Reemplace el contenido del /etc/init/lxc-net.confcon el siguiente contenido:

.

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. Agregue otro archivo, /etc/init/lxc-dnsmasqcon los siguientes contenidos:

.

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
fuente
0

Aquí hay una secuencia de comandos simple de Python que lanza el contrato de arrendamiento dnsmasq de LXC. Puede ejecutarlo desde la máquina host o falsificarlo desde otro contenedor, ¡sí, eso funciona !:

#!/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')]))

El requisito previo para lo anterior es la biblioteca de python scapy:

pip install scapy

Una vez ejecutado, debería ver en el registro del sistema algo como:

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

Para confirmar, simplemente verifique si se eliminó la entrada de /var/lib/misc/dnsmasq.lxcbr0.leases. El contenedor mismo mantendrá la IP, por lo que debe detenerse antes de comenzar cualquier contenedor nuevo que deba reutilizar la IP.

gertas
fuente
1
¡Eso es genial! ¡Ni siquiera sabía que DHCP lo admite! Voy a votar inmediatamente después de confirmar que funciona.
Adam Ryczkowski
0

Me doy cuenta de que mi respuesta lleva años de retraso, pero tal vez ayude a alguien más. ¡El problema fue que editó el código específico del paquete ( write_lxc_netfunción) Ubuntu LXC que estaba destinado a escribirse en otro destino como una cadena, no procesado dentro del lxc-netscript mismo!

Como resultado, el proceso dnsmasq no recibió el archivo de configuración que intentó pasar, dejándolo "sin efecto", como usted dice.

En su lugar, desearía establecer esta variable cerca de la parte superior del script, entre el resto:

#!/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
fuente