def ifaceup(): env.configure() logger.info(f'Running: {" ".join(sys.argv)}') libgw.load() if os.environ.get('IFACE'): ifname = os.environ['IFACE'] elif len(sys.argv) >= 2: ifname = sys.argv[1] else: return iface = libgw.Interface.get(ifname) if not iface or not iface.exists: logger.error(f'iface does not found in libgw: {ifname}') return if iface.config and iface.config.devgroup: logger.info( f'setting iface group, iface={ifname} group={iface.config.devgroup}' ) xcall([ 'ip', 'link', 'set', 'dev', ifname, 'group', str(iface.config.devgroup) ]) from .setup import setup_firewall, setup_route setup_firewall() setup_route()
def __init__(self, name, link=None, interface=None, interfaces=None, gateway=None, **kwargs): self.name = name # TODO should check if the link name exists self.link = link if interface and interfaces: logger.error( '[GatewayConfigure] interface and interfaces are exclusive') raise ValueError( '"interface" and "interfaces" can not be used together') if gateway and interfaces: logger.error( '[GatewayConfigure] interface and interfaces are exclusive') raise ValueError( '"gateway" and "interfaces" can not be used together') # TODO should check if interface exists if interfaces: self.single_interface_mode = False self.interfaces = interfaces else: self.single_interface_mode = True self.interface = interface or name self.gateway = gateway
def __init__(self, name, devgroup=None, gateway=None, table=None, **kwargs): self.name = name # TODO Support user defined group names in /etc/iproute2/group devgroup = { 'wan': 1, 'lan': 2, 'guest': 3, 'tunnel': 4 }.get(devgroup, None) if not (devgroup is None or isinstance(devgroup, int)): logger.error( f'[InterfaceConfig] Invalid devgroup valud: {devgroup}') raise ValueError(f'Invalid devgroup value: {devgroup}') self.devgroup = devgroup # Gateway address must be valid ip address (not cidr). # ip_address() supports both v4 and v6, however we currently only consider v6. if gateway: try: ipaddress.ip_address(gateway) except ipaddress.AddressValueError: logger.error( f'[InterfaceConfig] Invalid gateway value (must be valid ip address): {gateway}' ) raise self.gateway = gateway
def xcall(command, **kwargs): from gwtool.env import logger logger.info(f'Call command: {" ".join(command)}') silence_error = kwargs.pop('silence_error', False) if silence_error: kwargs["stderr"] = DEVNULL ret = call(command, **kwargs) if ret != 0 and not silence_error: logger.error(f'ERROR: command exited with non-zero: {ret}')
def __init__(self, config_file): if config_file.exists(): logger.info(f'Loading gateway config file: {config_file}') try: with config_file.open(encoding='utf8') as fp: content = yaml.safe_load(fp) except Exception: logger.error( f'Error loading gateway config file: {config_file}') raise else: logger.info( f'Config file does not exist: {config_file}, assume empty config' ) content = {} self.interfaces = {} for name, config in content.get('interfaces', {}).items(): self.interfaces[name] = InterfaceConfig(name, **config) self.gateways = {} for name, config in content.get('gateways', {}).items(): self.gateways[name] = GatewayConfig(name, **config) self.route_tables = {} for table, entries in content.get('routing', {}).get('tables', {}).items(): self.route_tables[table] = RouteTableConfig(table, entries) self.route_rules = [] for rule in content.get('routing', {}).get('rules', []): self.route_rules.append(RouteRuleConfig(rule=rule)) netzone_search_path = [] paths = content.get('netzone_search_path', []) if not isinstance(paths, list): logger.error( 'Config Error: netzone_search_path must be list of paths') raise ValueError( 'Invalid netzone_search_path, must be list of paths') for path in paths: netzone_search_path.append(Path(path)) netzone_search_path.append(env.codespace / 'netzones') self.netzone_search_path = netzone_search_path self.firewall_script = content.get('firewall_entry', None)
def create_route_table(table, entries): iproute(f'flush table {table}') lines = [] for (target, gateway_name) in entries: gateway = Gateway.get(gateway_name) if not gateway: logger.error( f'invalid gateway in route table {table}: {gateway_name}, rule skipped' ) continue if not gateway.available: logger.error( f'gateway is not available: {gateway_name}, rule skipped') continue if is_valid_cidr(target): iproute(f'replace table {table} {target} {gateway.gwdef}') continue zone = NetZone.get(target) if not zone: logger.error( f'invalid target in route table {table}: {target}, rule skipped' ) continue for prefix in zone.cidr_list: lines.append( f'route replace table {table} {prefix} {gateway.gwdef}\n') if not lines: logger.warning(f'No rules for table: {table}') return with tempfile.NamedTemporaryFile() as f: f.write(''.join(lines).encode('ascii')) f.flush() xcall(['ip', '-batch', '-'], stdin=open(f.name))