예제 #1
0
    def delete(self):
        cmd('service', 'jail', 'stop', self.name)
        jail_conf = get_jail_conf()
        try:
            jail_block = jail_conf[self.name]
        except KeyError:
            pass
        else:
            for version in (4, 6):
                try:
                    ip = jail_block['ip%s.addr' % version]
                except KeyError:
                    pass
                else:
                    assert isinstance(
                        ip, str)  # list of ips not yet supported by mjail
                    line = '%s %s\n' % (ip, self.name)
                    lines = [
                        l for l in open('/etc/hosts').readlines() if l != line
                    ]
                    temp_etc_hosts = to_tempfile(''.join(lines))
                    shutil.move(temp_etc_hosts, '/etc/hosts')
            del jail_conf[self.name]
            jail_conf.write('/etc/jail.conf')

        if os.path.exists(self.directory):
            cmd('chflags', '-R', 'noschg', self.directory)
            cmd('rm', '-rf', self.directory)
        PFManager.refresh_anchor()
예제 #2
0
 def delete(self):
     cmd('service', 'jail', 'stop', self.name)
     jail_conf = get_jail_conf()
     try:
         jail_block = jail_conf[self.name]
     except KeyError:
         pass
     else:
         try:
             ip4 = jail_block['ip4.addr']
         except KeyError:
             pass
         else:
             assert isinstance(ip4, str) # list of ips not yet supported by mjail
             line = '%s %s\n' % (ip4, self.name)
             lines = [l for l in open('/etc/hosts').readlines() if l != line]
             temp_etc_hosts = to_tempfile(''.join(lines))
             shutil.move(temp_etc_hosts, '/etc/hosts')    
         del jail_conf[self.name]
         jail_conf.write('/etc/jail.conf')
         
     if os.path.exists(self.directory):
         cmd('chflags', '-R', 'noschg', self.directory)
         cmd('rm', '-rf', self.directory)
     PFManager.refresh_anchor()
예제 #3
0
 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')
예제 #4
0
    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')
예제 #5
0
 def rdr(self, proto, internet_facing_host_port, jail_port):
     assert proto in ('tcp', 'udp')
     jail_conf = get_jail_conf()
     jail_conf[self.name][
         '$mjail_rdr_%s_%s' % (proto, int(internet_facing_host_port))
     ] = str(int(jail_port))
     jail_conf.write('/etc/jail.conf')
     PFManager.refresh_anchor()
예제 #6
0
 def rdr(self, proto, internet_facing_host_port, jail_port):
     assert proto in ('tcp', 'udp')
     jail_conf = get_jail_conf()
     jail_conf[self.name]['$mjail_rdr_%s_%s' %
                          (proto, int(internet_facing_host_port))] = str(
                              int(jail_port))
     jail_conf.write('/etc/jail.conf')
     PFManager.refresh_anchor()
예제 #7
0
 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)
예제 #8
0
 def cancel_rdr(self, proto, internet_facing_host_port):
     assert proto in ('tcp', 'udp')
     jail_conf = get_jail_conf()
     for _, jail_block in jail_conf.jails():
         try:
             del jail_block['$mjail_rdr_%s_%s' % (proto, int(internet_facing_host_port))]
         except KeyError:
             pass
     jail_conf.write('/etc/jail.conf')
     PFManager.refresh_anchor()
예제 #9
0
 def cancel_rdr(self, proto, internet_facing_host_port):
     assert proto in ('tcp', 'udp')
     jail_conf = get_jail_conf()
     for _, jail_block in jail_conf.jails():
         try:
             del jail_block['$mjail_rdr_%s_%s' %
                            (proto, int(internet_facing_host_port))]
         except KeyError:
             pass
     jail_conf.write('/etc/jail.conf')
     PFManager.refresh_anchor()
예제 #10
0
def available_ip4():
    jails_net = jails_network4()
    taken_ip4s = set([jails_net.network_address + 1])
    jail_conf = get_jail_conf()
    for _, jail_block in jail_conf.jails():
        try:
            ip4 = IPv4Address(jail_block['ip4.addr'])
        except KeyError:
            continue
        else:
            taken_ip4s.add(ip4)
    for host in jails_net.hosts():
        if host not in taken_ip4s:
            return host
예제 #11
0
 def _resolv_conf(self):
     jail_block = get_jail_conf()[self.name]
     lines = []
     for key, get_network in (('ip4.addr', jails_network4),
                              ('ip6.addr', jails_network6)):
         if jail_block.get(key):
             try:
                 j_network = get_network()
             except NoJailNetwork:
                 pass
             else:
                 lines.append("nameserver %s\n" %
                              str(j_network.network_address + 1))
     return ''.join(lines)
예제 #12
0
def available_ip6():
    jails_net = jails_network6()
    taken_ip6s = set([jails_net.network_address + 1])
    jail_conf = get_jail_conf()
    for _, jail_block in jail_conf.jails():
        try:
            ip6 = IPv6Address(jail_block['ip6.addr'])
        except KeyError:
            continue
        else:
            taken_ip6s.add(ip6)
    for host in jails_net.hosts():
        if host not in taken_ip6s:
            return host
예제 #13
0
 def minor_upgrade(self, to_version, unattended=False):
     # this function would need to be tested
     freebsd_update_conf = to_tempfile(''.join(
         (re.sub(r'(?<=\b)kernel(?=\b)', '', line) if re.
          match(r'^Components\s', line) else line)
         for line in open('/etc/freebsd-update.conf').readlines()))
     try:
         jail_conf = get_jail_conf()
         currently_running = jail_conf[
             self.name]['$mjail_currently_running_release']
         to_version_major = to_version.split('.')[0]
         running_major = currently_running.split('.')[0]
         if to_version_major != running_major:
             raise Exception(
                 "Can't upgrade from %s to %s. Only minor version upgrade is supported at the moment."
                 % (running_major, to_version_major))
         env = os.environ.copy()
         if unattended:
             env['PAGER'] = 'cat'
         cmd('freebsd-update',
             '-b',
             self.directory,
             '-f',
             freebsd_update_conf,
             '-r',
             to_version,
             'upgrade',
             'install',
             '--currently-running',
             currently_running,
             env=env)
         for _ in range(2):
             cmd('freebsd-update',
                 '-b',
                 self.directory,
                 '-f',
                 freebsd_update_conf,
                 'install',
                 env=env)
         jail_conf[
             self.name]['$mjail_currently_running_release'] = to_version
         jail_conf.write('/etc/jail.conf')
     finally:
         os.remove(freebsd_update_conf)
예제 #14
0
 def minor_upgrade(self, to_version, unattended = False):
     # this function would need to be tested
     freebsd_update_conf = to_tempfile(
         ''.join(
             (re.sub(r'(?<=\b)kernel(?=\b)', '', line) if re.match(r'^Components\s', line) else line)
             for line in
             open('/etc/freebsd-update.conf').readlines()
         )
     )
     try:
         jail_conf = get_jail_conf()
         currently_running = jail_conf[self.name]['$mjail_currently_running_release']
         to_version_major = to_version.split('.')[0]
         running_major = currently_running.split('.')[0]
         if to_version_major != running_major:
             raise Exception(
                 "Can't upgrade from %s to %s. Only minor version upgrade is supported at the moment." % (
                     running_major, to_version_major
                 )
             )
         env = os.environ.copy()
         if unattended:
             env['PAGER'] = 'cat'
         cmd('freebsd-update',
             '-b', self.directory,
             '-f', freebsd_update_conf,
             '-r', to_version, 'upgrade', 'install', '--currently-running', currently_running,
             env = env
         )
         for _ in range(2):
             cmd('freebsd-update',
                 '-b', self.directory,
                 '-f', freebsd_update_conf,
                 'install',
                 env = env
             )
         jail_conf[self.name]['$mjail_currently_running_release'] = to_version
         jail_conf.write('/etc/jail.conf')
     finally:
         os.remove(freebsd_update_conf)
예제 #15
0
    def create(self):
        release = Release()
        if not release.built():
            release.build()

        if os.path.exists(self.directory):
            raise JailAlreadyExists(self.name)

        cmd('cp', '-R', '-v', release.directory, self.directory)

        jail_conf = get_jail_conf()

        if self.name in jail_conf:
            raise JailAlreadyExists(self.name)

        jail_conf[self.name] = jailconf.JailBlock([
            ('$mjail_managed', 'yes'),
            ('$mjail_currently_running_release', str(release)),
            ('host.hostname', self.name)
        ])

        jail_conf.write('/etc/jail.conf')
예제 #16
0
 def create(self):
     release = Release()
     if not release.built():
         release.build()
     
     if os.path.exists(self.directory):
         raise JailAlreadyExists(self.name)
         
     cmd('cp', '-R', '-v', release.directory, self.directory)
     with open(os.path.join(self.directory, 'etc', 'resolv.conf'), "w") as fp:
         fp.write("nameserver %s\n" % str(jails_network4().network_address + 1))
     
     jail_conf = get_jail_conf()
     
     if self.name in jail_conf:
         raise JailAlreadyExists(self.name)
         
     jail_conf[self.name] = jailconf.JailBlock([
         ('$mjail_managed', 'yes'),
         ('$mjail_currently_running_release', str(release)),
         ('host.hostname', self.name)
     ])
     
     jail_conf.write('/etc/jail.conf')
예제 #17
0
    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)