Bug #15702
closedIPv4 DHCP client responses may be routed unexpectedly out unrelated WANs
100%
Description
When there are multiple DHCP client interfaces on an installation, DHCP ACK packets from DHCP servers on some interfaces may be routed unexpectedly in certain situations, leading to a potential information disclosure.
Notably, this happens when an interface address is renewed, such as by clicking the button on Status > Interfaces. The DHCP ACK packet sent by the WAN2 DHCP server is processed by dhclient
but at the time that ACK packet arrives, the destination address is not yet configured on an interface. Since the destination address is not on an interface, the OS does not know the packet is local, so it routes the packet according to the route table. In most cases this means the DHCP ACK from WAN2 will egress toward the WAN1 gateway. The ACK still has the source address of the WAN2 DHCP server and destination of what should be the new WAN2 address.
Since the DHCP ACK packet from WAN2 contains address information from WAN2, but is sent out WAN1, the gateway on WAN1 receives information about addresses on WAN2, thus it is a potential information disclosure.
The easiest way to reproduce this is to configure two DHCP client WANs on different segments, packet capture on both segments (upstream or locally), and then release/renew on WAN2. The DHCP request goes out WAN2, then the ACK comes back in WAN2 and then exits out WAN1.
A potential workaround that appears to suppress the behavior is to remove state tracking from the DHCP rules and also tag inbound packets so they can be prevented from egressing other WANs:
diff --git a/src/etc/inc/filter.inc b/src/etc/inc/filter.inc
index 398b01ca87..f723eaa3ca 100644
--- a/src/etc/inc/filter.inc
+++ b/src/etc/inc/filter.inc
@@ -3935,6 +3935,7 @@ EOD;
* Useful for protecting against sudden outbursts, etc.
*/
$ipfrules .= "block in {$log['block']} quick from <virusprot> to any ridentifier 1000000400 label \"virusprot overload table\"\n";
+ $ipfrules .= "block out quick proto udp from any port = 67 to any port = 68 tagged \"dhcpin\" ridentifier {$increment_tracker()} label \"Prevent routing dhcp responses\"\n";
foreach ($FilterIflist as $on => $oc) {
$saved_tracker += 10;
@@ -3948,8 +3949,8 @@ EOD;
}
$ipfrules .= <<<EOD
# allow our DHCP client out to the {$oc['descr']}
-pass in {$log['pass']} quick on \${$oc['descr']} proto udp from any port = 67 to any port = 68 ridentifier {$increment_tracker()} label "{$fix_rule_label("allow dhcp replies in {$oc['descr']}")}"
-pass out {$log['pass']} quick on \${$oc['descr']} proto udp from any port = 68 to any port = 67 ridentifier {$increment_tracker()} label "{$fix_rule_label("allow dhcp client out {$oc['descr']}")}" {$vlantag}
+pass in {$log['pass']} quick on \${$oc['descr']} proto udp from any port = 67 to any port = 68 tag "dhcpin" no state ridentifier {$increment_tracker()} label "{$fix_rule_label("allow dhcp replies in {$oc['descr']}")}"
+pass out {$log['pass']} quick on \${$oc['descr']} proto udp from any port = 68 to any port = 67 no state ridentifier {$increment_tracker()} label "{$fix_rule_label("allow dhcp client out {$oc['descr']}")}" {$vlantag}
# Not installing DHCP server firewall rules for {$oc['descr']} which is configured for DHCP.
EOD;
It's not clear if that is the best solution, however, and it needs more testing to ensure it doesn't lead to any other issues.
Updated by Jim Pingle 3 months ago
- Subject changed from Race condition in IPv4 DHCP client response may lead to inbound DHCP ACK packet being routed unexpectedly to IPv4 DHCP client responses may be routed unexpectedly out unrelated WANs
- Description updated (diff)
Updated description + diff based on further testing.
Updated by Jim Pingle 2 months ago
All indications are that the latest revision of the workaround is operating OK in lab testing, both internally and from the original reporter. It's ready for wider testing.
If we find further issues or come up with a better fix, we can continue to work on it as needed.
Updated by Jim Pingle 2 months ago
- Status changed from Confirmed to Feedback
- % Done changed from 0 to 100
Applied in changeset a039ec6ad853ef1673cc986127542a51d884f5a0.
Updated by Jim Pingle 2 months ago
- Status changed from Feedback to Resolved
Seems to be behaving on current snapshots on everything in my lab. It's also in the most recent public snapshot, and so far I haven't seen any reports of DHCP client issues. If someone does spot an issue we can treat it separately.
Updated by Jim Pingle about 2 months ago
- Plus Target Version changed from 24.08 to 24.11