[SOLVED] isc-dhcp и ipset

Проблема с вызовом execute("/usr/sbin/ipset"...) в обработчике on commit
Вариант решения.

Доброго Времени суток, уважаемые!

Что имеем

  • Gentoo 13:
    #uname -a
    Linux gw 4.0.5-gentoo #8 SMP Sun Nov 1 20:15:58 EET 2015 x86_64 Intel(R) Core(TM)2 Duo CPU E7400 @ 2.80GHz GenuineIntel GNU/Linux
  • net-misc/dhcp-4.3.1-r2::gentoo USE="client ldap server ssl -ipv6 (-selinux) -vim-syntax"
  • net-firewall/ipset-6.20.1::gentoo USE="-modules"
  • Права на ipset:
    #ls -l /usr/sbin/ip*
    -rwxr-xr-x 1 root root 22792 Nov  1 21:43 /usr/sbin/ipset

Задача

При выделении сервером DHCP IP-адреса клиенту зафиксировать пару (IP_клиента,MAC_клиента) в наборе ipset с именем lan.hosts.dhcp

Решение

  • Создаём ipset

    #ipset -L
    Name: lan.hosts.dhcp
    Type: bitmap:ip,mac
    Revision: 2
    Header: range 192.168.1.0-192.168.1.255 timeout 0 comment
    Size in memory: 22680
    References: 1
  • Создаём обработчик
    #cat /etc/dhcp/dhcpd.conf
    shared-network lan {
    ...SKIP...
        subnet 192.168.1.0 netmask 255.255.255.0 {
            interface lan;
            on commit {
                set macAddress = concat(
                    suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,1,1))),2),":",
                    suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,2,1))),2),":",
                    suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,3,1))),2),":",
                    suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,4,1))),2),":",
                    suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,5,1))),2),":",
                    suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,6,1))),2)
                );
                set ipAddress = binary-to-ascii(10,8,".",leased-address);
    
                execute ("/usr/sbin/ipset", "add", "-exist", "lan.hosts.dhcp", concat(ipAddress,",",macAddress));
    
                unset macAddress;
                unset ipAddress;
            } #on commit
    ...SKIP...
  • Запускаем демон dhcpd:
    #ps ax |grep dhcp
    20104 ?        Ss     0:00 /usr/sbin/dhcpd -cf /etc/dhcp/dhcpd.conf -q -pf /var/run/dhcp/dhcpd.pid -lf /var/lib/dhcp/dhcpd.leases -user dhcp -group dhcp -chroot / lan

Проблема

IP-адрес выделяется, но /usr/sbin/ipset add не выполняется или выполняется с ошибкой (status 256):

#tail -f /var/log/dhcp.log
Jan 10 16:24:52 gw dhcpd[20104]: DHCPDISCOVER from 60:a4:4c:3b:c9:97 via lan
Jan 10 16:24:52 gw dhcpd[20104]: DHCPOFFER on 192.168.1.80 to 60:a4:4c:3b:c9:97 via lan
Jan 10 16:24:52 gw dhcpd[20104]: from the dynamic address pool for lan
Jan 10 16:24:52 gw dhcpd[20104]: execute_statement argv[0] = /usr/sbin/ipset
Jan 10 16:24:52 gw dhcpd[20104]: execute_statement argv[1] = add
Jan 10 16:24:52 gw dhcpd[20104]: execute_statement argv[2] = -exist
Jan 10 16:24:52 gw dhcpd[20104]: execute_statement argv[3] = lan.hosts.dhcp
Jan 10 16:24:52 gw dhcpd[20104]: execute_statement argv[4] = 192.168.1.80,60:a4:4c:3b:c9:97
Jan 10 16:24:52 gw dhcpd[20104]: execute: /usr/sbin/ipset exit status 256
Jan 10 16:24:52 gw dhcpd[20104]: DHCPREQUEST for 192.168.1.80 (192.168.1.1) from 60:a4:4c:3b:c9:97 via lan
Jan 10 16:24:52 gw dhcpd[20104]: DHCPACK on 192.168.1.80 to 60:a4:4c:3b:c9:97 via lan

