我家里有一台 Debian 服务器。服务器是我的路由器,提供对外的VPN访问。
我没有静态 IP 地址; ISP给出的租用时间是两个小时。
这个为我居住的地区提供服务的有线电视单元似乎有至少为客户提供两个不同的网络块,并且在 Linux 服务器重新启动后获得不同的 IP 地址并非完全不寻常,或者不太常见,但更重要的是在一些 ISP 维护操作之后涉及到这个问题。
我有一些依赖于IP地址的服务;公共 IP 地址用于外部 (VPN) 访问和内部参考。
在某些服务中,我使用 FreeDNS 的动态 DNS 名称,以便不必在多个位置更改 IP 地址。
因此,到目前为止我设计的最佳方法是在 dhclient-exit 挂钩上运行脚本。该脚本在 DHCP 提供/更新 IP 后调用,如果 IP 更改则重新启动服务。
我还更改了动态 DNS 名称的 IP /etc/hosts
,以解决在 FreeDNS 端的更改影响到我之前使用旧 IP 可能出现的问题。
我写的剧本dhclient-exit-hooks.d
就是这个;exit_status
如果一切顺利的话应该是 0 dhclient
。
#!/bin/bash
PATH=$PATH:/usr/bin
if ! [[ -v exit_status ]]
then
exit 1
fi
if [ $exit_status -eq 0 ]
then
IP=`ip addr show eth0.101 | grep inet | awk ' { print $2 } ' | cut -f1 -d "/"`
OLDIP=`awk ' /xxxx.mooo.com/ { print $1 } ' /etc/hosts`
if [ $reason = "REBOOT" ] || [ $reason = "BOUND" ] || [ $IP != $OLDIP ]
then
sed -i "s/^[0-9\.]* xxxx.mooo.com/$IP xxxx.mooo.com/g" /etc/hosts
timeout 60 /opt/bin/iptables.sh
timeout 60 /etc/init.d/ipsec restart
timeout 60 /etc/init.d/asterisk restart
timeout 120 /etc/init.d/bind9 restart
timeout 60 /usr/bin/wget -O - http://freedns.afraid.org/dynamic/update.php?XXXXXXXXXXXX > /dev/null
fi
fi
我知道其他帖子也建议使用dhclient-exit-hooks.d
;然而我的问题是一种在 IP 地址更改时自动重新启动和配置这些服务的方法。
答案1
我建议按照关注点分离的原则进一步简化/拆分您的解决方案:
- 脚本
/etc/dhcp/dhclient-exit-hooks.d/trigger_on_ip_change
应该只决定是否需要采取操作并将操作推迟到单独的脚本/usr/local/bin/act_on_ip_change
- 该脚本
/usr/local/bin/act_on_ip_change
应该只执行必要的更改
将这些问题分开的原因是:
- 您可以单独测试是否
dhclient
正确触发(在调试期间无需实际修改系统上的任何内容) - 您可以测试“更改”,而无需更新(因此可能会松动)您的 IP
/usr/local/bin/act_on_ip_change
如果有需要,您可以手动执行- 这些部分更容易理解
简而言之,我建议将其包含在/etc/dhcp/dhclient-exit-hooks.d/trigger_on_ip_change_action
:
# based on /etc/dhcp/dhclient-exit-hooks.d/debug
if [ "$reason" = "BOUND" -a "$old_ip_address" != "$new_ip_address" ]; then
/usr/local/bin/act_on_ip_change
fi
答案2
答案3
最后,我最终简化了一些设置,以应对 IP 地址的变化。
Internet NAT 已更改为 MASQUERADE,因此我不必对其进行操作;规则iptables
留下了dhclient-exit-hooks.d
,安装了iptables-persistent
。
iptables -A POSTROUTING -o eth0.101 ! -p esp -j MASQUERADE
apt-get install iptables-persistent
iptables-save > /etc/iptables/rules.v4
BIND 不再在启动时失败,因为它现在可以识别对 iptables 的依赖关系。
我现在也不重新启动 BIND。此外,BIND 现在依赖于dnscrypt-proxy
crypt 来留给 Internet,因此它仅绑定到内部接口(不会改变)。
exit_status
虽然文档中提到了该变量dhclient-exit-hooks.d
,但显然存在一些混淆,它仅用于将退出状态传递给 DHCP,而不是获取它。
所以最终的脚本是:
#!/bin/bash
PATH=$PATH:/usr/bin
IP=`ip addr show eth0.101 | grep inet | awk ' { print $2 } ' | cut -f1 -d "/"`
OLDIP=`awk ' /xxxx.mooo.com/ { print $1 } ' /etc/hosts`
# if reboot or IP changed
if [ $reason = "REBOOT" ] || [ $reason = "BOUND" ] || [ $IP != $OLDIP ]
then
# put it in hosts
sed -i "s/^[0-9\.]* xxxx.mooo.com/$IP xxxx.mooo.com/g" /etc/hosts
timeout 60 /etc/init.d/ipsec restart
timeout 60 /etc/init.d/asterisk restart
# update FreeDNS service
timeout 60 /usr/bin/wget -O - http://freedns.afraid.org/dynamic/update.php?XXXX > /dev/null
fi
至于缺少,这些是启动时exit_status
出现的变量:dhclient-exit-hooks.d
requested_broadcast_address=1
new_network_number=95.94.xx.0
new_ip_address=95.94.xx.xx
new_dhcp_message_type=5
pid=1100
new_time_offset=0
new_routers=95.94.xx.xx
new_expiry=1462482903
new_subnet_mask=255.255.240.0
interface=eth0.101
requested_time_offset=1
new_domain_name=netcabo.pt
reason=REBOOT
new_time_servers=212.113.176.129 212.113.176.65
requested_routers=1
PATH=/usr/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/bin
requested_subnet_mask=1
new_log_servers=212.113.188.209
new_dhcp_server_identifier=79.169.255.254
new_domain_name_servers=0.0.0.0 8.8.8.8
new_broadcast_address=95.94.xx.255
new_dhcp_renewal_time=7200
new_dhcp_rebinding_time=12600
PWD=/
new_next_server=0.0.0.0
new_dhcp_lease_time=14400