A GPS Stratum 1 NTP Server

“A man with a watch knows what time it is. A man with two watches is never sure.” – Segal’s Law

Introduction

Keeping accurate time is critical for a number of things at an ISP. Accurate time is needed for debugging to see what devices were affected at what time.   If you had one reference clock that everything synced to, it really wouldn’t matter if it was 5mS off or 5 minutes off.  So long as everything was based on that clock.  Where it matters if you are trying to match your logs and data with devices that are not synced to your clock but to some other clock.  So long as the other set of devices have synced to the same coordinated set of clocks you are, then you may have a good chance of lining up your logs to these other devices.

In tracking an event you are looking for timestamps that are “newer” or “older”. The need for accurate time may be in the milli or microseconds to see fast-moving events. In order to have a device to determine what time it is, it will normally use a protocol like the Network Time Protocol (NTP).  NTP will send a packet out to another and trusted the NTP server to see what time it is. As there is latency on the Internet and in the protocol, NTP will also try to calculate the latency and adjust for it. 

Trusted NTP servers will be classified on how they get their time such as based on an internal, highly accurate clock (stratum 0) or based on another NTP server (stratum 1, 2, etc.). For instance, a stratum 1 server will get its time from a stratum 0 server. A stratum 2 server will get its time from a stratum 1 server and so on.

One does everything they can to minimize the workload on these servers so that when a server is queried, it can respond as quickly and reliably as possible.  So you may not have all of your devices connect to your only reference clock.  You would distribute a second tier of NTP servers that would sync to your reference clock that your devices get their time from.  As we are building a stratum 1 clock, you would deploy a set of NTP servers that would be stratum 2 servers for the rest of your devices.  The stratum 2 servers would also sync with other NTP servers on the net to confirm that the reference clock is accurate.

The NTP Server

This server uses the Adafruit Global Positioning System (GPS) receiver hat sitting on a Raspberry Pi 3 to get its time from GPS. GPS has to have a highly accurate time to have accurate positioning reporting. 

Setup

As mentioned above, our server will get its time from a stratum 0 server. In this case, a GPS clock is considered a stratum 0 server as it is a highly stable “coordinated clock”. Coordinated means that the time it calculates is coordinated with other clocks, such as the rest of the GPS satellite clocks as well as established clocks on the ground. Drift between these clocks is noted and adjusted as needed in order to keep all coordinated clocks in sync.

GPS receivers indicated time a couple of ways. Every second, this string is sent to the Pi. The actual timestamp of what time it is is sent to the Raspberry Pi via a 9600 baud serial port. As the string can vary in length as well as various other delays such as the computer servicing serial port interrupts, this is not an accurate method of finding out what time it is. It can actually vary several hundred mS. An additional method needs to be conveyed to the Raspberry Pi indicating the actual moment when the second occurs. This is typically a General Purpose I/O (GPIO) pin going high for a 100 mS and then going low. This GPIO pin is exposed to the computer as the Packet Per Second (PPS) interface such as /dev/pps0. The moment the GPIO pin goes high is the exact moment the second occurs. This is called the rising edge. So, timing software on the computer will get the time from the serial port and know the exact moment from the GPIO pin going high.

On a computer, you will have one process looking at the data from the GPS and one process handing the NTP protocol. The second process will get the timestamp and could be configured to assume that the first process is looking at the /dev/pps0 interface or it could use the /dev/pps0 interface. In the current configuration, the NTP server (CHRONYd) is getting the GPS timestamp from the GPSd process via shared memory and the NTP server is looking at the /dev/pps0 interface for the exact moment that the second occurs.

The GPSd daemon simply listens to the serial port and reports this via shared memory to the NTP server. We are using a compiled (source) GPSd as the packaged version was several revisions old for the Raspberry Pi distro. We are using an NTP server that is also a recent release and locally compiled called Chrony. In this case, Chrony is listening to the PPS interface to understand when the actual second starts.

Debugging

