Why?
I have a small webserver running inside my network on port 55555. I only want my friends to be able to access it. I know that they live in Denmark, Norway and Sweden. I want to make sure that China, Russia and other parts of the world has no access, in order to minimize the risk of exploiting 0-days on my server.
Edgerouter configuration
This is the configuration I add:
set firewall group network-group countries_allowed description 'Allowed countries' set firewall group network-group countries_allowed network 10.254.254.254/31 set service nat rule 10 description 'My funny dmz server' set service nat rule 10 destination group address-group ADDRv4_eth0 set service nat rule 10 destination port 55555 set service nat rule 10 inbound-interface eth0 set service nat rule 10 inside-address address 192.168.xxx.xxx set service nat rule 10 inside-address port 55555 set service nat rule 10 protocol tcp set firewall name WAN_IN rule 20 action accept set firewall name WAN_IN rule 20 description 'My funny dmz server' set firewall name WAN_IN rule 20 destination port 55555 set firewall name WAN_IN rule 20 protocol tcp set firewall name WAN_IN rule 20 source group network-group countries_allowed commit
This basically does the following:
- Creates a network-group that will be a placeholder for all the subnets I want to allow accessing my server. I add only one rule, that will be there when the Edgerouter is booted. That means that everything (except an arbitrary/random ip 10.254.254.254) is blocked until the real country-rules are loaded later.
- Then it makes a NAT forward rule that forwards all traffic to port 55555 comming in on my outside interface(eth0) to my internal server
- Allows the traffic to my server in the firewall if the traffic originates from my network-group “countries_allowed”
Getting subnets of countries
I now create a script file “/config/scripts/post-config.d/country-load” (chmod 755):
#!/bin/bash countryList="dk no se" firewallGroupName=countries_allowed #mkdir /config/zonefiles function loadcountry () { firewallGroupName=$1 country=$2 echo "Downloading country definition for $country..." >> /var/log/alex wget http://www.ipdeny.com/ipblocks/data/countries/${country}.zone -O /config/zonefiles/${country}.zone -q echo "Adding rules to firewall group $firewallGroupName..." >> /var/log/alex for rule in `cat /config/zonefiles/${country}.zone`; do ipset add $firewallGroupName $rule done } ipset -F $firewallGroupName for country in $countryList; do loadcountry $firewallGroupName $country done
This script will run when the Edgerouter boots. It will:
- Traverse the list of countries defined in the top of the script
- Download a list of subnets in each country
- Add it to the ipset table (thats what the Edgerouter uses for network-groups)
Testing
After rebooting the edgerouter or manually running the script, you can check that we actually got some subnets in our network-group:
ipset -L countries_allowed
Dont be fooled by looking in the GUI – it will know nothing about all this happening behind the scenes!
Be careful!
If you do any change to the network group “countries_allowed” from the GUI, the Edgerouter will empty the list generated from the script! Don’t do that 🙂
Cool! Nice job!
Now I can limit access to my management servers to .DK only…
Another example on how to do that :
https://community.ubnt.com/t5/EdgeMAX/GEOip-network-groups-creation-script/m-p/1435605#M91400
I get this error ?
NAT configuration error: rule type not specified/valid
Jeg fik det fik at virke ved at tilføje: set service nat rule 10 type destination
wget er vist ikke på som standard så blev nød til at ændre: “wget http://www.ipdeny.com/ipblocks/data/countries/${country}.zone -O /config/zonefiles/${country}.zone -q”
Til: “curl http://www.ipdeny.com/ipblocks/data/countries/${country}.zone -o /config/zonefiles/${country}.zone -s”
Godt at du fik det til at virke 🙂
Great trick.
Since I’ve implemented it (plus modified for other rules), there are no more ssh brute force attacks, I’ve had from china, brasil, india. One hour after … my fail2ban.log is all alone 🙂
One note thou ….. what if the site ipdeny.com is down ? Is there another resource that lists IPs by countries ?
Hi Alex,
I like your solution to IP blocking of external IPs. I understand the shell script but I’m not familiar with the “set service” cmd. I’m not sure what I need to do to block just Russia and China IPs on all ports and allowing other IPs to access my network. I have a couple of port forwarding rules defined via the GUI which I need to protect. Can you provide me with “set service” I should add/delete or change?
Thx much
Clyde
My ERL on v1.10.7 says:
ipset command not found when running the script. Has this been changed?