Page MenuHomeVyOS Platform

DHCP `ping-check` enabled by default
Closed, ResolvedPublicBUG

Description

It appears that in Sagitta the ping-check option of the DHCP server is enabled by default.

This conflicts with the per-network ping-check option, which allows us to enable to feature on a per network basis. As this option only allows us to enable the feature, there is no way of turning the check off.

The impact of having the ping-check enabled by default is noticeable when you have Linux users, using network-manager, roaming on your wireless. As NM will verify its DHCP lease when hopping BSSID's, but keeps its IP in the meantime (behavior described here: https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/527). Which will result in the following entry in our DHCP log:

dhcpd[2316]: ICMP Echo reply while lease 192.168.10.117 valid.
dhcpd[2316]: Abandoning IP address 192.168.10.117: pinged before offer

As a workaround you can disable the ping-check using custom parameters, like so:

set service dhcp-server global-parameters "ping-check false;"

If the feature should be enabled by default is up to the maintainers, but there should at least be the option to toggle it.

Details

Version
VyOS 1.4-rolling-202207290217
Is it a breaking change?
Behavior change
Issue type
Bug (incorrect behavior)

Event Timeline

ping-check shouldn't be allowed by default
To enable it you have to set set service dhcp-server shared-network-name Lan01 ping-check
There is no configuration in generated .conf:

vyos@r14# cat /run/dhcp-server/dhcpd.conf | grep ping
[edit]
vyos@r14#

So maybe it is default isc-dhcp-server behaviour

As remarked and as expected, this option is not enable by default.
Proofs:

  • Fist scenario: no ping-check option introduced in configuration:
###########################
## VyOS dhcp-server configuration
vyos@vyos# run show config comm | grep dhcp
set service dhcp-server shared-network-name ETH3-LAN subnet 198.51.100.0/24 default-router '198.51.100.1'
set service dhcp-server shared-network-name ETH3-LAN subnet 198.51.100.0/24 name-server '8.8.8.8'
set service dhcp-server shared-network-name ETH3-LAN subnet 198.51.100.0/24 range 0 start '198.51.100.100'
set service dhcp-server shared-network-name ETH3-LAN subnet 198.51.100.0/24 range 0 stop '198.51.100.200'


####################################
### See no ping-check option in config file ###

vyos@vyos# cat /run/dhcp-server/dhcpd.conf
### Autogenerated by dhcp_server.py ###

# For options please consult the following website:
# https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html
#
# log-facility local7;

ddns-update-style none;
option rfc3442-static-route code 121 = array of integer 8;
option windows-static-route code 249 = array of integer 8;
option wpad-url code 252 = text;

# Vendor specific options - Ubiquiti Networks
option space ubnt;
option ubnt.unifi-controller code 1 = ip-address;
class "ubnt" {
    match if substring (option vendor-class-identifier , 0, 4) = "ubnt";
    option vendor-class-identifier "ubnt";
    vendor-option-space ubnt;
}

# Shared network configration(s)
shared-network ETH3-LAN {
    subnet 198.51.100.0 netmask 255.255.255.0 {
        option domain-name-servers 8.8.8.8;
        option routers 198.51.100.1;
        default-lease-time 86400;
        max-lease-time 86400;
        pool {
            range 198.51.100.100 198.51.100.200;
        }  
    }
    on commit {
        set shared-networkname = "ETH3-LAN";
    }
}