You can check the status of the NTP server by running the Chrony command-line interface called “chronyc”.   A couple of commands are worth note are “sources” and “tracking”.  The “sources” command will list the sources it is using for time.  In the line below it shows PPS0 which is the Pulse Per Second GPIO pin.  It is within the error rate tolerable of +/- 8mS and is around 200nS. GPS0 is the GPS NEMA strings via shared memory from GPSd to CHRONYd. Normally this would be off around 500mS or so we compensate for that by putting an offset in the chrony config of 0.500 seconds. PSM0 and PST0 are GPS NEMA strings and PPS signals via shared memory. Since the GPS is not handling PPS, these entries will be zero. The rest of the various NTP servers that chrony can sync against and have some confidence that the GPS data is sane.

chronyc> sources
210 Number of sources = 8
MS Name/IP address         Stratum Poll Reach LastRx Last sample               
===============================================================================
#* PPS0                          0   4   377    10   +227ns[ +516ns] +/- 8186ns
#? GPS0                          0   3   377     5    -12ms[  -12ms] +/-  100ms
#? PSM0                          0   3     0     -     +0ns[   +0ns] +/-    0ns
#? PST0                          0   3     0     -     +0ns[   +0ns] +/-    0ns
^- jane.qotw.net                 2   4   377    10    +20us[  +20us] +/-   88ms
^- ntp18.kashra-server.com       2   4   177    10  +1485us[+1485us] +/-   95ms
^- time.iqnet.com                2   4   377     4  -1098us[-1097us] +/-  141ms
^- www.almaprovence.fr           3   4   377     5  -1196us[-1196us] +/-  115ms
chronyc>

The Chrony tracking command gives you an update of stratum Chrony thinks it is. In this case Stratum 1, it has some confidence about slaving from the GPS receiver.

chronyc> tracking
Reference ID    : 50505330 (PPS0)
Stratum         : 1
Ref time (UTC)  : Fri Aug 21 22:01:59 2020
System time     : 0.000000248 seconds fast of NTP time
Last offset     : +0.000000319 seconds
RMS offset      : 0.000000776 seconds
Frequency       : 0.923 ppm slow
Residual freq   : +0.000 ppm
Skew            : 0.034 ppm
Root delay      : 0.000000001 seconds
Root dispersion : 0.000025404 seconds
Update interval : 16.0 seconds
Leap status     : Normal
chronyc>

Configuration files

GPSd:

/etc/default/gpsd
# /etc/default/gpsd
## mod_install_stratum_one
# Default settings for the gpsd init script and the hotplug wrapper.
# Start the gpsd daemon automatically at boot time
START_DAEMON="true"
# Use USB hotplugging to add new USB devices automatically to the daemon
USBAUTO="true"
# Devices gpsd should collect to at boot time.
# They need to be read/writeable, either by user gpsd or the group dialout.
# DEVICES="/dev/ttyAMA0 /dev/pps0"
# in case you have two pps devices connected
# DEVICES="/dev/ttyAMA0 /dev/pps0 /dev/pps1"
# We tell GPSD to use the console serial port.  Alas, it will try to open /etc/pps0.  
# Run Chrony first to grab the port so GPSd doesn't get it.
DEVICES="/dev/ttyAMA0"
# Other options you want to pass to gpsd
GPSD_OPTIONS="-n -r -b"
GPSD_SOCKET="/var/run/gpsd.sock"
BAUDRATE="9600"
# Serial setup
# For serial interfaces, options such as low_latency are recommended
# Also, http://catb.org/gpsd/upstream-bugs.html#tiocmwait recommends
#   setting the baudrate with stty
# Uncomment the following lines if using a serial device:
/bin/stty -F ${DEVICE} raw ${BAUDRATE} cs8 clocal -cstopb
# /bin/setserial ${DEVICE} low_latency

Chrony:

