Showing posts with label kingbaron. Show all posts
Showing posts with label kingbaron. Show all posts

Friday, December 2, 2011

ddclient on a Debian 6 server

This post is an update to my original in March 2011.

Every time I reconnect to the internet, my router is given a different IP address by the upstream internet service provider. That's called dynamic hosting. But if I'm out on the internet, I cannot connect to my server unless I know the current IP. A Dynamic DNS (ddns) host simply tracks my ever-changing IP for me in an internet-accessible way.

The ddns host isn't psychic - I need a small piece of software (a ddns client) on my server that figures out whenever the IP changes, and sends that update to the ddns host.

  1. Register for a dynamic DNS service. Any good search engine can point you to a good free service.

  2. The 'ddclient' package is the server program that sends the new IP to the ddns host. Install ddclient using the command apt-get install ddclient. The installer will ask questions about the newly-registered dynamic dns account.

  3. There are two ways to run ddclient - as a daemon or as an occasionally-triggered non-daemon.
    • To run ddclient as a daemon (always-on), edit the file /etc/init.d/ddclient, and change the line:
      run_daemon=false  #from
      run_daemon=true   #to
      Restart ddclient (service ddclient restart) to reload the new config.

    • To run ddclient as a non-daemon, take a look in the /usr/share/doc/ddclient/examples directory for a bunch of possible trigger mechanisms.
      I chose to run ddclient whenever my server picks up a new IP address:
      cp /usr/share/doc/ddclient/examples/sample-etc_dhclient-exit-hooks /etc/dhcp/dhclient-exit-hooks.d/ddclient
      It's not perfect for my use, but we'll fix that later.

That should be it. ddclient should automatically update the ddns host regularly (or event-driven) now.

Usage: If you're out on the internet and need to know your server's IP, just look it up:
dig +short myaccount.dyndns.org                              # Elsewhere on the internet
nslookup myaccount.dyndns.org ns.dyndns.org                  # Another way from the internet
http://www.dnscog.com/dig/myaccount.dyndns.org/              # As a web page
Or have the service look it up for you by simply using the domain name: ssh myaccount.dyndns.org

Kingbaron: Sometimes my server is also an internet-facing router, sometimes it's just a LAN server. I don't want it erroneously feeding LAN addresses to the ddns. Happily, the dhclient-exit-hook script thought of that already. If the new IP address is in the normal LAN range, ddclient ignores it.

Saturday, November 26, 2011

NTP on a Debian 6 server

This post is an update to my original in March 2011.


NTP is useful to set the time of LAN devices. The correct time is essential for several services. I installed ntp on an almost-always-connected server, which will in turn broadcast the correct time to other devices on my LAN.

internet ntp servers  <--->  my net ntp client / LAN ntp server  <--->  my LAN ntp clients


The ntp program is both client and server (those used to be separate packages). The same ntp gets installed on all devices. You change the settings in the /etc/ntp.conf file. The version of ntp on those devices isn't important - different versions of ntp interact well together (unlike, say, different versions of the deluge torrent client/server)