### TCPDUMP on interface, shows no icmp entry while a client request ip address.
vyos@vyos# sudo tcpdump -i eth3
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth3, link-type EN10MB (Ethernet), snapshot length 262144 bytes
17:00:02.583914 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:50:79:66:68:05 (oui Unknown), length 364
17:00:02.584551 IP 198.51.100.1 > 198.51.100.101: ICMP echo request, id 25271, seq 0, length 28
17:00:02.584837 IP 198.51.100.101 > 198.51.100.1: ICMP echo reply, id 25271, seq 0, length 28
17:00:03.583854 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:50:79:66:68:05 (oui Unknown), length 364
17:00:03.584209 ARP, Request who-has 198.51.100.102 tell 198.51.100.1, length 28
17:00:04.584547 IP 198.51.100.1.bootps > 198.51.100.102.bootpc: BOOTP/DHCP, Reply, length 300
17:00:04.601124 ARP, Request who-has 198.51.100.102 tell 198.51.100.1, length 28
17:00:05.625126 ARP, Request who-has 198.51.100.102 tell 198.51.100.1, length 28
17:00:06.583975 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:50:79:66:68:05 (oui Unknown), length 364
17:00:06.586376 IP 198.51.100.1.bootps > 198.51.100.102.bootpc: BOOTP/DHCP, Reply, length 300
17:00:07.584043 ARP, Request who-has 198.51.100.102 (Broadcast) tell 198.51.100.102, length 50
17:00:07.929143 ARP, Request who-has 198.51.100.101 tell 198.51.100.1, length 28
17:00:08.584255 ARP, Request who-has 198.51.100.102 (Broadcast) tell 198.51.100.102, length 50
17:00:08.953145 ARP, Request who-has 198.51.100.101 tell 198.51.100.1, length 28
17:00:09.585198 ARP, Request who-has 198.51.100.102 (Broadcast) tell 198.51.100.102, length 50
17:00:09.977119 ARP, Request who-has 198.51.100.101 tell 198.51.100.1, length 28

And after adding ping-check option: we see:

### Print config comm with ping check
vyos@vyos# run show config comm | grep ping-check
set service dhcp-server shared-network-name ETH3-LAN ping-check
[edit]

## Verify config is present in config file
vyos@vyos# cat /run/dhcp-server/dhcpd.conf | grep ping
    ping-check true;
[edit]


## Finally, tcpdump
vyos@vyos# sudo tcpdump -i eth3
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth3, link-type EN10MB (Ethernet), snapshot length 262144 bytes
17:04:14.823826 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:50:79:66:68:05 (oui Unknown), length 364
17:04:14.824294 IP 198.51.100.1 > 198.51.100.102: ICMP echo request, id 58325, seq 0, length 28
17:04:15.823879 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:50:79:66:68:05 (oui Unknown), length 364
17:04:15.824608 IP 198.51.100.1.bootps > 198.51.100.102.bootpc: BOOTP/DHCP, Reply, length 300
17:04:18.824030 IP 0.0.0.0.bootpc > 255.255.255.255.bootps: BOOTP/DHCP, Request from 00:50:79:66:68:05 (oui Unknown), length 364
17:04:18.824238 IP 198.51.100.1.bootps > 198.51.100.102.bootpc: BOOTP/DHCP, Reply, length 300
17:04:19.824061 ARP, Request who-has 198.51.100.102 (Broadcast) tell 198.51.100.102, length 50
17:04:19.833123 ARP, Request who-has 198.51.100.102 tell 198.51.100.1, length 28
17:04:19.833246 ARP, Reply 198.51.100.102 is-at 00:50:79:66:68:05 (oui Unknown), length 28
17:04:20.824617 ARP, Request who-has 198.51.100.102 (Broadcast) tell 198.51.100.102, length 50
17:04:21.825454 ARP, Request who-has 198.51.100.102 (Broadcast) tell 198.51.100.102, length 50

Allow me to proof the opposite.

Explicitly disabling ping-check using the workaround

vyos@mauer:~$ cat /run/dhcp-server/dhcpd.conf | grep ping
ping-check false;