/etc/chrony/stratum1/10-refclocks-pps0.conf:
######################################################################
# PPS0
# PPS: /dev/pps0: Kernel-mode PPS ref-clock for the precise seconds
# refclock  PPS /dev/pps0                   refid PPS0  precision 1e-7  poll 3  trust  noselect  lock PSM0
refclock PPS /dev/pps0 refid PPS0 trust
# SHM(0), gpsd: NMEA data from shared memory provided by gpsd
# refclock  SHM 0                           refid GPS0  precision 1e-1  poll 3  trust  noselect  offset 0.0
refclock  SHM 0                           refid GPS0  precision 1e-1  poll 3  trust  noselect  offset 0.500
# SHM(1), gpsd: PPS0 data from shared memory provided by gpsd
refclock  SHM 1                           refid PSM0  precision 1e-7  poll 3  trust  prefer
# SOCK, gpsd: PPS0 data from socket provided by gpsd
refclock  SOCK /var/run/chrony.pps0.sock  refid PST0  precision 1e-7  poll 3  trust  noselect
/etc/chrony/stratum1/20-ntp-servers.conf:
# NTP Servers
pool  2.debian.pool.ntp.org  iburst  minpoll 4  maxpoll 4
rc.local:
# for the GPS...
# Start Chrony first to grab /etc/pps0 before GPSd does...
/usr/local/sbin/chronyd
sleep 2
stty -F /dev/serial0 raw 9600 cs8 clocal -cstopb
/usr/local/sbin/gpsd -n -b /dev/ttyAMA0 -F /var/run/gpsd.sock

References

Be the first to like this

Protecting your Asterisk PBX…

Disclaimer:  This is likely not everything you should do in securing your FreePBX box, but it is a good starting point.   It is meant to limit your exposure to the public Internet, but this doesn’t cover exploits that can happen after you lock that down such as from address space you are allowing.  Having good credentials, among other security measures is also expected.

FreePBX‘s GUI makes setting up Asterisk a breeze.  This is a great product that Sangoma has been supporting for a while.  You can get the main package at https://www.freepbx.org/downloads/freepbx-distro for running on your own server or VM.  I am running RasPBX that is a slightly slimmed down version that runs very nicely on a Raspberry Pi.

The packages are built on a Debian-based Linux but have some exposure that one needs to do to really lock it down.  There are a bunch of applications that are on FreePBX that are listening and waiting for the rest of the Internet to exploit them.  You can easily see them by running the command “lsof -i | grep LISTEN”.  You may see something like:

root@asterisk:/etc/network# lsof -i | grep LISTEN
sshd        612        root    3u  IPv4   10163      0t0  TCP *:ssh (LISTEN)
sshd        612        root    4u  IPv6   10165      0t0  TCP *:ssh (LISTEN)
mysqld     1149       mysql   10u  IPv4   10996      0t0  TCP localhost:mysql (LISTEN)
exim4      1592 Debian-exim    4u  IPv4   11165      0t0  TCP localhost:smtp (LISTEN)
exim4      1592 Debian-exim    5u  IPv6   11166      0t0  TCP localhost:smtp (LISTEN)
asterisk   1971    asterisk   13u  IPv6   15624      0t0  TCP *:omniorb (LISTEN)
asterisk   1971    asterisk   14u  IPv6   15625      0t0  TCP *:8089 (LISTEN)
asterisk   1971    asterisk   15u  IPv4   13884      0t0  TCP localhost:5038 (LISTEN)
node       6868    asterisk   13u  IPv6 2435746      0t0  TCP *:8001 (LISTEN)
node       6868    asterisk   14u  IPv6 2435747      0t0  TCP *:8003 (LISTEN)
apache2   24214    asterisk    4u  IPv6   10221      0t0  TCP *:http (LISTEN)
apache2   24214    asterisk    6u  IPv6   10225      0t0  TCP *:https (LISTEN)
apache2   24215    asterisk    4u  IPv6   10221      0t0  TCP *:http [...]

root@asterisk:/etc/network# 

The first column shows the application that is bound and listening to that port.  The last column shows the protocol, what IP address it is bound to and what port.  Anything that shows “*:…” means it is listening to all IP addresses on the server.  Anything that shows “localhost:…” means it is listening to a local IP address and is not exposed to the public Internet.

