| Next revision | Previous revision | 
| make_a_dd-wrt_bridge_silently_eat_dhcp_traffic [2008/04/01 18:28]  – created tkbletsc | make_a_dd-wrt_bridge_silently_eat_dhcp_traffic [2008/04/11 21:17] (current)  –  tkbletsc | 
|---|
|  | ===== Introduction ===== | 
|  |  | 
| We have a pair of WRT54GL's running DD-WRT as a WDS bridge.  It works great, except we both have our own cable modem and routers.  Each router functions as a DHCP server.  Because we're bridged, this means that we have two competing DHCP servers on the same LAN, so sometimes a machine will pick the other router as it's gateway.  This means that Internet traffic would be crammed through our tenuous bridge, making much sadness. | We have a pair of WRT54GL's running DD-WRT as a WDS bridge.  It works great, except we both have our own cable modem and routers.  Each router functions as a DHCP server.  Because we're bridged, this means that we have two competing DHCP servers on the same LAN, so sometimes a machine will pick the other router as it's gateway.  This means that Internet traffic would be crammed through our tenuous bridge, making much sadness. | 
|  |  | 
| The correct solution is to have separate subnets with routing and blah blah blah. | The correct solution is to have separate subnets with routing and blah blah blah. | 
|  |  | 
| Screw that.  The quick and dirty solution is just to ban DHCP traffic from the bridge.  After some trial and error, I found the iptables rules that would do that: | Screw that.  The quick and dirty solution is just to ban DHCP traffic from the bridge. | 
|  |  | 
| iptables -t mangle -I PREROUTING 1 -p UDP --sport 67 -j DROP | ===== HOWTO ===== | 
| iptables -t mangle -I PREROUTING 1 -p UDP --sport 68 -j DROP |  | 
| iptables -t mangle -I PREROUTING 1 -p UDP --dport 67 -j DROP |  | 
| iptables -t mangle -I PREROUTING 1 -p UDP --dport 68 -j DROP |  | 
|  |  | 
| The only question then is how to make these rules get applied automatically at bootup.  [[http://linuxwhore.com/modules.php?name=News&file=article&sid=155&mode=thread&order=0&thold=0|This article]] covers that: just use the 'rc_firewall' value in the nvram.  At the router's command prompt: | Go to Administration | Commands, and paste this: | 
|  | <file> | 
|  | echo "begin-base64 644 -" > /tmp/ebt_ip.o.gz.u64 | 
|  | echo "H4sIADwAAAACA5VWz28bVRD+dteON20KG9eq3BJUB21UVy1m2+RQRCO5cX5w" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "yMGHHpAQcr32Eq9wHMveIFAPNSkHDq7wIb1H5R+p0gpx7J8QtaH8EBfuSGbm" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "vbdh8whEHelp9ps3883Mm/ecPFhZXzUMA7EYsPEPAv5Ikc1BdUGgIt7CWSQl" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "i5ejFJY8B2VntjrAecIFPByyLUM2B4cjA43RGDveN6g4HJMD7CxeH9nvo5KT" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "XK9HNva9KsUxPo/fiKvyyMZ7N5hrmrgmVUxHcV0hrmm8OrK3FBfbJmC6FnyK" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "M92P4At7AUuPBsRZwHMPWBq+TXUOHBN5DJzZsg8T5uM8DnfHqHi4ZMHMmpjL" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "+7hWaCKNQW62CFzCy91rTgUW1VSg2gykXdZpwgae3FpDWeRap9oc6qeCPYH5" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "+6LqDZQnd0qeCyqPqWI4D5+vQzXHua6rXBvqTIsqlzzffS9LfiZpORc+y8Oh" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "oWYD/Dycgj90nWXqaUXkuE887B/bc1gRfGzL8YwdiBmniIf5TMU1hV+GjohZ" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "QwbLgsvGgcX+sd1K2A2aCe/xtzybH76fIdsNmtPv47Rr49muTfh9NbcU9kXd" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "V1W/WboLT8lvjIee6wR0ZtLOtbnOipgN4x8pBfN58L0zYl47Xh73HLbpdyR7" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "dEd21N1l31e78bwpXtTmqP14RjnyUXMS+2yXve9x5beBi7Q+vGKjQL1+655s" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "Oy5hF6fKx+a/bX9l8ARvIO/SuvwfXMn9gvX/+wun7LfDRtDpB4tr1XV8EfQ6" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "Qbv2ZdDrh1udxZulhdK8x86l/tebUd0nHfWkbsVfvaBdioKvIvnVrEd1lPx+" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "n+FG2Pl8S9q7zR5Km83A394o1f1w/iahrabYfwO5LN4aMKFwmVY10Z96wHiH" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "1mQi7hMb4LFNqfiUuOvAVYVjipElOXW+OY3vJwrOKz4rwfeB0jHfC+3sY74F" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "2UPXTPjlE37Mx/iOqi+WX8lvoPmxLGr1Hdj8VmR9mUR9qxpfK3W8vnjvrvo2" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "E37uCXmnE72y0B8XfHYCX5KLZYaKOiB9TtWdUmczqfHRm8GnJ/DpYhyr7c9x" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "cs/SoixYGk5reFLDZzQ8oeGM8OB3mBO/fwb99sh3F+M57Q7Ma3hVvyOBH9XC" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "bqmBsBNGNXop2+0AjXZQ72x3Y1irRa2wHyOO4BfXj4JebbMeNVrCtN3RjOLu" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "pUx5j1jPGFJ/p/QLpfdMqelHGGm6SEXSE1OyzzQtjzGtW4xpkLcZn5N98/6y" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "2i/y7InnutKc31T/qjAuKF1W+p7SfwMbOFhxAAkAAA==" >> /tmp/ebt_ip.o.gz.u64 | 
|  | echo "====" >> /tmp/ebt_ip.o.gz.u64 | 
|  | uudecode /tmp/ebt_ip.o.gz.u64 | gzip -cd > /tmp/ebt_ip.o | 
|  | insmod ebtables | 
|  | insmod ebtable_filter | 
|  | insmod /tmp/ebt_ip.o | 
|  | ebtables -I INPUT -i tap0 -p IPv4 --ip-protocol udp --ip-destination-port 67:68 -j DROP | 
|  | </file> | 
|  |  | 
| nvram set rc_firewall="iptables -t mangle -I PREROUTING 1 -p UDP --sport 67 -j DROP | Then hit "Save commands".  Finally, reboot.  You can check to see if it works by telnetting in and typing "ebtables -L".  You should see: | 
| iptables -t mangle -I PREROUTING 1 -p UDP --sport 68 -j DROP | <file> | 
| iptables -t mangle -I PREROUTING 1 -p UDP --dport 67 -j DROP | Bridge table: filter | 
| iptables -t mangle -I PREROUTING 1 -p UDP --dport 68 -j DROP" |  | 
| nvram commit |  | 
|  |  | 
| Reboot, and presto, the bridge is eating all DHCP traffic: | Bridge chain: INPUT, entries: 1, policy: ACCEPT | 
|  | -p IPv4 -i tap0 --ip-proto udp --ip-dport 67:68 -j DROP | 
|  |  | 
| <file> | Bridge chain: FORWARD, entries: 0, policy: ACCEPT | 
| # iptables -t mangle -vL |  | 
| Chain PREROUTING (policy ACCEPT 262 packets, 50464 bytes) | Bridge chain: OUTPUT, entries: 0, policy: ACCEPT | 
| pkts bytes target     prot opt in     out     source               destination |  | 
| 0     0 DROP       udp  --  any    any     anywhere             anywhere            udp dpt:bootpc |  | 
| 37 14776 DROP       udp  --  any    any     anywhere             anywhere            udp dpt:bootps  <=== Counter shows 37 DHCP packets have been eaten! |  | 
| 0     0 DROP       udp  --  any    any     anywhere             anywhere            udp spt:bootpc |  | 
| 0     0 DROP       udp  --  any    any     anywhere             anywhere            udp spt:bootps |  | 
| </file> | </file> | 
|  |  | 
|  | ===== What does that crap do? ===== | 
|  |  | 
|  | Because we need to hook into the bridging system, iptables is insufficient.  [[http://www.dd-wrt.com/phpBB2/viewtopic.php?t=12372&highlight=ebtables|This thread]] explains that we need to use //ebtables// to do that.  This requires 2 included modules: ''ebtables'' and ''ebtable_filter'', plus one module that's not included: ''ebt_ip.o'' (attached in the thread).  How can we add this extra module, given that the flash filesystem is read only?  Answer: we crap it into the NVRAM as a series of commands. | 
|  |  | 
|  | I took the original ebt_ip.o, and ran "gzip -c ebt_ip.o | uuencode -m -", which means "compress with gzip, then uuencode with base-64 mode".  This turns the binary file into safe ASCII.  We then wrap all this ASCII in that giant pile of "echo ... >> /tmp/ebt_ip.o.gz.u64" commands.  We then decode it back into binary with "gzip -cd ... | uudecode -".  Then we load the required modules: ''ebtables'', ''ebtable_filter'', and our hacked up ''/tmp/ebt_ip.o''.  Finally, we input the ebtables rule to drop all the DHCP packets it sees. | 
|  |  |