-
Notifications
You must be signed in to change notification settings - Fork 10
User Guide
Depending on your file system permissions, you will likely have to execute some of the commands below with sudo or similar to avoid permission errors. You can use sudo -s
in a terminal to keep from having to type sudo before every command, then type "exit" to return to your normal user command prompt when you're finished with the setup. Always exercise caution when running with elevated privileges.
Now that the installation is complete you can move on to setting up your ruleset. Beginning with v2.1.0 of Geolocation for nftables you can flush and refill your geolocation sets atomically with an nftables script that's generated automatically from user settings you create. This is the preferred method for setting up geolocation filtering. The bash script now does error checking at run time to verify that the country codes that you specify to fill your sets actually exist in the current geolocation database. This is important as the free database can drop a few of the smaller country codes in the database from month to month. Manually referencing one of these dropped country codes in your ruleset will cause an nftables error if you're not using this feature.
We'll start by listing the major steps to be done and then go into detail on completing these steps.
- Create an nftables.conf file for testing, using one of the example files in the Wiki.
- Running the bash script for the first time to create the
refill-sets.conf
configuration file. - Configuring the
refill-sets.conf
file with user settings. - Running the bash script again to automatically create the
refill-sets.nft
nftables script to flush and refill the geolocation sets. - Testing the configuration.
- Testing geolocation filtering.
- Finalize user settings with preferred country codes.
The setup is now much easier using the refill-sets.conf
file for configuration settings. This file is automatically created when you run the bash script for the first time. Settings in this file will be used to automatically generate the refill-sets.nft
nftables script that will flush and refill your geolocation sets at boot time and after the monthly database update.
Setup begins with creating an nftables.conf
file for testing. Three example firewall rulesets are available in the Wiki that will allow you to test geolocation filtering. Note that these are basic firewalls for testing purposes and not complete firewalls to protect your system. The three example firewalls to choose from are IPv4 only, IPv6 only and one with both IPv4 and IPv6 support.
After backing up your current nftables.conf file, copy and paste code from one of the example firewalls below to a new file /etc/nftables.conf
(Ubuntu/Debian) or /etc/sysconfig/nftables.conf
(Fedora/Red Hat).
Example IPv4 only firewall
Example IPv6 only firewall
Example IPv4 and IPv6 firewall
Remember to modify the new nftables.conf
file that you just created to change the device_name
in the ingress chain to match the name of your WAN network interface reported by running ip a
or ifconfig
in a terminal. Leave the last line of the file (include line) commented out until all testing is complete. You can test the new nftables.conf
file by restarting nftables.
systemctl restart nftables
If nftables fails to restart you can check the status of nftables to see what the problem is.
systemctl status nftables
Next, if you have an existing refill-sets.nft
script that you created manually (prior to Geolocation for nftables v2.1.0) then you should create a backup of the file, as this file is now generated automatically and will be overwritten.
cp /etc/nftables/geo-nft/refill-sets.nft /etc/nftables/geo-nft/refill-sets.nft.bak
If you ran the bash script during installation then you should have a new configuration file /etc/nftables/geo-nft/refill-sets.conf
. If this file doesn't exist then you can run the bash script to create it.
sudo /etc/nftables/geo-nft/geo-nft.sh
You can also manually run the bash script using the soft link that you created in /usr/sbin:
sudo geo-nft
The next step is to configure the refill-sets.conf
file. This configuration file will allow you to define the 'include' lines to load country sets as well as which geolocation sets you wish to fill with specific country code address ranges. By default this file is created with all settings commented out, so it will be ignored by the bash script until you define settings. To begin configuration, first determine which version of nftables that you have installed.
nft -v
Next, open the configuration file in your favorite text editor.
nano /etc/nftables/geo-nft/refill-sets.conf
Uncomment the appropriate 'include' line(s) in the first section.
If your version of nftables is >= 0.9.4 then you can uncomment the last 'include' line to include all country sets like this (works with IPv4, IPv6, or both):
# Specify 'include' lines to add to refill-sets.nft.
# You can add as many include lines as required.
# ==============================================
#include "/etc/nftables/geo-nft/include-all.ipv4"
#include "/etc/nftables/geo-nft/include-all.ipv6"
include "/etc/nftables/geo-nft/countrysets/*"
If your version of nftables is 0.9.3 or older, then you can uncomment one or both of the first two 'include' lines to include all country sets like this:
# Specify 'include' lines to add to refill-sets.nft.
# You can add as many include lines as required.
# ==============================================
include "/etc/nftables/geo-nft/include-all.ipv4"
include "/etc/nftables/geo-nft/include-all.ipv6"
#include "/etc/nftables/geo-nft/countrysets/*"
Uncomment the first two 'include' lines above if your using both IPv4 and IPv6. Uncomment just the first 'include' line if you're using IPv4 only, or the second 'include' line if you're using IPv6 only.
The next configuration step is to uncomment the appropriate line(s) in the 'define' section. The default define lines provided in this section will work with any of the example firewall rulesets in the Wiki. The geolocation set names used in this section match the set names defined in the firewall rulesets. The example country codes used were chosen randomly due to having relatively few address ranges, making it easier to list and compare the geolocation sets. Each of the example rulesets allow you to geolocation filter in both the netdev
table and the main table (inet
, ip
or ip6
) depending on which ruleset you chose.
Continue the configuration by uncommenting the appropriate 'define-ipv4' or 'define-ipv6' line(s) in the second section.
If you're using both IPv4 and IPv6, then you'll want to uncomment both of the netdev
entries and both of the inet
entries like this:
# Define-Protocol Table Family Table Name Set Name Country Codes To Fill Set
# ==================================================================================
# For 'netdev' table uncomment either or both of the following:
define-ipv4 netdev filter geo-netdev4 AD,BI
define-ipv6 netdev filter geo-netdev6 AQ,BI
# For 'inet' table (IPv4-IPv6) uncomment either or both of the following:
define-ipv4 inet filter geo-inet4 AD
define-ipv6 inet filter geo-inet6 AQ
# For 'ip' table (IPv4 only) uncomment the following:
#define-ipv4 ip filter geo-ip4 AD
# For 'ip6' table (IPv6 only) uncomment the following:
#define-ipv6 ip6 filter geo-ip6 AD
# Add any additional 'define-ipv4' or 'define-ipv6' lines here:
If you're using IPv4 only, then you'll want to uncomment the first netdev
entry and the single ip
entry like this:
# Define-Protocol Table Family Table Name Set Name Country Codes To Fill Set
# ==================================================================================
# For 'netdev' table uncomment either or both of the following:
define-ipv4 netdev filter geo-netdev4 AD,BI
#define-ipv6 netdev filter geo-netdev6 AQ,BI
# For 'inet' table (IPv4-IPv6) uncomment either or both of the following:
#define-ipv4 inet filter geo-inet4 AD
#define-ipv6 inet filter geo-inet6 AQ
# For 'ip' table (IPv4 only) uncomment the following:
define-ipv4 ip filter geo-ip4 AD
# For 'ip6' table (IPv6 only) uncomment the following:
#define-ipv6 ip6 filter geo-ip6 AD
# Add any additional 'define-ipv4' or 'define-ipv6' lines here:
If you're using IPv6 only, then you'll want to uncomment the second netdev
entry and the single ip6
entry like this:
# Define-Protocol Table Family Table Name Set Name Country Codes To Fill Set
# ==================================================================================
# For 'netdev' table uncomment either or both of the following:
#define-ipv4 netdev filter geo-netdev4 AD,BI
define-ipv6 netdev filter geo-netdev6 AQ,BI
# For 'inet' table (IPv4-IPv6) uncomment either or both of the following:
#define-ipv4 inet filter geo-inet4 AD
#define-ipv6 inet filter geo-inet6 AQ
# For 'ip' table (IPv4 only) uncomment the following:
#define-ipv4 ip filter geo-ip4 AD
# For 'ip6' table (IPv6 only) uncomment the following:
define-ipv6 ip6 filter geo-ip6 AD
# Add any additional 'define-ipv4' or 'define-ipv6' lines here:
Configuration of this file for testing is complete, so you can save the file and exit the text editor. Next run the bash script so that it reads the refill-sets.conf
settings and creates the refill-sets.nft
nftables script.
sudo geo-nft
If any errors in the configuration are found, then the bash script will notify you. If not, then you're ready to manually test the refill-sets.nft
nftables script.
sudo nft -f /etc/nftables/geo-nft/refill-sets.nft
Once you have the refill-sets.nft
file working manually you'll need to uncomment the 'include' line on the last line of your /etc/nftables.conf
file. This will fill your geolocation sets during system startup with set data defined in the refill-sets.nft
file. Open the /etc/nftables.conf
file in your favorite text editor.
nano /etc/nftables.conf
Uncomment the last 'include' line in the file so it looks like this. Note that the filename includes an asterisk to allow nftables to load if the file isn't found.
include "/etc/nftables/geo-nft/*refill-sets.nft"
Save the file and exit the text editor.
The next step is to edit your /etc/geo-nft.conf
file to enable the refill script to run automatically after a database update. Open the file in your favorite text editor.
nano /etc/geo-nft.conf
Set the enable_refill
setting to yes.
enable_refill=yes
Confirm that restart_nftables=no in the configuration file (the default), since that setting is mutually exclusive with the enable_refill setting. After editing, save the file and exit the text editor. The refill-sets.nft
script will now run automatically after a database update.
You can test the configuration by manually running the geo-nft.sh
script with:
sudo geo-nft
The script output should show that the flush and refill operation completed successfully. Once this is set up, the geo-nft.sh
script will update the geolocation database each month and atomically flush and refill geolocation sets without interrupting your system's connections to other computers. In the event that your system is turned off during the scheduled monthly database update then the geo-nft.sh
script will run during the next system startup. This configuration is now ready for geolocation testing.
To test geolocation filtering open the refill-sets.conf
file in your favorite text editor.
nano /etc/nftables/geo-nft/refill-sets.conf
Add your own country code to the define line(s) in your main table so that you block outgoing traffic to your own country. For this example we'll assume you're located in the US and you're using both IPv4 and IPv6, so your main table is inet
. Your define lines in the inet
table currently look like this:
# For 'inet' table (IPv4-IPv6) uncomment either or both of the following:
define-ipv4 inet filter geo-inet4 AD
define-ipv6 inet filter geo-inet6 AQ
Add the US country code to the end of each line since the US has both IPv4 and IPv6 addresses.
# For 'inet' table (IPv4-IPv6) uncomment either or both of the following:
define-ipv4 inet filter geo-inet4 AD,US
define-ipv6 inet filter geo-inet6 AQ,US
Save the file and exit the text editor. Changes to the refill-sets.conf
file won't take affect until the bash script is run, so launch the bash script to generate a new refill-sets.nft
script that will flush and fill geolocation sets with the new address ranges.
sudo geo-nft
Next, open a Web browser and visit a website outside of the US, such as the CERN website https://home.cern. You should be able to view this website. Now visit a website in the US, such as https://www.google.com. If this site is unavailable, then geolocation filtering is working properly. Keep in mind that websites that appear to be located in your country may actually be hosted in a data center outside of your country. Likewise, websites that appear to be located outside of your country may be hosted in a data center that's inside your country.
You can list your output chain to see how many packets have been rejected by your geolocation rules. Replace inet
in the command below with ip
if you're using IPv4 only, or ip6
if you're using IPv6 only.
sudo nft list chain inet filter output
Now that testing is complete you'll want to do your final configuration changes to add the country codes that you wish to geolocation filter with. You'll also want to add your standard ruleset rules and make any other changes necessary. Remember to run the bash script after making any changes to the refill-sets.conf
file so that your changes take effect.
If you only want to geolocation filter incoming traffic then you can remove the geolocation sets/rules in your main table and keep the ones in the netdev
table. You can list your ingress chain in the netdev
table to see how many packets have been rejected by your geolocation rules. The following command works with any of the example rulesets.
sudo nft list chain netdev filter ingress
The geo-nft.sh script will now update the geolocation database each month and atomically flush and refill geolocation sets without interrupting your computer's connections. In the event that your system is turned off during the scheduled monthly database update then the geo-nft.sh
script will run during the next system startup. The setup for this configuration is now complete. If you like Geolocation for nftables please consider giving the project a Star at the top of the main project page, as this allows people to find us easier here on GitHub.
A systemd path unit can be set up to monitor the /var/log/geo-nft-error.log
file and notify you if a runtime error occurs with the bash script. This guide has details.
You can also configure systemd to send you an e-mail if the monthly database update fails. Instructions can be found in this guide.
The geo-nft.sh
script builds the country code list from the database itself, instead of using a third party location file that may not be up-to-date. Generating the list directly from the latest geolocation database file ensures that new and expired country codes are accounted for in the address range sets.
The db-ip.com geolocation database contains two non-standard country codes according to their FAQ. The ZZ country code is assigned to invalid address blocks that have by definition, no location and owner such as private or multicast IP addresses. The geo-nft.sh
script will exclude the ZZ country code and won't create any sets associated with this code.
The database also contains a non-standard country code XK, which is used by the European Commission, Switzerland, the Deutsche Bundesbank, SWIFT, and other organizations as a temporary country code for Kosovo. This temporary code has been used for more than a decade, and the database contains approximately 100 IP address ranges representing tens of thousands of valid IPv4 and IPv6 addresses for this code. The geo-nft.sh
script includes the XK country code and will generate sets associated with this code.
The geo-nft.sh
script will automatically generate sets associated with any new country codes that db-ip.com may add to their database in the future.
-
Geolocation for nftables v2.1.0 or greater now checks all country codes referenced in the
refill-sets.conf
file to verify that address ranges for those country codes exist in the updated database each month, preventing nftables errors. The refill-sets.nft script is now created on-the-fly to flush and fill your geolocation sets. The old method of manually creating the refill script is no longer recommended since it doesn't do any country code error checking. -
To keep things simple, the file naming convention used for country set files uses the same name for the defined country code variable as the filename itself. For example, the IPv4 set file for the United States is named
US.ipv4
and contains a defined variableUS.ipv4
. When you reference$US.ipv4
in your ruleset you're actually referencing the defined variable name in the file rather than the filename itself. Following the same naming convention, the IPv6 set file for the United States is namedUS.ipv6
and contains a defined variableUS.ipv6
. The variable definition in each geolocation set file contains the IP address ranges for that particular country code and IP protocol. You can open any of the geolocation set files in your favorite text editor and view the data format as well as details such as the number of address range elements in each set. Geolocation sets are located by default in/etc/nftables/geo-nft/countrysets
. -
By default the base directory for project files is
/etc/nftables/geo-nft
. If you change the base directory defined in the user configuration file/etc/geo-nft.conf
, avoid using a pathname with spaces, links or special characters as this may cause the script to fail. -
Errors detected by the
geo-nft.sh
script will be written to the log file/var/log/geo-nft-error.log
. Any future errors will be appended to the end of the error log file, which can be deleted at any time. This logging is in addition to error logging done by the journal. If you experience an error, one or more of the following commands should help you determine the cause:journalctl -u geo-update.service journalctl -xe systemctl status nftables
-
Be aware that some countries may only have IPv4 addresses or IPv6 addresses. The
geo-nft.sh
script will list those country codes on the screen when run manually from a terminal. While creating your geolocation rules it's a good idea to first check the/etc/nftables/geo-nft/countrysets
directory to verify that the IPv4 or IPv6 country code file exists. If you reference an IPv4 or IPv6 country code variable that isn't defined then nftables will alert you. -
If you would like to upgrade your version of nftables to something newer than what's available in your distribution's repository, then see the nftables Wiki for good information on building and installing nftables from sources.
-
The following examples will give you an idea of how long it takes the
geo-nft.sh
script to run. The script creates ~500 IPv4 and IPv6 set files from the geolocation database in about 11 seconds on a low power 4 core 2200ge server with SSD storage. The script takes about 90 seconds to do the same task on a Raspberry Pi 4 with SD card storage. A number of variables will affect the run time, such as processor speed, storage speed, and whether you generate IPv4 sets, IPv6 sets, or both. -
While the
geo-nft.sh
script does an extensive amount of error checking, nothing is infallible. If you find a use case that could benefit from better error checking, please use the issue tracker to report the problem.
The following commands can help you troubleshoot your nftables ruleset. They will allow you to see how many packets match each firewall rule that uses a counter. The examples below support both IPv4 and IPv6, so each command uses the inet
table family. You can replace inet
with ip
or ip6
if you're using IPv4 only or IPv6 only, respectively.
To list your input chain:
sudo nft list chain inet filter input
To list your output chain:
sudo nft list chain inet filter output
To list the set geo-inet4
in table inet filter:
sudo nft list set inet filter geo-inet4
To list the set geo-inet6
in table inet filter:
sudo nft list set inet filter geo-inet6
To list all sets in table inet filter:
sudo nft list sets inet filter
To list your entire ruleset including set elements:
sudo nft list ruleset
To list your entire ruleset without displaying set elements:
sudo nft -t list ruleset
An additional troubleshooting method is to employ logging. If you want to see which packets don't match any of the rules in your input chain, add a rule just above the final rule so that it logs some of those packets (with a prefix) to your system log. Then you can grep your system log using the prefix to see which packets don't match your input chain rules. This is the rule to add, which also shows the existing final rule in your input chain:
# Log some of the packets (using a prefix) that don't match any rules in the input chain.
limit rate 3/second log prefix "[nft] input no match: " counter comment "Log and rate limit packets that don't match any input rules"
# Drop all other incoming traffic.
counter drop comment "Drop all other incoming traffic"
Then grep your system log for a list of packets that don't match any input rules. Substitute the pathname of your system log if different from the example below.
sudo grep -i -F '[nft] input no match:' /var/log/syslog
You can also add a similar rule to other chains, changing 'input' in the prefix to match the chain name.
Another good troubleshooting tip is to list all of the ports that your server is listening to, so that you can verify that your firewall rules match those ports, and protect all of them.
sudo netstat -ltup
You can print service names instead of port numbers by adding the -n flag.
sudo netstat -lntup
Nmap can also be used to give information about your server ports.
sudo nmap -n -PN -sT -sU -p- localhost
Geolocation for nftables documentation is licensed under the GNU GPLv2 (or at your option, any later version).
For Geolocation for nftables copyright information see the Copyright Notice.
Photos used to create the header image courtesy of NASA Visible Earth.
All trademarks, logos and copyrights are the property of their respective owners.