So what are these applications and why do they need to be open to the net?  The first one is “sshd” which you likely are using to log into the server with.

mysqld” is the daemon for the MySQL database that FreePBX uses for configuration and it is bound to the “localhost” so no worry here.  If it isn’t you can see https://serversforhackers.com/c/mysql-network-security for a guide on how to lock down MySQL.

exim4” is a mail server.  Normally this is used for delivery of mail to users when there is voicemail or there is a report that needs to be mailed out to an administrator. 

“asterisk” has a number of ports open.  The “omniorb” port really is port “8088”.  You can see this in the file /etc/services.  The 8089 port is used by the same feature in Asterisk.  This is the “Asterisk GUI” framework.  FreePBX uses this for interaction with Asterisk.  It really should be locked down to the localhost IP address.    You can change this to the localhost IP address of “127.0.0.1” in FreePBX’s “Settings” -> “Advance Settings” tab.  Change the HTTP and HTTPS bind address entries for these ports and click on “Submit” and then “Apply Config”.  Port 5038 is used for the API for Asterisk.  By the default config, it is already bound to locahost / 127.0.0.1.

“node” that is listening on ports 8001 and 8003 is the FreePBX nodejs application that is used for the “User Control Panel (UCP) Node Server” that FreePBX uses.  This is used for a user to check voicemail, etc.   You can map Asterisk to use the localhost IP address by going into the “Settings” and then “Advanced Settings” and go to the section called “UCP NodeJS Server” and update the “Bind Address” to “127.0.0.1”.  (This seems to be not on FreePBX 15 and is already mapped to the localhost.)

Session Initiation Protocol (SIP)

SIP is going to be your biggest risk.   Depending on the distribution of FreePBX/RasPBX/etc., asterisk really has to listen to the SIP ports (5060/5061) so your phones and providers can send commands to Asterisk to do things like making a call.  Having Asterisk just exposed to the Internet at large means that your Asterisk box will be cracked in 30 seconds once you put it on the net.  Hackers love to find an exposed SIP server out there to make outbound calls through your box.  This obscures who is making the call and they don’t have to pay for the VoIP service.  You are.

There are a number of ways to deploy an Asterisk box.  You can either do it behind a firewall with rules on the firewall to allow certain IP addresses to be passed to the Asterisk box or you can have Linux do the filtering.   FreePBX and RasPBX both have FAIL2BAN as an option.   Fail2Ban is a program that scans the logs of various programs like SSH and Asterisk and looks for times that an IP address is trying to crack into your site and was unsuccessful.  If so, it will add a firewall rule on Linux to prevent that IP address from accessing the box for some time frame.  By default, this is about 10 minutes.  After that, the rule is taken out and that IP address can try again.  This can retard the progress of someone trying to crack into your box, but do you really want the hassle?  What happens if they do make through?  Then you may find some rather expensive bills from your VoIP provider.   Unless you really want to be serving up SIP to the rest of the Internet, let’s lock this puppy down.

My installation has a public IP address and I rely on using Linux’s “netfilter” to firewall.  Netfilter can be configured a couple of ways.  The more traditional is to use IPTABLES.  I am not going into detail on how to use IPTABLES as there are plenty of sites that can show you that.

First off, identify the IP addresses you need to allow to connect to your Asterisk box.  This will include your VoIP provider’s session border controller (SBC) that will be protecting their SIP server.  I use VoIP.ms out of Canada and they list their servers on their wiki.  Also, identify the IP addresses that your phones will be using.  This may be on your local LAN or they may be coming from other sites.  Hopefully, these are IP addresses that won’t be changing much.  In times past, I had to run an Asterisk server that had a number of home employees, so they were coming from cable providers that would change the IP address on occasion.  Normally this wouldn’t change that often so it was manageable.  Let’s say you have the following IP  addresses…

  • VOIP provider: 1.1.1.1
  • Your local LAN’s prefix 192.168.0.0/24 assuming your Asterisk box is directly connected.
  • Your local LAN’s public IP address 2.2.2.2/32 if your Asterisk box is not connected to your LAN
  • An offsite worker: 3.3.3.3/32.