These instructions are for debian 6, running as root. For Ubuntu, you need to prepend most commands with 'sudo'


  1. Install NTP with the following command:
    apt-get install ntp
  2. Edit the server's /etc/ntp.conf file (if needed). If you want your device to get time from the default internet time servers (in most cases, this is exactly what you want), then skip this step and make no changes.

    In my case, however, my server is both a client of those upstream internet time servers AND a time server to my LAN. Your LAN probably does not need a timeserver - I'm doing this for fun.
    ## Around Line 48
    # If you want to provide time to your local subnet, change the next line.
    # (Again, the address is an example only.)
    #broadcast 192.168.123.255
    
    # Since my LAN is 192.168.1.0, the corresponding broadcast address is at 192.168.1.255
    broadcast 192.168.1.255
  3. No changes to /etc/hosts.allow and /etc/hosts.deny are needed to limit access to ntpd. Access controls are set by the /etc/ntp.conf file, they default to nobody has any access, and we didn't change those rules.
  4. xinted and dnsmasq do not interact with ntpd, and no special configuration is required.
  5. Firewall rules to open udp port 123 for ntp sync messages. Normally, this won't be necessary. Since the ntp client sends the first packet to the upstream internet server, and outbound packets usually are not blocked, the firewall should automatically let the server's response through.

    If an ntp client has a really locked-down firewall (blocking outgoing traffic), then open the client's UDP port 23 to outgoing traffic.
    iptables -A OUTPUT -p udp --sport 123 -j ACCEPT

    If you run a LAN-facing NTP server, then of course you must ensure that LAN-interface UDP port 23 is open to that same inbound traffic from your clients. (your -i interface name will be different)
    iptables -A INPUT -i lan0 -p udp --dport 123 -j ACCEPT 

    If you run an exposed internet-facing NTP server, then you should really be working with ntp.org for security, and to help support the ntp infrastructure!

    In my case, no firewall changes were needed at all. My firewall blocks inbound packets from the internet, not LAN-only packets, and not outbound-packets (or responses).
  6. Restart/update the firewall (how you do that is up to you), and then restart ntp to reload the changed config file. Let's test ntp to see if it's working:
    $ ntpq -p
         remote           refid      st t when poll reach   delay   offset  jitter
    ==============================================================================
    -w1-wdc.ipv4.got 10.0.77.54       4 u  396 1024  377   30.567    1.853   2.901
    *ntp3.junkemailf 209.81.9.7       2 u  465 1024  377   64.788   -0.072   1.269
    +vimo.dorui.net  208.90.144.52    3 u  633 1024  377   32.876   -1.081  30.206
    +aeolus.seobeo.c 193.67.79.202    2 u  184 1024  377  110.840    0.577   1.790
     192.168.1.255   .BCST.          16 u    -   64    0    0.000    0.000   0.000
    
    Looks correct. The first character of each row (*/+/-) is the status of each upstream server. See the explanation. The 'when' column is the number of seconds since the last check of that server. The'poll' column is the number of seconds between checks. The first four rows are upstream internet servers. The last row is the LAN broadcast, which is why it doesn't have an upstream status.
  7. The other ntp clients on the LAN need to be modified to listen for the new ntp server. Left alone, they will pull time from the upstream internet time servers (good). But, of course, I now have a server broadcasting time, so let's set each device on my LAN to listen for it. Plus, I still want them to get time from upstream in case my ntp server goes down or starts sending bad time.

    Log in to each device, and look at their /etc/ntp.conf (though it may be in a different location or names differently).

    Here's an example /etc/ntp.conf change from an Ubuntu system on the LAN, starting at around Line #15. We added the LAN ntp server, and marked it as the preferred source. We added minpoll to the internet servers to increase the time between pollings.
    # Specify one or more NTP servers.
    server kiwkak.dyndns.org prefer
    
    # Use servers from the NTP Pool Project. Approved by Ubuntu Technical Board
    # on 2011-02-08 (LP: #104525). See http://www.pool.ntp.org/join.html for
    # more information.
    server 0.ubuntu.pool.ntp.org minpoll 12
    server 1.ubuntu.pool.ntp.org minpoll 12
    server 2.ubuntu.pool.ntp.org minpoll 12
    server 3.ubuntu.pool.ntp.org minpoll 12
    Restart ntp (in debian 'service ntp restart'. For ubuntu 'sudo service ntp restart') to reload the new configuration file.

    Let's also take a loot at their ntp status:
    $ ntpq -p
         remote           refid      st t when poll reach   delay   offset  jitter
    ==============================================================================
    *adsl-76-229-175 184.105.182.7    3 u   28   64  377    0.274    0.805   0.209
     ntp1.Rescomp.Be 169.229.128.214  3 u  838 1024    3   63.979    3.262   0.424
     cheezum.mattnor 129.7.1.66       2 u  818 1024    3   34.490    0.145  25.810
     host2.kingrst.c 204.9.54.119     2 u  789 1024    3   22.359    0.721  17.671
     vf1.bbnx.net    128.4.1.1        2 u  824 1024    3   68.227   -0.820   1.466
    

    This looks good. See how the local server is preferred, and gets checked more often than the backup upstream servers. And the backup upstreams are reachable, but not currently used.
  8. The server itself may not always be the network router/firewall. I automagically switching between server between router and non-router roles using my kingbaron script. I use a script and two config files to change how ntp runs based on if the system is a router (Network King, runlevel 3) or just a LAN client (Faithful Baron, runlevel 4). The decision logic operates in runlevel 2.

    Create two .conf files, one for each runlevel. Let's call them /etc/ntp-king.conf and /etc/ntp-baron.conf. Look at all the .conf stuff above for the contents of those files.

    Use the following command once to automatically prevent ntp from starting in runlevel 2 (the decision logic level), and to stop ntp if you manually switch to runlevel 2 due to a loss of connectivity or for maintenance:
    update-rc.d ntp stop 2

    Add the following patch to /etc/init.d/ntp to restart ntp with the appropriate config files upon runlevel changes.
    test -x $DAEMON || exit 5    # Insert after this line
    
    current_runlevel=echo $(runlevel | cut -d' ' -f2)
    if [ current_runlevel -eq "3" ]; then
         NTPD_OPTS="$NTPD_OPTS -c /etc/ntp-king.conf"
    elif [ current_runlevel -eq "4" ]; then
         NTPD_OPTS="$NTPD_OPTS -c /etc/ntp-baron.conf"
    
    This covers the common use cases (booting, manual force of decision logic), but doesn't cover everything - if I manually switch to runlevels 3/4/5, ntp won't automatically check the config.

