如何处理 ISP 更改的 IP 地址?

如何处理 ISP 更改的 IP 地址?

我家里有一台 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

作为沃特评论说,你现有的设置看起来已经相当不错了。

如果你想要一些不太依赖的东西dhclient,你可以看看 Debian 中打包的许多动态 DNS 客户端。

例如,ddclient可以对 DHCP 更改做出反应或简单地监视以太网接口;当 IP 地址发生变化时(并且只有此时),它可以更新动态 DNS 条目(在任意数量的提供商上),并运行单独的脚本(这将涵盖您的两种用例)。

答案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-proxycrypt 来留给 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

相关内容