You will need to create a file like /etc/iptables/rules.v4 that looks something like:

*filter
# SIP...
-A INPUT -s 1.1.1.1 -p all -m all --dport 5060 -m comment --comment "VoIP Provider" -j ACCEPT
-A INPUT -s 1.1.1.1 -p all -m all --dport 5061 -m comment --comment "VoIP Provider" -j ACCEPT
-A INPUT -s 2.2.2.2 -p all -m all --dport 5060 -m comment --comment "Public IP of Office" -j ACCEPT
-A INPUT -s 2.2.2.2 -p all -m all --dport 5061 -m comment --comment "Public IP of Office" -j ACCEPT
-A INPUT -s 3.3.3.3 -p all -m all --dport 5060 -m comment --comment "Remote Worker" -j ACCEPT
-A INPUT -s 3.3.3.3 -p all -m all --dport 5061 -m comment --comment "Remote Worker" -j ACCEPT
-A INPUT -p all -m all --dport 5060 -m comment --comment "Drop all other SIP connections" -j DROP
-A INPUT -p all -m all --dport 5061 -m comment --comment "Drop all other SIP-TLS connections" -j DROP

In this file, you are allowing SIP access for the IP addresses listed to port 5060 (UDP) and port 5061 (TCP/TLS).  The very last two rules say, if IP addresses don’t match the above, then DROP those packets.

Secure Shell (SSH)

This is another popular service that as soon as you stand up a server, you will see bots knocking at your door.  Again, fail2ban can address this, but why would you want the exposure?  Let’s just lock it down to a couple of IP addresses with IP tables.  Updating the /etc/iptables/rules.v4 file and using the example IP addresses we used for SIP…

# SSH...
-A INPUT -s 2.2.2.2 -p tcp -m tcp --dport 22 -m comment --comment "Office Public IP Address" -j ACCEPT
-A INPUT -s 3.3.3.3 -p tcp -m tcp --dport 22 -m comment --comment "Offisite IT Provider" -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m comment --comment "Drop all other SSH TCP connections" -j DROP
Apache

This is the webserver to get into the FreePBX GUI.  Let’s just lock it down to a couple of IP addresses with IP tables.  Again, updating the /etc/iptables/rules.v4 file and using the example IP addresses we used for SIP…

# Apache...
-A INPUT -s 2.2.2.2 -p tcp -m tcp --dport 80 -m comment --comment "Office Public IP Address" -j ACCEPT
-A INPUT -s 3.3.3.3 -p tcp -m tcp --dport 80 -m comment --comment "Offisite IT Provider" -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -m comment --comment "Drop all other Web TCP connections" -j DROP
-A INPUT -s 2.2.2.2 -p tcp -m tcp --dport 443 -m comment --comment "Office Public IP Address" -j ACCEPT 
-A INPUT -s 3.3.3.3 -p tcp -m tcp --dport 443 -m comment --comment "Offisite IT Provider" -j ACCEPT 
-A INPUT -p tcp -m tcp --dport 443 -m comment --comment "Drop all other Web SSL TCP connections" -j DROP
IPTABLES That is Persistent

I mentioned added these rules to /etc/iptables/rules.v4. We are going to add a bit of config to the networking section of FreePBX to have the server add these rules on reboot.

Simply you need to add the line “pre-up /sbin/iptables-restore /etc/iptables/rules.v4″ for the network interface you are using to /etc/network/interfaces.  It should look something like:

auto eth0
iface eth0 inet static
    pre-up /sbin/iptables-restore /etc/iptables/rules.v4

This tells the server to load the rules you created before it turns up the network interface.

The more recent FreePBX/Raspbx uses dhcpcd.  There is a set of scripts that get run in /lib/dhcpcd/dhcpcd-hooks/.  You can create a file called “/lib/dhcpcd/dhcpcd-hooks/05-iptables” and put “/sbin/iptables-restore /etc/iptables/rules.v4” it in.  This will add the rules before the rest of the network gets turned up.