Sunday, October 30, 2011

Using runlevels to demote a network king to a mere baron

I have put enough services onto my server that it has become a single-point of failure. It's a router, a DSL modem, backup storage, and has network-shared drive, plus a few other cool things.

The key point of failure is the combination of Modem + Router. The PCI DSL card requires a custom driver, and sometimes after a system upgrade it needs to be reinstalled. The details of the wanrouter driver are here.

What I need is a failover mode: If the DSL fails to work, I want to use my old external modem and router. So I still want the system to run, but as a dchp-client server instead of a router.

Let's use some startup logic and runlevels to define two roles for the server: Network King routing over DSL, and faithful Baron merely connecting over wi-fi to the Linksys. And a bit of connective tissue so the machine automagically boots into the correct role, plus can be switched manually.

Internet <------+ Network King +-----> LAN

Internet <------+ Other router +------> LAN <------+ Faithful Baron 

Runlevel 1 - startup (Don't touch this)
Runlevel 2 - network testing
Runlevel 3 - server (Network King)
Runlevel 4 - client (Faithful Baron)
Runlevel 5 - unchanged from stock install
Runslevel6 - reboot (Don't touch this)

Decision logic:
If the server can connect to the internet over the dsl interface, then it is a King
Otherwise, it is a Baron.

Issues:
1) I need to change the LAN IP address of the server so it doesn't conflict with the router anymore!
2) All changes to the server must be tracked and undoable

Changes to the external router
Port-forward from the internet to the Baron (easy, one DMZ setting or separate port-forward settings for each service)

Server setup changes
1) Create a new directory to hold the three small scripts we are going to make, so you can keep track!
mkdir /root/startup-scripts

2) It's possible to create one really ugly /etc/networking/interfaces file, but let's not do that. Instead, we'll create separate interface files for runlevels 3 and 4. For convenience, let's put a link to them next to the original interfaces file.
cp /etc/network/interfaces /root/startup-scripts/runlevel-3-interfaces
cp /etc/network/interfaces /root/startup-scripts/runlevel-4-interfaces
ln /root/startup-scripts/runlevel-3-interfaces /etc/network/interfaces
ln /root/startup-scripts/runlevel-4-interfaces /etc/network/interfaces

3) Edit the runlevel 3 file (/root/startup-scripts/runlevel-3-interfaces)
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# This file is ONLY for runlevel 3 (Network King [router] mode)

# The loopback network interface
auto lo
iface lo inet loopback

# The ethernet jack and wi-fi antenna in bridged server mode
iface eth0 inet manual
iface wlan0 inet manual
     up hostapd -B /etc/hostapd/hostapd.conf
     down ifconfig mon.wlan0 down
     down pkill hostapd
auto br0                       
iface br0 inet static
     # Adding and removing the slave eth0 and wlan0 interfaces
     # is handled by /etc/init.d/kingbaron
     address 192.168.1.1
     broadcast 192.168.1.255
     netmask 255.255.255.0
     network 192.168.1.0
     up hostapd -B /etc/hostapd/hostapd.conf
     up route add -net 239.0.0.0 netmask 255.0.0.0 br0
     down ifconfig mon.wlan0 down
     down pkill hostapd
     down route del -net 239.0.0.0 netmask 255.0.0.0 br0

iface dsl-provider inet ppp
     pre-up /sbin/ifconfig dsl0 up # line maintained by pppoeconf
     provider dsl-provider

