summaryrefslogtreecommitdiff
path: root/src/conf_mode/firewall.py
diff options
context:
space:
mode:
authorsarthurdev <965089+sarthurdev@users.noreply.github.com>2022-06-01 11:53:18 +0200
committersarthurdev <965089+sarthurdev@users.noreply.github.com>2022-06-11 15:08:45 +0200
commit8ba45cfcc1cc3fba57e1f82fa1299b7c253ba5ea (patch)
tree37068db2932e20ed4aec01329c9e60d16eb769ed /src/conf_mode/firewall.py
parentfe18efba34c5d95d3052c9e6fda69668bbfe63f3 (diff)
downloadvyos-1x-8ba45cfcc1cc3fba57e1f82fa1299b7c253ba5ea.tar.gz
vyos-1x-8ba45cfcc1cc3fba57e1f82fa1299b7c253ba5ea.zip
firewall: T4299: Add support for GeoIP filtering
Diffstat (limited to 'src/conf_mode/firewall.py')
-rwxr-xr-xsrc/conf_mode/firewall.py61
1 files changed, 60 insertions, 1 deletions
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py
index 792e17b85..46b8add59 100755
--- a/src/conf_mode/firewall.py
+++ b/src/conf_mode/firewall.py
@@ -26,6 +26,7 @@ from vyos.config import Config
from vyos.configdict import dict_merge
from vyos.configdict import node_changed
from vyos.configdiff import get_config_diff, Diff
+from vyos.firewall import geoip_update
from vyos.firewall import get_ips_domains_dict
from vyos.firewall import nft_add_set_elements
from vyos.firewall import nft_flush_set
@@ -35,6 +36,7 @@ from vyos.template import render
from vyos.util import call
from vyos.util import cmd
from vyos.util import dict_search_args
+from vyos.util import dict_search_recursive
from vyos.util import process_named_running
from vyos.util import run
from vyos.xml import defaults
@@ -150,6 +152,38 @@ def get_firewall_zones(conf):
return {'name': used_v4, 'ipv6_name': used_v6}
+def geoip_updated(conf, firewall):
+ diff = get_config_diff(conf)
+ node_diff = diff.get_child_nodes_diff(['firewall'], expand_nodes=Diff.DELETE, recursive=True)
+
+ out = {
+ 'name': [],
+ 'ipv6_name': [],
+ 'deleted_name': [],
+ 'deleted_ipv6_name': []
+ }
+ updated = False
+
+ for key, path in dict_search_recursive(firewall, 'geoip'):
+ if path[0] == 'name':
+ out['name'].append(f'GEOIP_CC_{path[1]}_{path[3]}')
+ elif path[0] == 'ipv6_name':
+ out['ipv6_name'].append(f'GEOIP_CC_{path[1]}_{path[3]}')
+ updated = True
+
+ if 'delete' in node_diff:
+ for key, path in dict_search_recursive(node_diff['delete'], 'geoip'):
+ if path[0] == 'name':
+ out['deleted_name'].append(f'GEOIP_CC_{path[1]}_{path[3]}')
+ elif path[0] == 'ipv6-name':
+ out['deleted_ipv6_name'].append(f'GEOIP_CC_{path[1]}_{path[3]}')
+ updated = True
+
+ if updated:
+ return out
+
+ return False
+
def get_config(config=None):
if config:
conf = config
@@ -174,6 +208,8 @@ def get_config(config=None):
key_mangling=('-', '_'), get_first_key=True,
no_tag_node_value_mangle=True)
+ firewall['geoip_updated'] = geoip_updated(conf, firewall)
+
return firewall
def verify_rule(firewall, rule_conf, ipv6):
@@ -219,6 +255,16 @@ def verify_rule(firewall, rule_conf, ipv6):
if side in rule_conf:
side_conf = rule_conf[side]
+ if dict_search_args(side_conf, 'geoip', 'country_code'):
+ if 'address' in side_conf:
+ raise ConfigError('Address and GeoIP cannot both be defined')
+
+ if dict_search_args(side_conf, 'group', 'address_group'):
+ raise ConfigError('Address-group and GeoIP cannot both be defined')
+
+ if dict_search_args(side_conf, 'group', 'network_group'):
+ raise ConfigError('Network-group and GeoIP cannot both be defined')
+
if 'group' in side_conf:
if {'address_group', 'network_group'} <= set(side_conf['group']):
raise ConfigError('Only one address-group or network-group can be specified')
@@ -322,8 +368,13 @@ def cleanup_commands(firewall):
commands = []
commands_end = []
for table in ['ip filter', 'ip6 filter']:
+ geoip_list = []
+ if firewall['geoip_updated']:
+ geoip_key = 'deleted_ipv6_name' if table == 'ip6 filter' else 'deleted_name'
+ geoip_list = dict_search_args(firewall, 'geoip_updated', geoip_key) or []
+
state_chain = 'VYOS_STATE_POLICY' if table == 'ip filter' else 'VYOS_STATE_POLICY6'
- json_str = cmd(f'nft -j list table {table}')
+ json_str = cmd(f'nft -t -j list table {table}')
obj = loads(json_str)
if 'nftables' not in obj:
continue
@@ -353,6 +404,8 @@ def cleanup_commands(firewall):
commands.append(f'delete rule {table} {chain} handle {handle}')
elif 'set' in item:
set_name = item['set']['name']
+ if set_name.startswith('GEOIP_CC_') and set_name not in geoip_list:
+ continue
commands_end.append(f'delete set {table} {set_name}')
return commands + commands_end
@@ -476,6 +529,12 @@ def apply(firewall):
if firewall['policy_resync']:
resync_policy_route()
+ if firewall['geoip_updated']:
+ # Call helper script to Update set contents
+ if 'name' in firewall['geoip_updated'] or 'ipv6_name' in firewall['geoip_updated']:
+ print('Updating GeoIP. Please wait...')
+ geoip_update(firewall)
+
post_apply_trap(firewall)
return None