![通过“MAC”地址更改“iptables”规则](https://linux22.com/image/169724/%E9%80%9A%E8%BF%87%E2%80%9CMAC%E2%80%9D%E5%9C%B0%E5%9D%80%E6%9B%B4%E6%94%B9%E2%80%9Ciptables%E2%80%9D%E8%A7%84%E5%88%99.png)
我使用连接到 VPN 的网关来对工业 LAN 元件的端口进行转发。
我在浏览器中使用 iptables 转发访问我的网关的 80/443 端口,以显示该项目的 80/443 端口的内容:
iptables -t nat -A POSTROUTING -p tcp -d 192.168.1.37 --dport 80 -j MASQUERADE
iptables -t nat -A POSTROUTING -p tcp -d 192.168.1.37 --dport 443 -j MASQUERADE
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 80 -j DNAT --to 192.168.1.37:80
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 443 -j DNAT --to 192.168.1.37:80
问题在于,该元素有时会通过重新启动路由器或通过 DHCP 服务器过期来更改本地 IP 地址;我们无权访问。为此,我想知道是否可以通过您的 MAC 进行转发,而不是通过您的 IP 地址进行转发。
我尝试做类似的事情,但它不起作用:iptables -t nat -A POSTROUTING -p tcp -m mac --mac-source AA:BB:CC:DD:EE:FF --dport 80 -j MASQUERADE
,扔iptables: Invalid argument. Run 'dmesg' for more information.
使用脚本更新
为了解决这个问题,我开发了一个脚本来bash
检查 MAC 地址并返回其 IP 地址以创建iptables
规则。主要思想是不时使用 启动脚本crontab
。
这是脚本:
#!/bin/bash
vpnip=10.2.10.1
subred=192.168.1.0/24
mac=aa:bb:cc:11:22:33 # lowercase
ip=$(nmap -sP $subred >/dev/null && arp -an | grep $mac | awk '{print $2}' | sed 's/[()]//g')
if [ $ip ]; then
echo "IP address found: $ip"
iptables -t nat -A POSTROUTING -p tcp -d $ip --dport 80 -j MASQUERADE
iptables -t nat -A POSTROUTING -p tcp -d $ip --dport 443 -j MASQUERADE
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 80 -j DNAT --to $ip:80
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 443 -j DNAT --to $ip:443
iptables -t nat -A PREROUTING -d $vpnip -p tcp -m multiport --dports 80,443 -j DNAT --to-destination $ip:80
iptables --table nat --list
else
echo "IP not found"
fi
该脚本运行正常。但是,当iptables
规则定期发布时,它们就会重复。
在重新编写这些规则之前,有没有办法检查这些规则是否存在?或者先删除它们?
答案1
在重新编写这些规则之前,有没有办法检查这些规则是否存在?或者先删除它们?
您可以对 iptables 使用 -C 选项。查看man iptables
更多信息。我认为一个巧妙的方法是创建一个包含规则的数组,并在将其添加到链之前检查规则是否存在。
示例脚本:
#!/bin/bash
ip='1.1.1.1'
ip2='8.8.8.8'
rules=(
"INPUT -s $ip -j DROP"
"INPUT -s $ip2 -j DROP"
)
for rule in "${rules[@]}"; do
if ! iptables -C $rule 2> /dev/null; then
echo "Adding rule \"$rule\""
iptables -A $rule
fi
done