예제 #1
0
def lisp_itr_kernel_filter(sources, dyn_eids):
    if (os.getenv("LISP_NO_IPTABLES") != None):
        lisp.lprint("User selected to suppress installing iptables rules")
        return
    #endif
    
    os.system("sudo iptables -t raw -N lisp")
    os.system("sudo iptables -t raw -A PREROUTING -j lisp")
    os.system("sudo ip6tables -t raw -N lisp")
    os.system("sudo ip6tables -t raw -A PREROUTING -j lisp")

    #
    # Have kernel process packets for local addresses when sourced from site
    # EIDs. We do not want the lisp-itr process to process such packets. 
    # We want the kernel to deliver packets to and from local applications. 
    # And we want the kernel to forward decapsulated packets out interfaces 
    # leading the EIDs.
    #
    add = "sudo ip{}tables -t raw -A lisp -j ACCEPT -d {}"
    addr_set = ["127.0.0.1", "::1", "224.0.0.0/4 -p igmp", "ff00::/8",
        "fe80::/16"]
    addr_set += sources + lisp.lisp_get_all_addresses()
    for addr in addr_set:
        if (lisp.lisp_is_mac_string(addr)): continue
        six = "" if addr.find(":") == -1 else "6"
        os.system(add.format(six, addr))
    #endfor

    #
    # When source and destination addresses are EIDs for this LISP site,
    # we want the kernel to do local routing. But as a PITR, we don't want
    # the kernel to route everything (EID-prefix 0.0.0.0/0) or we can't have
    # this process encapsulate for any source address to a destination EID.
    #
    if (lisp.lisp_pitr == False):
        add = "sudo ip{}tables -t raw -A lisp -j ACCEPT -s {} -d {}"
        check = "sudo ip{}tables -t raw -C lisp -j ACCEPT -s {} -d {}"
        for source in sources:
            if (lisp.lisp_is_mac_string(source)): continue
            if (source in dyn_eids): continue
            six = "" if source.find(":") == -1 else "6"
            for s in sources:
                if (lisp.lisp_is_mac_string(s)): continue
                if (s in dyn_eids): continue
                if (s.find(".") != -1 and source.find(".") == -1): continue
                if (s.find(":") != -1 and source.find(":") == -1): continue
                if (commands.getoutput(check.format(six, source, s)) == ""):
                    continue
                #endif
                os.system(add.format(six, source, s))
            #endfor
        #endfor
    #endif

    #
    # Now put in drop rules for each "lisp database-mapping" EID-prefix.
    #
    drop = "sudo ip{}tables -t raw -A lisp -j DROP -s {}"
    for source in sources:
        if (lisp.lisp_is_mac_string(source)): continue
        six = "" if source.find(":") == -1 else "6"
        os.system(drop.format(six, source))
    #endif

    #
    # Print out rules we just configured.
    #
    rules = commands.getoutput("sudo iptables -t raw -S lisp").split("\n")
    rules += commands.getoutput("sudo ip6tables -t raw -S lisp").split("\n")
    lisp.lprint("Using kernel filters: {}".format(rules))

    #
    # Check if we need to put in a iptables rule workaround for the virtio TCP
    # checksum corruption problem for KVM guest OSes. Check environmnt 
    # variable LISP_VIRTIO_BUG.
    #
    # Note a debian host system that runs docker will need the following
    # command so ip6tables works inside of the docker container:
    #
    #   sudo modprobe ip6table_filter
    #
    if (os.getenv("LISP_VIRTIO_BUG") != None):
        c = ("sudo iptables -A POSTROUTING -t mangle -p tcp -j " + \
            "CHECKSUM --checksum-fill; ")
        c += ("sudo iptables -A POSTROUTING -t mangle -p udp -j " + \
            "CHECKSUM --checksum-fill; ")
        c += ("sudo ip6tables -A POSTROUTING -t mangle -p tcp -j " + \
            "CHECKSUM --checksum-fill; ")
        c += ("sudo ip6tables -A POSTROUTING -t mangle -p udp -j " + \
            "CHECKSUM --checksum-fill")
        os.system(c)
        virtio = lisp.bold("virtio", False)
        lisp.lprint("{} bug workaround, configure '{}'".format(virtio, c))
    #endif
    return
예제 #2
0
def lisp_itr_build_pcap_filter(sources, dyn_eids, l2_overlay, pitr):
    if (l2_overlay):
        pfilter = "ether[6:4] >= 0 and ether[10:2] >= 0"
        lisp.lprint("Using pcap filter: '{}'".format(pfilter))
        return(pfilter)
    #endif

    ether_pfilter = "(not ether proto 0x806)"
    probe_pfilter = " or (udp src port 4342 and ip[28] == 0x28)"
    decent_pfilter = \
        " or (ip[16] >= 224 and ip[16] < 240 and (ip[28] & 0xf0) == 0x30)"

    src_pfilter = ""
    dst_pfilter = ""
    for source in sources:
        insert_source = source
        if (lisp.lisp_is_mac_string(source)):
            insert_source = source.split("/")[0]
            insert_source = insert_source.replace("-", "")
            mac_str = []
            for i in range(0, 12, 2): mac_str.append(insert_source[i:i+2])
            insert_source = "ether host " + ":".join(mac_str)
        #endif

        src_pfilter += "{}".format(insert_source)
        if (source not in dyn_eids): dst_pfilter += "{}".format(insert_source)
        if (sources[-1] == source): break
        src_pfilter += " or "
        if (source not in dyn_eids): dst_pfilter += " or "
    #endfor
    if (dst_pfilter[-4::] == " or "): dst_pfilter = dst_pfilter[0:-4]

    #
    # If "lisp-nat = yes" is configured, then we are a PETR and we need
    # to accept packets for local EIDs (assigned to loopback interfaces).
    # So allow the first one to be accepted.
    #
    lisp_nat = commands.getoutput("egrep 'lisp-nat = yes' ./lisp.config")
    lisp_nat = (lisp_nat != "" and lisp_nat[0] == " ")
    loopback = lisp.lisp_get_loopback_address() if (lisp_nat) else None

    addr_pfilter = ""
    addresses = lisp.lisp_get_all_addresses()
    for addr in addresses:
        if (addr == loopback): continue
        addr_pfilter += "{}".format(addr)
        if (addresses[-1] == addr): break
        addr_pfilter += " or "
    #endif

    if (src_pfilter != ""):
        src_pfilter = " and (src net {})".format(src_pfilter)
    #endif
    if (dst_pfilter != ""):
        dst_pfilter = " and not (dst net {})".format(dst_pfilter)
    #endif
    if (addr_pfilter != ""):
        addr_pfilter = " and not (dst host {})".format(addr_pfilter)
    #endif

    #
    # A PITR wants to see packets from anywhere so it can encap to possible
    # LISP sites. But we want the kernel to route and consume for RLOCs for
    # this system.
    #
    if (pitr):
        dst_pfilter = ""
        addr_pfilter = addr_pfilter.replace("dst ", "")
    #endif

    #
    # Concatenate all the filters.
    #
    pfilter = ether_pfilter + src_pfilter + dst_pfilter + addr_pfilter
    pfilter += probe_pfilter
    pfilter += decent_pfilter

    lisp.lprint("Using pcap filter: '{}'".format(pfilter))
    return(pfilter)