Ubiquiti routers straight out of the box require security hardening like any Cisco, Juniper, or Mikrotik router. Some very basic configuration changes can be made immediately to reduce attack surface while also implementing best practices, and more advanced changes allow routers to pass compliance scans and formal audits. Almost all of the configuration changes below are included in requirements for PCI and HIPAA compliance, and the best-practice steps are also included in CIS security benchmarks and DISA STIGs.
If you'd like a printable copy of this guide complete with a checklist, links to STIGs, and more in-depth discussions of best practices than will fit in a blog post check out the Ubiquiti EdgeRouter Hardening Guide.
The router that will be used for this article is a brand new Ubiquiti EdgeRouter X, fresh out of the box and updated with the latest firmware (1.8.5 as of this writing). Before going any further ensure that your device is updated with the latest firmware and rebooted.
The device will be configured in a Branch Office-type configuration, with a WAN connection on Eth0, a LAN connected to Eth1, and a Management interface on Eth4.
Addresses for the interfaces are as follows:
- WAN - DHCP from ISP
- LAN - 192.168.60.0/24
- Management - 192.168.61.0/24
LAN and Management interfaces will be assigned the lowest usable address (.1/24) in their respective subnets.
The first step we'll take is disabling any physical network interfaces that aren't in use, denying an intruder access to the device if they somehow got into the wiring closet or server room. To plug into the router they'd have to disconnect a live connection and draw attention by bouncing the port.
First list all the interfaces, making note of the numbers associated with each interface:
On our current EdgeRouter X device this is what we're seeing:
As mentioned earlier we'll be using eth0 for the WAN, and eth1 for the LAN. Let's add interface descriptions so they don't get confused:
set interfaces ethernet eth0 description "WAN" set interfaces ethernet eth1 description "LAN" set interfaces ethernet eth4 description "Management"
Not only does this help us not get confused, it also helps other networking staff keep things straight. Then we'll shut off all the interfaces that aren't live so they can't be used to access the device. In our case we're NOT using interfaces eth2 and eth3, so let's shut them off:
set interfaces ethernet eth2 disable set interfaces ethernet eth3 disable
We'll also take a moment to assign IP addresses to the LAN and Management interfaces:
set interfaces ethernet eth1 address 192.168.60.1/24 set interfaces ethernet eth4 address 192.168.61.1/24
With those changes made let's commit and save the current configuration before moving forward, then show interfaces again to see our changes.
Here's the results:
We see that the interface state has changed and our new descriptions and IP addresses are listed as well.
Next we'll disable or firewall services that don't need to be running or exposed. Disabling a service rather than firewalling it is the most appropriate, long-term solution. It reduces overall attack surface, and ensures that even if a firewall rule gets botched, the service isn't available for an attacker to take advantage of. An Nmap port scan of the router via Eth0 (the WAN port) shows four services running - SSH, HTTP, HTTPS, and NTP as shown below:
We'll restrict access to the HTTP(S) GUI to the Management network so only IT staff plugged into that network can access it. We'll also disable older crypto ciphers that now have documented vulnerabilities and available exploits. The same will happen with SSH. We'll leave NTP running, assuming it's being used as the branch office's NTP time source, but restrict it on the WAN port so it can't be used in NTP DDoS attacks.
First set the HTTP(S) GUI to only listen for connections on the Management (eth4) interface, then disable older, vulnerable ciphers:
set service gui listen-address 192.168.61.1 set service gui older-ciphers disable
Once those changes are committed and saved only hosts on the Management network will be allowed to reach the device's web interface. We'll restrict SSH now in the same way, and also require that SSH v2 be used for all connections. Once the following commands are passed and committed you won't be able to access the device unless you're in the Management network.
set service ssh listen-address 192.168.61.1 set service ssh protocol-version v2
The Ubiquiti factory-default username and password combination of "ubnt" and "ubnt" is widely known and publicly available, and many compliance and security scanners like Tenable's Nessus check for factory default credentials. Compliance standards like PCI-DSS and HIPAA strictly forbid the use of factory-default credentials. In keeping with that spirit we will set up our own credentials, and remove the factory-default set. First, I'll create an admin user for myself:
set system login user tyler set system login user tyler full-name "Tyler Hart" set system login user tyler authentication plaintext-password 1234 set system login user tyler level admin
In place of the "1234" password you should use a suitably secure password that meets your organization's security and compliance requirements. Although the command setting the password uses the phrase "plaintext-password", the system will encrypt it for you. Only after setting my full name and a strong password do I pass the final command, giving myself "admin"-level privileges. Commit and save the new credentials, log out of the default "ubnt" user, and log in with your own admin-level credentials. Logged in as yourself, delete the built-in "ubnt" user so that it can't ever be used to breach the router:
delete system login user ubnt
If you're not comfortable deleting the built-in "ubnt" user you must set a complex password, because port scanners will attempt to login with factory credentials given the opportunity. Each device administrator should have their own credentials, so it's possible to see who changed what and when on the device. If all admins log in as the same user there is no non-repudiation, and no way to tell who may have made a malicious configuration change.
Ubiquiti routers come with neighbor discovery turned on by default, which is great for convenience but not great for security. It runs on UDP port 10001, and allows administrators to easily see what devices are on the network and how they are addressed. Unfortunately it can also allow attackers to easily fingerprint a network, and can help them discover soft targets faster than they might otherwise. Having neighbor discovery turned on can also make attackers aware of other devices they may not have seen otherwise because of network segmentation. We'll shut off neighbor discovery to start with:
set service ubnt-discover disable
This disables the neighbor discovery service on all ports, both physical and virtual. It also ensures that any new virtual interfaces won't run neighbor discovery when they are created. If you'd like to use neighbor discovery, you should disable it on all ports except those you want it running on. This could mean adding a lot more configuration lines, but that is the current state of things. Best practice says that you should run neighbor discovery protocols like CDP, LLDP, etc only on management interfaces.
Firewalling is a complex topic, but there are basic rules that can be put in place to secure a device from port scanners, malicious login attempts, and other probes from the WAN. We'll create a firewall rule specifically for inbound traffic on the WAN, and give it a good description:
set firewall name WAN_In set firewall name WAN_In description "Block WAN Probes"
Once the rule is created and described we'll set the default action that the rule should take for matching packets. With this rule being on the inbound side of our WAN, port scanners and others will be hitting it, so the default action should be to "drop":
set firewall name WAN_In default-action drop
If traffic doesn't match the rules we'll create in just a moment, then the default action takes place and that traffic gets dropped. You may be tempted to use the "reject" action instead of "drop", but even rejected packets can help a port scanner fingerprint your router. The best option is to just silently "drop" the packets, and this is required for PCI-DSS.
The first rule in "WAN_In" will allow any connections through the firewall with states of either "Established" or "Related". This is authorized traffic that originated properly, and should be quickly allowed through the firewall:
set firewall name WAN_In rule 1 action accept set firewall name WAN_In rule 1 description "Allow Established / Related Traffic" set firewall name WAN_In rule 1 state established enable set firewall name WAN_In rule 1 state related enable
Next we'll define an Address Group of trusted external IPs. We'll allow remote connections to the router via the WAN, but only from those trusted IPs. First, create the Address Group, then set a description:
set firewall group address-group Trusted_IPs set firewall group address-group Trusted_IPs description "External Trusted IPs"
Add any trusted external IP addresses you have to this list. This could be for a site-to-site VPN, ICMP echos to check if the device is up, SNMP monitoring traffic, or anything else. I'll use 18.104.22.168 and 22.214.171.124 just as examples:
set firewall group address-group Trusted_IPs address 126.96.36.199 set firewall group address-group Trusted_IPs address 188.8.131.52
Now we'll create a firewall rule in WAN_In and reference the address group created above:
set firewall name WAN_In rule 2 action accept set firewall name WAN_In rule 2 description "Allow Trusted IPs" set firewall name WAN_In rule 2 source group address-group Trusted_IPs
By default Ubiquiti devices accept all ICMP requests, including echo requests or "pings". We only want the WAN interface responding to pings from our trusted IPs, so there are two options. The first is to disable all ICMP replies globally:
set firewall all-ping disable
This is quick and easy, but it also removes the use of ICMP as a troubleshooting tool. The second option is to create a third firewall rule for WAN_In, specifically dropping ICMP and echo replies but letting it run elsewhere:
set firewall name WAN_In rule 3 action drop set firewall name WAN_In rule 3 description "Drop ICMP" set firewall name WAN_In rule 3 protocol icmp set firewall name WAN_In rule 3 icmp type 8
At this point we're ready to apply the rule on the inbound side of the WAN (Eth0) interface. Traffic that has a state of "Established" or "Related", and traffic from IPs in the Trusted_IPs list will be allowed. Everything else (port scans, login attempts, pings, etc) will be dropped by the default action. We've created the firewall entry, added rules to it, now we'll apply it:
set interfaces ethernet eth0 firewall in name WAN_In set interfaces ethernet eth0 firewall local name WAN_In
We'll commit and save the configuration, then run another port scan like before. You can see the results below, scanning both TCP and UDP:
Nmap can tell there is something there and it's a Ubiquiti router only because the scanning computer is directly connected to it and can see the MAC address via the physical link. Were this a production router being scanned across a WAN connection there wouldn't be that information, and it would appear that the WAN IP has no device assigned to it. This is exactly what we want remote scanners to see - nothing at all.
It's best to set up logging to an external repository, like a Syslog server. If a device is ever compromised or the configuration tampered with by an insider, the logs on the local device become suspect. Sending logs to an external server and archiving them preserves logs for investigations and forensics, and can ensure their integrity remains intact.
See the Ubiquiti Syslog article for directions on how to configure Syslog logging.
In that same vein it's important to ensure that the timestamps of your log entries are accurate. It's also important that the clocks of all your routers are actively updated, so if you need to correlate events between devices you know that their time is correct.
See the Ubiquiti NTP article for directions on configuring NTP and keeping clocks in sync.