auto dsl0
iface dsl0 inet manual

4) Edit the runlevel 4 file (/root/startup-scripts/runlevel-4-interfaces)
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
# This file os ONLY for runlevel 4 (Network dhcp client mode)

# The loopback network interface
auto lo
iface lo inet loopback

# The ethernet jack in client mode
auto eth0
allow-hotplug eth0
iface eth0 inet dhcp

# The wi-fi antenna in client mode
auto wlan0
iface wlan0 inet dhcp
     pre-up ifconfig wlan0 down
     pre-up iwconfig wlan0 mode Managed
     pre-up iwconfig wlan0 essid MY_LAN_NAME

5) Let's edit the original /etc/network/interfaces file to reduce startup time by not automatically raising the eth0 and wlan0 interfaces. We don't need those in runlevel 2, since only the DSL line will needs to be brought up.
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The ethernet jack in client mode
# (Disabled during initial boot)
allow-hotplug eth0
iface eth0 inet manual

# The wi-fi antenna in client mode
# (Disabled during initial boot)
auto wlan0
iface wlan0 inet manual
     pre-up iwconfig wlan0 essid Klein-Weisser

# The following lines are auto-generated for the dsl connection

auto dsl-provider
iface dsl-provider inet ppp
     pre-up /sbin/ifconfig dsl0 up # line maintained by pppoeconf
     provider dsl-provider

auto dsl0
iface dsl0 inet manual

6) Create a new file for the startup testing and decision logic: /root/startup-scripts/kingbaron
#!/bin/bash

### BEGIN INIT INFO
# Provides:             runlevel_chooser
# Required-Start:       $network $remote_fs $syslog wanrouter
# Required-Stop:        $network
# Default-Start:        2
# Default-Stop:
# Short-Description:    Choose runlevels based on testing network connection to an interface
### END INIT INFO

# Functions

start_king_mode () {
   # If coming from runlevel N or 4, need to change from dhcp to static/Master
   [ runlevel=="4 2" ] && ifdown -a --interface=/etc/network/runlevel-4-interfaces
   [ runlevel=="N 2" ] && ifdown -a

   # If the br0 interface does not exist (coming from runlevel N), create it.
   [ $(brctl show | grep -c br0) -eq 0 ] && brctl addbr br0

   # Add the slave interfaces to br0
   [ $(brctl show | grep -c eth0) -eq 0 ] && brctl addif br0 eth0
   [ $(brctl show | grep -c wlan0) -eq 0 ] && brctl addif br0 wlan0

   # Bring up the King mode interfaces (except dsl0 and ppp0, which are already up)
   ifup -a -v --interfaces=/etc/network/runlevel-3-interfaces

   # Test that ifup worked
   [ $(ifconfig | grep -c mon.wlan0) -eq 0 ] && logger -i -s -t kingbaron "Failed to bring up wlan0...Sorry"
   [ $(ifconfig | grep -c br0) -eq 0 ] && logger -i -s -t kingbaron "Failed to bring up br0...Sorry"

   logger -i -s -t kingbaron "Network should be up now. If not, try 'ifconfig' for LAN interfaces and 'wanrouter' for the DSL interface"
   telinit 3
   exit 0
}

start_baron_mode () {
   # Shut down the dsl0 and ppp0 interfaces (not used in Runlevel 4).
   # Sometimes the signal needs to be sent twice
   [ $(wanrouter status | grep -c stopped) -gt 0 ] || wanrouter stop
   [ $(wanrouter status | grep -c stopped) -gt 0 ] || wanrouter stop

   # If coming from runlevel 3, need to change from static/Master to dhcp
   # If coming from runlevel N or 4, we can keep the same interfaces
   [ runlevel=="3 2" ] && ifdown -a --interface=/etc/network/runlevel-3-interfaces

   # If br0 is up, bring it down. If it still has slaves from runlevel 3, unslave them
   [ $(ifconfig | grep -c br0) -gt 0 ] && ifconfig br0 down
   [ $(brctl show | grep -c wlan0) -gt 0 ] && brctl delif br0 wlan0 && ifconfig wlan0 down
   [ $(brctl show | grep -c eth0) -gt 0 ] && brctl delif br0 eth0 && ifconfig eth0 down

   # If wlan0 is stuck in Master mode from runlevel 3, unstick it
   [ $(ifconfig | grep -c mon.wlan0) -gt 0 ] && pkill hostapd && ifconfig wlan0 down && iwconfig wlan0 Managed

   # Bring up the Baron Mode interfaces, ignoring anything already up
   ifup -a -v --interfaces=/etc/network/runlevel-4-interfaces

   # Sometimes the network fails to come up, especially if it didn't go down properly
   # Check for the most common errors (like WiFi not going up) and try to autofix
   if [ $(ifconfig | grep -A2 wlan0 | grep -c inet) -eq 0 ]; then
      logger -i -s -t kingbaron "Wireless failed to come up. Resetting and trying again..."
      ifconfig wlan0 down
      iwconfig wlan0 mode Managed
      iwconfig wlan0 essid MY_ESSID
      ifconfig wlan0 up
      dhclient -v wlan0
   fi
   logger -i -s -t kingbaron "Network should be up now. If not, try 'ifconfig' and 'iwconfig'"
   telinit 4
   exit 0
}