Check Your work

Reboot your box and see if the IPTABLES loaded.  If you have fail2ban loaded, you will also see entries from it there.

root@asterisk:/home/pozar# iptables --list
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
fail2ban-asterisk  tcp  --  anywhere             anywhere             tcp dpt:sip
fail2ban-asterisk  udp  --  anywhere             anywhere             udp dpt:sip
fail2ban-asterisk  tcp  --  anywhere             anywhere             tcp dpt:sip-tls
fail2ban-ssh  tcp  --  anywhere             anywhere             multiport dports ssh
ACCEPT     any  --  1.1.1.1  anywhere             any dpt:sip /* voip provider */
ACCEPT     tcp  --  1.1.1.1  anywhere             tcp dpt:sip-tls /* voip provider */
ACCEPT     any  --  2.2.2.2       anywhere             any dpt:sip /* Office Public IP */
ACCEPT     tcp  --  2.2.2.2       anywhere             tcp dpt:sip-tls /* Office Public IP */
ACCEPT     any  --  3.3.3.3       anywhere             any dpt:sip /* Joe's Home Office */
ACCEPT     tcp  --  3.3.3.3       anywhere             tcp dpt:sip-tls /* Joe's Home Office */
DROP       any  --  anywhere             anywhere             any dpt:sip /* Drop all other SIP UDP connections */
DROP       tcp  --  anywhere             anywhere             tcp dpt:sip-tls /* Drop all other SIP-TLS connections */
ACCEPT     tcp  -- 2.2.2.2              anywhere             tcp dpt:ssh /* Office Public IP address */
DROP       tcp  --  anywhere             anywhere             tcp dpt:ssh /* Drop all other SSH TCP connections */

Now look at the daemons and see if they are bound to the IP addresses you are expected:

root@asterisk:/home/pozar# lsof -i | grep LIST
sshd       604        root    3u  IPv4  12384      0t0  TCP *:ssh (LISTEN)
sshd       604        root    4u  IPv6  12386      0t0  TCP *:ssh (LISTEN)
apache2   1087        root    4u  IPv6  12480      0t0  TCP *:http (LISTEN)
apache2   1087        root    6u  IPv6  12484      0t0  TCP *:https (LISTEN)
mysqld    1148       mysql   10u  IPv4  13502      0t0  TCP localhost:mysql (LISTEN)
apache2   1176    asterisk    4u  IPv6  12480      0t0  TCP *:http (LISTEN)
apache2   1176    asterisk    6u  IPv6  12484      0t0  TCP *:https (LISTEN)
[...]
exim4     1562 Debian-exim    4u  IPv4  12786      0t0  TCP localhost:smtp (LISTEN)
exim4     1562 Debian-exim    5u  IPv6  12787      0t0  TCP localhost:smtp (LISTEN)
asterisk  1802    asterisk   13u  IPv4  13291      0t0  TCP localhost:omniorb (LISTEN)
asterisk  1802    asterisk   14u  IPv4  13292      0t0  TCP localhost:8089 (LISTEN)
asterisk  1802    asterisk   15u  IPv4  13293      0t0  TCP localhost:5038 (LISTEN)
node      1993    asterisk   13u  IPv4  14461      0t0  TCP localhost:8001 (LISTEN)
node      1993    asterisk   14u  IPv4  14462      0t0  TCP localhost:8003 (LISTEN)
Conclusion

As mentioned in my disclaimer, this likely isn’t everything you need to do but it will make a dent in having your server hijacked for unwanted SIP calls to countries you never thought you called.

 

Blocking traffic by MAC address on Ubiquiti EdgeRouters by Time of Day

See the update at the bottom of this post – Tim 20180211

I have an Ubiquiti EdgeRouter PoE at the house as my main router.  In order to manage “resources” at the house,  I wanted a way to block a couple of MAC addresses at a certain time each day.   I created a filter that blocks by MAC address that looks something like:

