I have a Debian server at home. The server is my router and provides VPN access to the outside.

I do not have a static IP address; the lease time given by the ISP is two hours.

This cable cell which services the area I live, seems to have at least two different different netblocks for customers, and it is not entirely unusual obtaining a different IP address after a reboot of the Linux server, or less usually, but more importantly in what concerns this question, after some ISP maintenance operations.

I have some services that are dependent on the IP address; and the public IP adddress is used either for external (VPN) access, and for internal reference.

In some services, I use the dynamic DNS name from FreeDNS in order not to have to change an IP address in several locations.

As such, the best method I devised until now is running a script on dhclient-exit hooks. The script is called after DHCP gives/renews an IP, and restart services if the IP is changed.

I also change the IP of my dynamic DNS name on /etc/hosts, for solving possible problems of using the old IP before the change at FreeDNS side trickles down to me.

The script I wrote for dhclient-exit-hooks.d is this one; exit_status should be 0 if all went ok with dhclient.



if ! [[ -v exit_status ]]
   exit 1

if [ $exit_status -eq 0 ]
   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 ] 
      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

I am aware of other posts that also recommend using dhclient-exit-hooks.d; however my question is a way to automate the restarting and configuration of those services upon an IP address change.

  • Define "better"? What's wrong with this method? Is there a problem with it, where something doesn't exactly work? Since you're getting your IP address from DHCP, running it from the DHCP client seems like the best method, to me. Remember the old adage, "if it ain't broken, don't fix it"... Mar 20, 2016 at 7:59
  • A bit complicated, too much dependent on the DHCP client, slight probability of getting hang services. You are absolutely right in the KISS part. Mar 20, 2016 at 8:42
  • 1
    Complicated? Seems simple enough. Dependent on the DHCP client? That seems like a feature, not a bug (anything else would require you to poll the IP address every so often, which is... well, not a good idea). Hung services? There are plenty of good monitoring tools out there which you can use to automatically restart services that are hung... Personally, I think your setup is cool, and I might actually duplicate it at home :-) Mar 21, 2016 at 15:31
  • I edited it out with a view on having possible hang up services. And yep, there is monit. I do really need the IPsec part to be working with the right IP, as I use the VPN to have access to everything from the outside, including voIP and ssh. Hmmm I have started encrypting DNS in the meanwhile, will have to see if I need to add it to the restarted services. Mar 21, 2016 at 15:47

3 Answers 3


I propose to further simplify/split up your solution following the principle of separation of concerns:

  • a script /etc/dhcp/dhclient-exit-hooks.d/trigger_on_ip_change should only decide whether action needs to be taken and defer the action to a separate script /usr/local/bin/act_on_ip_change
  • the script /usr/local/bin/act_on_ip_change should only execute the necessary changes

The reasons for separating those concerns are:

  • you can test separately whether dhclient is triggering correctly (without actually modifying anything on your system during debugging)
  • you can test the "change making" without the need to renew (and thus potential loose) your IP
  • you can execute /usr/local/bin/act_on_ip_change manually in case there's a need
  • the parts are much easier to understand

In short, I'd suggest to have this in /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
  • +1 for noticing $new_ip_address is there, and does not have to be extracted from the interface. Oct 4, 2016 at 17:08

As Wouter commented, your existing setup seems pretty decent already.

If you want something less dependent on dhclient, you could have a look at the many dynamic DNS clients packaged in Debian.

For example, ddclient can react to DHCP changes or simply monitor an Ethernet interface; when the IP address changes (and only then), it can update a dynamic DNS entry (on any number of providers), as well as run a separate script (which would cover both your use-cases).

  • The dynamic DNS entry is quite a good idea, thanks. I should not have modified the original question with the edited timeouts, as it should also been part of the answer. There is still something missing about the way I had dhcpd configured...I have to test BIND better, had a race problem that I am not sure it is 100% solved. Apr 14, 2016 at 6:18

In the end, I ended up simplifying things a bit my setup to act on IP addresses changes.

The Internet NAT was changed to MASQUERADE, so I do not have to act on it; the iptables rules left the dhclient-exit-hooks.d, installing iptables-persistent.

iptables -A POSTROUTING -o eth0.101 ! -p esp -j MASQUERADE
apt-get install iptables-persistent
iptables-save > /etc/iptables/rules.v4

BIND stopped failing on boot because it recognises dependencies on iptables going up now.

I also do not restart BIND now. Furthermore, BIND is now dependent on dnscrypt-proxy crypt to leave to the Internet, so it is only binded to the internal interfaces (which do not change).

Whist the variable exit_status is mentioned in the dhclient-exit-hooks.d documentation, apparently there is some confusion, and it is only used to pass exit status to DHCP, and not to get it.

So the final script is:



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 ] 
      # 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

As for the absence of exit_status, these are the vars presented in dhclient-exit-hooks.d upon boot:

  • 1
    An additional useful service is DNS-o-matic (dnsomatic.com). It's not useful if you just need to update one service, but I have to update both FreeDNS and HE's tunnel broker for my IPv6 tunnel and this lets me do it with only a single update (critical for things like DD-WRT that require hasty hacking to allow multiple update targets).
    – Todd Knarr
    May 5, 2016 at 17:36
  • Cool stuff. Thanks for the heads up @ToddKnarr May 5, 2016 at 18:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .