def init(ip4_network): check_compatibility() address4 = str(ip4_network.network_address + 1) netmask = str(ip4_network.netmask) rc_conf_mod('cloned_interfaces+=%s' % cloned_if()) cmd('service', 'netif', 'cloneup') rc_conf_mod('ifconfig_%s=inet %s netmask %s' % (cloned_if(), address4, netmask)) cmd('ifconfig', cloned_if(), 'inet', address4, 'netmask', netmask) rc_conf_mod('jail_enable=YES') cmd( 'mkdir', '-p', '/var/mjail/instances/', '/var/mjail/releases/', '/var/mjail/generated_confs/' ) cmd('chmod', '700', '/var/mjail/instances/', '/var/mjail/releases/') cmd('chmod', '755', '/var/mjail/', '/var/mjail/generated_confs/') try: jail_conf = jailconf.load('/etc/jail.conf') except FileNotFoundError: jail_conf = jailconf.JailConf() jail_conf['exec.start'] = '"/bin/sh /etc/rc"' jail_conf['exec.stop'] = '"/bin/sh /etc/rc.shutdown"' jail_conf['exec.clean'] = True jail_conf['mount.devfs'] = True jail_conf['path'] = '"/var/mjail/instances/$name"' jail_conf.write('/etc/jail.conf') release = Release() if not release.built(): release.build() LocalUnboundManager.enable() PFManager.enable()
def _set_ip(self, ip, version, network): if ip not in network: raise ValueError("Can't assign this ip to the jail. " "The ip should belong to the network %s" % network) jail_conf = get_jail_conf() for jail_name, jail_block in jail_conf.jails(): try: ip_addr = jail_block['ip%s.addr' % version] except KeyError: continue if ip_addr == str(ip): raise IPAlreadyRegistered elif isinstance(ip_addr, (list, tuple)): if str(ip) in ip_addr: raise IPAlreadyRegistered jail_conf[self.name]['interface'] = cloned_if() jail_conf[self.name]['ip%s.addr' % version] = str(ip) jail_conf.write('/etc/jail.conf') self._update_resolv_conf() PFManager.refresh_anchor() line = '%s %s\n' % (str(ip), self.name) lines = open('/etc/hosts').readlines() if line not in lines: lines.append(line) temp_etc_hosts = to_tempfile(''.join(lines)) shutil.move(temp_etc_hosts, '/etc/hosts')
def set_ip4(self, ip4): assert isinstance(ip4, IPv4Address) jail_conf = get_jail_conf() for jail_name, jail_block in jail_conf.jails(): try: ip4_addr = jail_block['ip4.addr'] except KeyError: continue if ip4_addr == str(ip4): raise IPAlreadyRegistered elif isinstance(ip4_addr, (list, tuple)): if str(ip4) in ip4_addr: raise IPAlreadyRegistered jail_conf[self.name]['interface'] = cloned_if() jail_conf[self.name]['ip4.addr'] = str(ip4) jail_conf.write('/etc/jail.conf') PFManager.refresh_anchor() line = '%s %s\n' % (str(ip4), self.name) lines = open('/etc/hosts').readlines() if line not in lines: lines.append(line) temp_etc_hosts = to_tempfile(''.join(lines)) shutil.move(temp_etc_hosts, '/etc/hosts')
def init(ip4_network: IPv4Network, ip6_network: IPv6Network): if not ip4_network.is_private: raise ValueError( "The network should be private. " "see https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses" ) if not ip6_network.is_private or not ip6_network.prefixlen == 64: raise ValueError( "The network should be a private network as defined in https://tools.ietf.org/html/rfc4193.html" ) check_compatibility() rc_conf_mod('cloned_interfaces+=%s' % cloned_if()) cmd('service', 'netif', 'cloneup') address4 = str(ip4_network.network_address + 1) netmask = str(ip4_network.netmask) rc_conf_mod('ifconfig_%s=inet %s netmask %s' % (cloned_if(), address4, netmask)) cmd('ifconfig', cloned_if(), 'inet', address4, 'netmask', netmask) address6 = str(ip6_network.network_address + 1) rc_conf_mod('ifconfig_%s_ipv6=inet6 %s prefixlen 64' % (cloned_if(), address6)) cmd('ifconfig', cloned_if(), 'inet6', address6, 'prefixlen', '64') rc_conf_mod('jail_enable=YES') cmd('mkdir', '-p', '/var/mjail/instances/', '/var/mjail/releases/', '/var/mjail/generated_confs/') cmd('chmod', '700', '/var/mjail/instances/', '/var/mjail/releases/') cmd('chmod', '755', '/var/mjail/', '/var/mjail/generated_confs/') try: jail_conf = jailconf.load('/etc/jail.conf') except FileNotFoundError: jail_conf = jailconf.JailConf() jail_conf['exec.start'] = '"/bin/sh /etc/rc"' jail_conf['exec.stop'] = '"/bin/sh /etc/rc.shutdown"' jail_conf['exec.clean'] = True jail_conf['mount.devfs'] = True jail_conf['path'] = '"/var/mjail/instances/$name"' jail_conf.write('/etc/jail.conf') release = Release() if not release.built(): release.build() LocalUnboundManager.enable() PFManager.enable()
def _anchor_conf(cls): ext_if = get_ext_if() filter_rules = [] translation_rules = [] jail_conf = get_jail_conf() jails = [ jail_block for name, jail_block in jail_conf.jails() if ( jail_block.get('$mjail_managed') == 'yes' and jail_block.get('ip4.addr') ) ] cif = cloned_if() def append_jail_line(rules, jail, *strgs, **formats): for strg in strgs: rules.append( strg.format( ext_if = ext_if, cif = cif, ip4 = jail['ip4.addr'], **formats ) ) for jail in jails: append_jail_line( translation_rules, jail, 'nat on {ext_if} inet from {ip4} to any -> ({ext_if})' ) append_jail_line( filter_rules, jail, 'pass quick on {cif} inet proto udp from {ip4} to ({cif}) port 53', 'pass quick on {cif} inet proto tcp from {ip4} to ({cif}) port 53' ) for key in jail: if key.startswith('$mjail_rdr_'): proto, host_port = key[len('$mjail_rdr_'):].split('_') assert proto in ('udp', 'tcp') host_port = int(host_port) jail_port = int(jail[key]) append_jail_line( translation_rules, jail, 'rdr pass on {ext_if} inet proto {proto} from any to ({ext_if}) port {host_port} -> {ip4} port {jail_port}', proto = proto, host_port = host_port, jail_port = jail_port, ) filter_rules.append( 'pass quick on {cif} from ({cif}) to ({cif}:network)'.format(cif = cif), # TODO: allow only the host to access the jails but not the jails between them? # (could be an option in `mjail init`) ) ruleset = translation_rules + filter_rules + [''] return '\n'.join(ruleset)
def jails_network4(): try: cloned_if_params = output('sysrc', '-n', 'ifconfig_%s' % cloned_if()) except CalledProcessError: raise NoIPv4JailNetwork else: gd = (re.match( r'^inet\s+(?P<inet>{ip_reg})\s+netmask\s+(?P<netmask>{ip_reg})'. format(ip_reg=_ip_reg), cloned_if_params).groupdict()) return IPv4Network((gd['inet'], gd['netmask']), strict=False)
def jails_network6(): try: cloned_if_params = output('sysrc', '-n', 'ifconfig_%s_ipv6' % cloned_if()) except CalledProcessError: raise NoIPv6JailNetwork else: gd = (re.match( r'^inet6\s+(?P<inet6>{ip6_reg})\s+prefixlen\s+(?P<prefixlen>\d+)'. format(ip6_reg=_ip6_reg), cloned_if_params).groupdict()) return IPv6Network(gd['inet6'] + '/' + gd['prefixlen'], strict=False)
def interface_ip4(): strg = output('sysrc', '-n', 'ifconfig_%s' % cloned_if()).strip() return re.match( '^inet\s(?P<ip4>{ip_reg})\s*(netmask {ip_reg})?$'.format(ip_reg = _ip_reg), strg ).groupdict()['ip4']
def interface_ip4(): strg = output('sysrc', '-n', 'ifconfig_%s' % cloned_if()).strip() return re.match( r'^inet\s(?P<ip4>{ip_reg})\s*(netmask {ip_reg})?$'.format( ip_reg=_ip_reg), strg).groupdict()['ip4']
def _anchor_conf(cls): ext_if = get_ext_if() filter_rules = [] translation_rules = [] jail_conf = get_jail_conf() jails = [ jail_block for name, jail_block in jail_conf.jails() if (jail_block.get('$mjail_managed') == 'yes' and ( jail_block.get('ip4.addr') or jail_block.get('ip6.addr'))) ] cif = cloned_if() ext_if_ip6s = external_interface_ip6s() def append_jail_line(rules, jail, *strgs, **formats): ips = { key: jail[jail_key] for key, jail_key in (('ip4', 'ip4.addr'), ('ip6', 'ip6.addr')) if jail_key in jail } for strg in strgs: rules.append( strg.format(ext_if=ext_if, cif=cif, **ips, **formats)) for jail in jails: if 'ip4.addr' in jail: append_jail_line( translation_rules, jail, 'nat on {ext_if} inet from {ip4} to any -> ({ext_if})') append_jail_line( filter_rules, jail, 'pass quick on {cif} inet proto udp from {ip4} to ({cif}) port 53', 'pass quick on {cif} inet proto tcp from {ip4} to ({cif}) port 53' ) if 'ip6.addr' in jail: try: ext_if_ip6 = ext_if_ip6s[0] except IndexError: raise Exception( "Couldn't find a global scope IPv6 address of the external interface" ) append_jail_line( translation_rules, jail, 'nat on {ext_if} inet6 from {ip6} to any -> %s' % ext_if_ip6) append_jail_line( filter_rules, jail, 'pass quick on {cif} inet6 proto udp from {ip6} to ({cif}) port 53', 'pass quick on {cif} inet6 proto tcp from {ip6} to ({cif}) port 53' ) for key in jail: if key.startswith('$mjail_rdr_'): proto, host_port = key[len('$mjail_rdr_'):].split('_') assert proto in ('udp', 'tcp') host_port = int(host_port) jail_port = int(jail[key]) if 'ip4.addr' in jail: append_jail_line( translation_rules, jail, 'rdr pass on {ext_if} inet proto {proto} from any to ({ext_if}) port {host_port} -> {ip4} port {jail_port}', proto=proto, host_port=host_port, jail_port=jail_port, ) if 'ip6.addr' in jail: if len(ext_if_ip6s) == 0: raise Exception( "Couldn't find a global scope IPv6 address of the external interface" ) if len(ext_if_ip6s) > 1: warnings.warn( "The external interface has many global scope IPv6 addresses. " "The port redirection from port {host_port} to jail {jail_name}:{jail_port} will only occur on " "the address {ext_if_ip6} of the external interface." .format(host_port=host_port, jail_name=jail.get( 'host.hostname', ''), jail_port=jail_port, ext_if_ip6=ext_if_ip6s[0])) append_jail_line( translation_rules, jail, ('rdr pass on {ext_if} inet6 proto {proto} from any to %s port {host_port} -> {ip6} port {jail_port}' % ext_if_ip6s[0]), proto=proto, host_port=host_port, jail_port=jail_port, ) filter_rules.append( 'pass quick on {cif} from ({cif}) to ({cif}:network)'.format( cif=cif), # TODO: allow only the host to access the jails but not the jails between them? # (could be an option in `mjail init`) ) ruleset = translation_rules + filter_rules + [''] return '\n'.join(ruleset)