set firewall name SWITCH0_IN default-action accept
set firewall name SWITCH0_IN description 'Used for blocking local users'
set firewall name SWITCH0_IN rule 1 action drop
set firewall name SWITCH0_IN rule 1 description APhone
set firewall name SWITCH0_IN rule 1 disable
set firewall name SWITCH0_IN rule 1 log disable
set firewall name SWITCH0_IN rule 1 protocol all
set firewall name SWITCH0_IN rule 1 source mac-address '66:55:44:33:22:11'
set firewall name SWITCH0_IN rule 2 action drop
set firewall name SWITCH0_IN rule 2 description iPhone
set firewall name SWITCH0_IN rule 2 disable
set firewall name SWITCH0_IN rule 2 log disable
set firewall name SWITCH0_IN rule 2 protocol all
set firewall name SWITCH0_IN rule 2 source mac-address '11:22:33:44:55:66'
set firewall name SWITCH0_IN rule 3 action drop
set firewall name SWITCH0_IN rule 3 description Desktop
set firewall name SWITCH0_IN rule 3 disable
set firewall name SWITCH0_IN rule 3 log disable
set firewall name SWITCH0_IN rule 3 protocol all
set firewall name SWITCH0_IN rule 3 source mac-address '12:34:56:78:90:ab'

I applied this rule to the “switch0” interface that talks to my LAN interfaces at eth2, eth3 and eth4.

For the rulesets above, I want to enable rule #2 and #3 for the devices “iPhone” and “Desktop” to block traffic from them.  Two hours later, I want to disable this rule to pass traffic again.  This script does just that…

#!/bin/vbash                                              
# A script to disable access for two MAC addresses at     
# 0330 to 0530 UTC (1930 to 2130 Pacific) everyday.
unblock=0
if [ $# == 1 ]; then
  unblock=1
fi
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
WR="/opt/vyatta/sbin/vyatta-cfg-cmd-wrapper"
$WR begin
if [ $unblock == 1 ]; then
  $WR set firewall name SWITCH0_IN rule 2 disable
  $WR set firewall name SWITCH0_IN rule 3 disable
else
  $WR delete firewall name SWITCH0_IN rule 2 disable
  $WR delete firewall name SWITCH0_IN rule 3 disable
fi
$WR commit                                     
$WR end

There are a couple of ways to configure the router with scripts.  Ubiquiti suggests using the /opt/vyatta/etc/functions/script-template script like:

 

#!/bin/vbash
     
if [ $# == 0 ]; then
  echo usage: $0 
  exit 1
fi
new_ip=$1;
     
source /opt/vyatta/etc/functions/script-template
configure
set interfaces tunnel tun0 local-ip $new_ip
commit
save
exit

This actually breaks due to a bug.  I have had to use the /opt/vyatta/sbin/vyatta-cfg-cmd-wrapper as part of my script.  Works just fine.

The CRON entries that will run the scripts at 0330 and 0530 UTC…

30 3 * * * /home/joeuser/block_mac.sh
30 5 * * * /home/joeuser/block_mac.sh unblock

Updated on Feb 11th 2018...

It seems that either I missed this feature or Ubiquiti just added it.  You can add times to enable and disable the rule.  For instance, in the case of Rule #2 above, you would add starttime and stoptime statements.  You can also specify date of the week or date such as day/month/year.  This has been in Vyatta for a while now.

set firewall name SWITCH0_IN rule 2 action drop
set firewall name SWITCH0_IN rule 2 description iPhone
set firewall name SWITCH0_IN rule 2 disable
set firewall name SWITCH0_IN rule 2 log disable
set firewall name SWITCH0_IN rule 2 protocol all
set firewall name SWITCH0_IN rule 2 source mac-address '11:22:33:44:55:66'
set firewall name SWITCH0_IN rule 2 time starttime '21:00:00'
set firewall name SWITCH0_IN rule 2 time stoptime '22:00:00'
set firewall name SWITCH0_IN rule 2 time utc