Skip to main content

Calculating 32 bit port masks through Python

Recently I had to work with openvswitch to apply drop some VIP traffic on some particular IPs. The problem was that those particular IPs had port ranges and the job was to only block those particular IP addresses with a specific port range.
Openvswitch does not allows to specify port ranges like numbers, so if i were to add a rule for port range e.g 7 to 14 I cannot specify it like 7 - 14. Instead, I must specify the first number and wildcard the port numbers until the least significant 1 of the number changes to 0.

For example:

Number            Binary           Number of trailing 0s            Covered Range               Port Mask
     7                    0111                              0                                   only 7                             f
     8                    1000                              3                                    8-11                              c
    12                   1100                              2                                  12-13                              e
    14                   1110                              1                                   only 14                           f

Exaplanation:
We want range 7-14.. In case of 8 there are 3 trailing zeros. If we wildcard all three zeros, the range will reach 15 but we want to limit it to 14 so we limit it to 2 zeros and then adjust remaining numbers in the next range.

Number              1***
9               :          1001
10             :          1010
11             :          1011
12             :          1100
13             :          1101
14             :          1110
15             :          1111

Python Code for calculating 32 bit Port Masks
def dec2bin(val):
    if val is None:
        return False
    if int(val) > 65535:
        return False 
    return '{0:016b}'.format(val)
  
def getMask(bits):
    return {
    '0': "0xffff",
    '1': "0xfffe",
    '2': "0xfffc",
    '3': "0xfff8",
    '4': "0xfff0",
    '5': "0xffe0",
    '6': "0xffc0",
    '7': "0xff80",
    '8': "0xff00",
    '9': "0xfe00",
    '10': "0xfc00",
    '11': "0xf800",
    '12': "0xf000",
    '13': "0xe000",
    '14': "0xc000",
    '15': "0x8000"
    }[str(bits)]

def binLower(binary,bits):
    outBin = binary[0:16-bits]
    for i in range(0,bits):
        outBin += "0"
    return int(outBin,2)
 
def binHigher(binary, bits):
    outBin = binary[0:16-bits]
    for i in range(0,bits):
        outBin += "1"
    return int(outBin,2)

def testMasks(binary, start, end):
    if binary is None:
        return None
    for mask in range(0,17):
        maskStart = binLower(binary, mask)
        maskEnd = binHigher(binary, mask)
        if maskStart < start or maskEnd > end:
            return mask-1
    return mask


def get_port_mask(range_start, range_end):
    container = []
    mask_range = []
    if range_end < range_start:
        raise:
        print "First port value must be lower than the second"
        return None
    if range_start <=0 or range_start > 65535:
        raise:
        print "Port end : ", range_start , "is out of range. Valid range: 1-65535"
        return None 
    if range_end <=0 or range_end > 65535:
        raise:
        print "Port end : ", range_end , "is out of range. Valid range: 1-65535"
        return None
    processing = True
    while processing:
        binary = []
        binary_start = dec2bin(range_start)
        binary_lastOne = str(binary_start).rfind("1")+1
        binary_bitsToChange = 16 - binary_lastOne
        mask = testMasks(binary_start, range_start, range_end)
        if mask is None:
            return None
        maskStart = binLower(binary_start, mask)
        maskEnd = binHigher(binary_start, mask)
        container.append ((maskStart, getMask(mask)))
        range_port = range_start
        range_mask = getMask(mask)
        range_start = maskEnd + 1
        if range_start > range_end:
            processing = False
    return container

#Call this script like this:
print get_port_mask(7,14)

This code is inspired by a blog post jpwise. Original post can be found at:
http://blog.of.geek.nz/2012/07/22/u32-port-masks-calculator/

Comments

Popular posts from this blog

Running long background processes with double fork magic

Note: In the following post child process is the process created after first fork() and grand child process is the process created after second fork().    In one of my projects recently I had to run a shell command as a background process. The system was performance intensive, so I had to run a child process and continue execution on the parent process.            We were using Python on Ubuntu so initially it seemed very easy. I thought of just using the subprocess library available for python. I started a background process with subprocess.Popen() and not call a Popen.wait() for it because I had to run the shell command in the background. PROBLEM:            Initially I thought it worked but when I checked the process tree. I noticed that the child processes completed  and entered a < defunct> state were not releasing memory.  SOLUTION:           After ...

Hack The Box - Invite Challenge

Hack The Box is an online platform allowing you to test your penetration testing skills and exchange ideas and methodologies with other members of similar interests. It contains several challenges that are constantly updated. Some of them simulating real world scenarios and some of them leaning more towards a CTF style of challenge. As an individual, you can complete a simple challenge to prove your skills and then create an account, allowing you to connect to our private network (HTB Labs) where several machines await for you to hack them. By hacking machines you get points that help you advance in the Hall of Fame.            I have started to solve the challenges one by one.                                        Website Link: https://www.hackthebox.eu                   To take Challenges you must registe...