firewall/nat.py

204 lines
5.9 KiB
Python
Raw Normal View History

2019-01-16 21:57:50 +00:00
#! /usr/bin/python3
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# Copyright © 2019 Hugo Levy-Falk <me@klafyvel.me>
"""
Creates the nat set.
"""
import logging
from configparser import ConfigParser
import netaddr
from firewall import NetfilterSet
CONFIG = ConfigParser()
CONFIG.read('config.ini')
2019-03-12 21:06:21 +00:00
def get_ip_iterable_from_str(ip):
try:
ret = netaddr.IPGlob(ip)
except netaddr.core.AddrFormatError:
try:
ret = netaddr.IPNetwork(ip)
except netaddr.core.AddrFormatError:
begin,end = ip.split('-')
ret = netaddr.IPRange(begin,end)
return ret
2019-01-16 21:57:50 +00:00
def create_nat(name, range_in, range_out, first_port, last_port):
"""Create two nftables tables for the nat:
- <name>_address : which link a (or a range of) local address to a
public address;
- <name>_port : which links a local address to a
range of ports.
Args:
name: name of the sets
range_in: an IPRange with the private IP address
range_out: an IPRange with the public IP address
first_port: the first port used for the nat
last_port: the last port used for the nat
Returns:
(<name>_address, <name>_port) which are NetfilterSet
"""
2019-03-12 21:06:21 +00:00
assert 0 <= first_port < last_port < 65536, (name + ": Your first_port "
2019-01-16 21:57:50 +00:00
"is lower than your last_port")
2019-03-12 21:06:21 +00:00
nb_private_by_public = range_in.size // range_out.size
nb_port_by_ip = (last_port - first_port + 1) // nb_private_by_public
2019-01-16 21:57:50 +00:00
2019-03-12 21:06:21 +00:00
ports = {}
ips = {}
2019-01-16 21:57:50 +00:00
port = first_port
2019-03-12 21:06:21 +00:00
for ip in range_in:
ports[(str(netaddr.IPAddress(ip)),)] = ("%d-%d" % (port, min(port+nb_port_by_ip, 65535)),)
2019-01-16 21:57:50 +00:00
port += nb_port_by_ip + 1
if port >= last_port:
port = first_port
ip = range_in.first
for ip_out in range_out:
2019-03-12 21:06:21 +00:00
ips[('-'.join([
2019-01-16 21:57:50 +00:00
str(netaddr.IPAddress(ip)),
str(netaddr.IPAddress(ip+nb_private_by_public))
2019-03-12 21:06:21 +00:00
]),)] = (str(ip_out),)
2019-01-16 21:57:50 +00:00
ip += nb_private_by_public + 1
return (
NetfilterSet(
target_content=ips,
2019-03-12 21:06:21 +00:00
type_=('IPv4',),
name=name+'_nat_address',
2019-01-16 21:57:50 +00:00
table_name='nat',
2019-03-12 21:06:21 +00:00
flags=('interval',),
type_from=('IPv4',)
2019-01-16 21:57:50 +00:00
),
NetfilterSet(
target_content=ports,
2019-03-12 21:06:21 +00:00
type_=('port',),
name=name+'_nat_port',
2019-01-16 21:57:50 +00:00
table_name='nat',
2019-03-12 21:06:21 +00:00
flags=('interval',),
type_from=('IPv4',)
2019-01-16 21:57:50 +00:00
),
)
def create_nat_adherent():
2019-03-12 21:06:21 +00:00
range_in = get_ip_iterable_from_str(CONFIG['NAT']['range_in_adherent'])
range_out = get_ip_iterable_from_str(CONFIG['NAT']['range_out_adherent'])
first_port = int(CONFIG['NAT']['first_port_adherent'])
last_port = int(CONFIG['NAT']['last_port_adherent'])
2019-01-16 21:57:50 +00:00
return create_nat(
'adherent',
range_in,
range_out,
first_port,
last_port
)
def create_nat_federez():
2019-03-12 21:06:21 +00:00
range_in = get_ip_iterable_from_str(CONFIG['NAT']['range_in_federez'])
range_out = get_ip_iterable_from_str(CONFIG['NAT']['range_out_federez'])
first_port = CONFIG['NAT']['first_port_federez']
last_port = CONFIG['NAT']['last_port_federez']
2019-01-16 21:57:50 +00:00
return create_nat(
'federez',
range_in,
range_out,
first_port,
last_port
)
def create_nat_aloes():
2019-03-12 21:06:21 +00:00
range_in = get_ip_iterable_from_str(CONFIG['NAT']['range_in_aloes'])
range_out = get_ip_iterable_from_str(CONFIG['NAT']['range_out_aloes'])
first_port = CONFIG['NAT']['first_port_aloes']
last_port = CONFIG['NAT']['last_port_aloes']
2019-01-16 21:57:50 +00:00
return create_nat(
'aloes',
range_in,
range_out,
first_port,
last_port
)
def create_nat_admin():
2019-03-12 21:06:21 +00:00
range_in = get_ip_iterable_from_str(CONFIG['NAT']['range_in_admin'])
range_out = get_ip_iterable_from_str(CONFIG['NAT']['range_out_admin'])
first_port = CONFIG['NAT']['first_port_admin']
last_port = CONFIG['NAT']['last_port_admin']
2019-01-16 21:57:50 +00:00
return create_nat(
'admin',
range_in,
range_out,
first_port,
last_port
)
def create_nat_prerezotage():
2019-03-12 21:06:21 +00:00
range_in = get_ip_iterable_from_str(CONFIG['NAT']['range_in_prerezotage'])
range_out = get_ip_iterable_from_str(CONFIG['NAT']['range_out_prerezotage'])
first_port = CONFIG['NAT']['first_port_prerezotage']
last_port = CONFIG['NAT']['last_port_prerezotage']
2019-01-16 21:57:50 +00:00
return create_nat(
'prerezotage',
range_in,
range_out,
first_port,
last_port
)
def main():
logging.info("Creating adherent nat...")
address, port = create_nat_adherent()
address.manage()
port.manage()
logging.info("Done.")
2019-03-12 21:06:21 +00:00
#logging.info("Creating federez nat...")
#address, port = create_nat_federez()
#address.manage()
#port.manage()
#logging.info("Done.")
#logging.info("Creating aloes nat...")
#address, port = create_nat_aloes()
#address.manage()
#port.manage()
#logging.info("Done.")
#logging.info("Creating admin nat...")
#address, port = create_nat_admin()
#address.manage()
#port.manage()
#logging.info("Done.")
#logging.info("Creating prerezotage nat...")
#address, port = create_nat_prerezotage()
#address.manage()
#port.manage()
#logging.info("Done.")
if __name__=='__main__':
logging.info('Updating the NAT table.')
main()