В результате запись в lan.hosts.dhcp не производится.

Вопросы

  1. Что за "status 256"?
  2. Как можно это отладить?

Вариант решения.

"Отлазил" как смог...

  1. Создал скрипт /etc/dhcp/dhcp-events
    cmd="$1"; ipset="$2"; ip="$3";
    case "${cmd}" in
        "commit")
            mac="$4";
            /usr/sbin/ipset add -exist ${ipset} ${ip},${mac} 2>/var/dhcp.on-commit;
        ;;
        "release")
            /usr/sbin/ipset del -exist ${ipset} ${ip};
        ;;
        "expire")
            /usr/sbin/ipset del -exist ${ipset} ${ip};
        ;;
    esac
  2. Задал ему нужные права:
    -rwxr-xr-x 1 root root  370 Jan 12 10:13 dhcpd-events
  3. Подправил обработчик on commit:

                on commit {
    
                     set macAddress = concat(
                        suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,1,1))),2),":",
                        suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,2,1))),2),":",
                        suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,3,1))),2),":",
                        suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,4,1))),2),":",
                        suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,5,1))),2),":",
                        suffix(concat("0",binary-to-ascii(16,8,"", substring(hardware,6,1))),2)
                    );
    
                    set ipAddress = binary-to-ascii(10,8,".",leased-address);
    
    execute ("/usr/sbin/ipset", "add", "-exist", "wlan.hosts.wl", concat(ipAddress,",",macAddress));
                    execute ("/etc/dhcp/dhcpd-events", "commit", "wlan.hosts.dhcp", ipAddress, macAddress);
    
                    unset macAddress;
                    unset ipAddress;
                } #on commit
    
  4. Вот что я увидел в файле /var/dhcp.on-commit:

    ipset v6.20.1: Kernel error received: Operation not permitted

Я в растерянности...

Вариант решения

#ps ax |grep dhcp
20104 ?        Ss     0:00 /usr/sbin/dhcpd -cf /etc/dhcp/dhcpd.conf -q -pf /var/run/dhcp/dhcpd.pid -lf /var/lib/dhcp/dhcpd.leases -user dhcp -group dhcp -chroot / lan

Здесь мы видим, что:

  1. демон запускается от имени пользователя dhcp:dhcp
  2. и chroot-ится в /

Соответственно ему не хватает прав на выполнение /usr/sbin/ipset

Рассмотрим вариант решения с использованием sudoers.

  1. Создаём файл /etc/sudoers.d/local-firewall:
    Cmnd_Alias      FIREWALL = /usr/sbin/ipset, /sbin/iptables, /bin/ip
    
    %dhcp   ALL=NOPASSWD:    FIREWALL
    
  2. Правим скрипт обработчика событий /etc/dhcp/dhcp-events:
    #!/bin/bash
    
    cmd="$1"; ipset="$2"; ip="$3";
    
    case "${cmd}" in
        "commit")
            mac="$4";
            -/usr/sbin/ipset add -exist ${ipset} ${ip},${mac} 2>/var/dhcp.on-commit;
           +/usr/bin/sudo /usr/sbin/ipset add -exist ${ipset} ${ip},${mac} 2>/var/dhcp.on-commit;
        ;;
        "release")
            -/usr/sbin/ipset del -exist ${ipset} ${ip};
            +/usr/bin/sudo /usr/sbin/ipset del -exist ${ipset} ${ip};
        ;;
        "expire")
            -/usr/sbin/ipset del -exist ${ipset} ${ip};
            +/usr/bin/sudo /usr/sbin/ipset del -exist ${ipset} ${ip};
        ;;
    

Теперь всё работает.

Вопрос:

Есть другие варианты решения?

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".