logger -i -s -t kingbaron "Testing for DSL connectivity"

# Check for the existence of a the DSL interface. If it exists, try to get a connection
# If the internet is reachable, goto runlevel 3 (King mode). Else goto runlevel 4 (Baron mode)

# If wanrouter is not already running, then start it
flag="wanrouter off"
[ $(wanrouter status | grep -c Connecting) -eq 0 ] && flag="wanrouter on"
[ $(wanrouter status | grep -c Connected) -eq 0 ] && flag="wanrouter on"
[ $flag=="wanrouter off" ] && wanrouter start

# If the test interface does not exist, then start client mode
if [ $(ifconfig | grep -c dsl0) -eq "0" ]; then
   logger -i -s -t kingbaron "The DSL interface (dsl0) does not exist. Entering dhcp client mode"
   start_baron_mode
fi

# If the test interface exists, then wait for wanrouter to start up
# Average start time is about 20 seconds
logger -i -s -t kingbaron "Found the DSL interface. Waiting up to 40 seconds for the DSL link (dsl0) to come up"
i="0"
while [ $i -lt 40 ]; do
   sleep 1
   i=$[$i+1]
   [ $(wanrouter status | grep -c Connecting) -gt 0 ] || i=100
done

# If time expires without the wanrouter starting, print the error and start client mode
if [ $i -lt 100 ]; then
   logger -i -s -t kingbaron "dsl0 interface failed to come up. Entering dhcp client mode"
   start_baron_mode
fi

# If the wanrouter comes up properly, then wait for a ppp connection
logger -i -s -t kingbaron "dsl0 up. Waiting up to 40 seconds for a PPPoE connection (ppp0)"
pon dsl-provider
i="0"
while [ $i -lt 40 ]; do
   sleep 1
   i=$[$i+1]
   [ $(route | grep -c default) -gt 0 ] && i=100
done

# If time expires without the ppp connection starting, print the error and start client mode
if [ $i -lt 100 ]; then
   logger -i -s -t kingbaron "ppp0 failed to come up. Entering dhcp client mode"
   start_baron_mode
fi

# If all has gone well, and the ppp connection comes up
logger -i -s -t kingbaron "ppp0 came up. This system has DSL connectivity. Starting Router services"
start_king_mode

7) Install the script:
chmod +x /etc/startup-scripts/kingbaron            # Make executable
ln /root/startup-scripts/kingbaron /etc/init.d/    # Hardlink to init.d
update-rc.d kingbaron defaults                     # Symlink to runlevel 2

8) Take a look at /etc/rc2.d/. See all those router and server services that shouldn't operate in runlevel 2? Or shouldn't operate in runlevels 2 and 4? Use the command "update-rc.d $Name disable 2" to disable the appropriate services in runlevel 2 (or 4).

...And do a whole lot of tweaking and testing, and voila! An automated detection and failover system. If the DSL line is active, router services start and the interfaces come up in static/master mode. If the DSL line isn't active, router services don't start and the interfaces come up in dhcp mode. Runlevel 2 is the decision mode, runlevel 3 is the King (router) mode, and runlevel 4 is the Baron (dhcp) mode.

All the server services (samba, cups, etc) still operate, regardless. And you can manually reset with the command 'telinit 2' to make the system reset the interfaces and router services.

TIP: Look for related posts using the kingbaron tag.