vyos@mauer:~$ tcpdump -ni bond0.10 port bootps or port bootpc or icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on bond0.10, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:06:13.555352 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 3c:f0:11:67:dd:d3, length 289
20:06:13.555353 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 3c:f0:11:67:dd:d3, length 289
20:06:13.556404 IP 192.168.10.1.67 > 192.168.10.93.68: BOOTP/DHCP, Reply, length 318
20:06:13.557034 IP 192.168.10.1.67 > 192.168.10.93.68: BOOTP/DHCP, Reply, length 318
20:06:13.558845 IP 192.168.10.93 > 192.168.10.1: ICMP 192.168.10.93 udp port 68 unreachable, length 354
20:06:13.559012 IP 192.168.10.93 > 192.168.10.1: ICMP 192.168.10.93 udp port 68 unreachable, length 354
20:06:13.559233 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 3c:f0:11:67:dd:d3, length 295
20:06:13.559321 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 3c:f0:11:67:dd:d3, length 295
20:06:14.150639 IP 192.168.10.1.67 > 192.168.10.93.68: BOOTP/DHCP, Reply, length 318
20:06:14.153244 IP 192.168.10.93 > 192.168.10.1: ICMP 192.168.10.93 udp port 68 unreachable, length 354
20:06:14.726676 IP 192.168.10.1.67 > 192.168.10.93.68: BOOTP/DHCP, Reply, length 318
### Autogenerated by dhcp_server.py ###

# For options please consult the following website:
# https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html
#
# log-facility local7;
on release {
    set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
    set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
    execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", "");
}
on expiry {
    set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
    set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
    execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", "");
}

use-host-decl-names on;
ddns-update-style none;
option rfc3442-static-route code 121 = array of integer 8;
option windows-static-route code 249 = array of integer 8;
option wpad-url code 252 = text;

# Vendor specific options - Ubiquiti Networks
option space ubnt;
option ubnt.unifi-controller code 1 = ip-address;
class "ubnt" {
    match if substring (option vendor-class-identifier , 0, 4) = "ubnt";
    option vendor-class-identifier "ubnt";
    vendor-option-space ubnt;
}

# The following 1 line(s) have been added as
# global-parameters in the CLI and have not been validated !!!
ping-check false;


# Shared network configration(s)
shared-network LAN {
    authoritative;
    option domain-name "redacted";
    option domain-search "redacted";
    subnet 192.168.10.0 netmask 255.255.255.128 {
        option domain-name-servers 192.168.10.1;
        option routers 192.168.10.1;
        default-lease-time 86400;
        max-lease-time 86400;
        pool {
            range 192.168.10.80 192.168.10.120;
        }
    }
    on commit {
        set shared-networkname = "LAN";
        set ClientIp = binary-to-ascii(10, 8, ".", leased-address);
        set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
        set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name, "empty_hostname");
        if not (ClientName = "empty_hostname") {
            set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
            execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "commit", ClientName, ClientIp, ClientMac, ClientDomain);
        } else {
            log(concat("Hostname is not defined for client with IP: ", ClientIP, " MAC: ", ClientMac));
        }
    }
}

No special DHCP options set

vyos@mauer:~$ cat /run/dhcp-server/dhcpd.conf | grep ping

vyos@mauer:~$ tcpdump -ni bond0.10 port bootps or port bootpc or icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on bond0.10, link-type EN10MB (Ethernet), snapshot length 262144 bytes
20:07:41.030229 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 3c:f0:11:67:dd:d3, length 300
20:07:41.030229 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 3c:f0:11:67:dd:d3, length 300
20:07:41.031508 IP 192.168.10.1 > 192.168.10.93: ICMP echo request, id 22262, seq 0, length 28
20:07:41.035771 IP 192.168.10.93 > 192.168.10.1: ICMP echo reply, id 22262, seq 0, length 28
20:07:43.228146 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 3c:f0:11:67:dd:d3, length 300
20:07:43.228146 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 3c:f0:11:67:dd:d3, length 300
20:07:44.230192 IP 192.168.10.1.67 > 192.168.10.103.68: BOOTP/DHCP, Reply, length 318
20:07:44.237352 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 3c:f0:11:67:dd:d3, length 300
20:07:44.237353 IP 0.0.0.0.68 > 255.255.255.255.67: BOOTP/DHCP, Request from 3c:f0:11:67:dd:d3, length 300

vyos@mauer:~$ show log dhcp server·
--- %< ---  SNIP --- %< ---
Aug 09 20:07:14 dhcpd[13734]: Server starting service.
Aug 09 20:07:41 dhcpd[13734]: reuse_lease: lease age 21119 (secs) under 25% threshold, reply with unaltered, existing lease for 192.168.10.93
Aug 09 20:07:41 dhcpd[13734]: DHCPDISCOVER from 3c:f0:11:67:dd:d3 (greta) via bond0.10
Aug 09 20:07:41 dhcpd[13734]: ICMP Echo reply while lease 192.168.10.93 valid.
Aug 09 20:07:41 dhcpd[13734]: Abandoning IP address 192.168.10.93: pinged before offer
### Autogenerated by dhcp_server.py ###

# For options please consult the following website:
# https://www.isc.org/wp-content/uploads/2017/08/dhcp43options.html
#
# log-facility local7;
on release {
    set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
    set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
    execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", "");
}
on expiry {
    set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name);
    set ClientIp = binary-to-ascii(10, 8, ".",leased-address);
    execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "release", "", ClientIp, "", "");
}

use-host-decl-names on;
ddns-update-style none;
option rfc3442-static-route code 121 = array of integer 8;
option windows-static-route code 249 = array of integer 8;
option wpad-url code 252 = text;

# Vendor specific options - Ubiquiti Networks
option space ubnt;
option ubnt.unifi-controller code 1 = ip-address;
class "ubnt" {
    match if substring (option vendor-class-identifier , 0, 4) = "ubnt";
    option vendor-class-identifier "ubnt";
    vendor-option-space ubnt;
}


# Shared network configration(s)
shared-network LAN {
    authoritative;
    option domain-name "redacted";
    option domain-search "redacted";
    subnet 192.168.10.0 netmask 255.255.255.128 {
        option domain-name-servers 192.168.10.1;
        option routers 192.168.10.1;
        default-lease-time 86400;
        max-lease-time 86400;
        pool {
            range 192.168.10.80 192.168.10.120;
        }
    }
    on commit {
        set shared-networkname = "LAN";
        set ClientIp = binary-to-ascii(10, 8, ".", leased-address);
        set ClientMac = binary-to-ascii(16, 8, ":", substring(hardware, 1, 6));
        set ClientName = pick-first-value(host-decl-name, option fqdn.hostname, option host-name, "empty_hostname");
        if not (ClientName = "empty_hostname") {
            set ClientDomain = pick-first-value(config-option domain-name, "..YYZ!");
            execute("/usr/libexec/vyos/system/on-dhcp-event.sh", "commit", ClientName, ClientIp, ClientMac, ClientDomain);
        } else {
            log(concat("Hostname is not defined for client with IP: ", ClientIP, " MAC: ", ClientMac));
        }
    }
}

diff of the two configs

vyos@mauer:~$ diff /tmp/dhcp-no-workaround.conf /tmp/dhcp-with-workaround.conf
32a33,36
> # The following 1 line(s) have been added as
> # global-parameters in the CLI and have not been validated !!!
> ping-check false;
>

What version you are using?

In my labs:

  • I see no ICMP with defaults config (no global-paramenter set)
  • I see no ICMP with global-option set like set service dhcp-server global-parameters 'ping-check false;'
  • I see ICMP packets if:
    • Add global-parameter -->set service dhcp-server global-parameters 'ping-check true;'
    • Or, adding ping-check option in shared-nework --> set service dhcp-server shared-network-name ETH3-LAN ping-check

I've verified this behavior with 1.4-rolling-202207290217 and 1.4-rolling-202204250217.

I would expect the most important software package version to be isc-dhcp-server, which is currently at version 4.4.1-2.3.

I'm happy to provide a more complete configuration dump if needed, but I can't imagine anything outside of the dhcpd.conf to influence this.

m4rcu5 claimed this task.

I've recently migrated from a PCEngines APU2C4 to a Wyse 5070 with a X520 card, as well as upgrading to VyOS 1.4-rolling-202305081003
After which I was unable to reproduce this issue. Roaming now works fine without the ICMP check.

I'll mark this one as resolved, even though I am not sure what fixed it in the end.