#Generating a regex based on a CIDR string

6 messages · Page 1 of 1 (latest)

brave niche
#

I want to generate regex strings to match IP-addresses in a given CIDR range.

Yes. I know this is stupid. Yes I know regex isn't ideal for handling IP-addresses. I'm just trying to work with what I've got. And to get all the eventual x/y-problem sorts of comments out of the way:
The place where I need to *use *these regexes does not support straight up IP-ranges, nor CIDR notation "natively" all I can work with is regex operating on strings. So I can't just use the "Contains" method from a [System.Net.IPNetwork] object, for example.

So given for example an input of 10.10.10.0/24, I would want function that outputs ^10\.10\.10\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$
and for a larger network such as a 123.123.120.0/20 a resulting regex would be something like ^123\.123\.(12[0-7])\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$

I've found various LLM tools to be fairly proficient at generating these for specific examples, but I'm getting stuck on writing a general purpose function to do it for any given (valid) CIDR input.

I "only" need it to work on IPv4 addresses, IPv6 is not relevant for my use case.
The intended use is to programmatically generate/convert these strings from arbitrary input, but more specifically the IP ranges published by Microsoft for various M365 services (https://learn.microsoft.com/en-us/microsoft-365/enterprise/microsoft-365-ip-web-service?view=o365-worldwide) which are published as for example just 52.100.0.0/14

Learn how to use the Microsoft 365 IP Address and URL web service to help you better identify and differentiate Microsoft 365 network traffic.

#

Basically, my idea is to have say a
function Convert-CidrToRegex([string]Cidr)

Such that
Convert-CidrToRegex -Cidr '10.10.10.0' would return ^10\.10\.10\.(25[0-5]|2[0-4]\d|1\d{2}|[1-9]?\d)$

snow yew
#

This problem is gonna be much easier to solve if you approach generating the regex for a single octet

#

That's only 8 possible options, try writing that out on a piece of paper or in a text editor:
0/8 -> 0
0/7 -> [0-1]
0/6 -> [0-3]
0/5 -> [0-7]
0/4 -> 1[0-5]|[0-9]
0/3 -> 3[0-1]|[1-2]?[0-9]
etc...

#

That's all you need - if you can generate all 8 permutations of the regex pattern for a single octect then you just need to repeat that for every octet masked

brave niche
#

Honestly, my brain is not doing brain's job. Ended up calling a web service for this. https://d-fault.nl/cidrtoregex

function Convert-CidrToRegex {
    # This function crafts a web request against the "interactive" web form at:
    # https://d-fault.nl/cidrtoregex
    param(
        [Parameter()]
        # Incomplete validation, but checks for four octets of 3 digits, and a possible /prefixLength
        [ValidatePattern('(?<baseAddress>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})(?<prefixLength>\/\d{1,2}){0,1}')]
        [string]
        $Cidr
    )

    $uri = 'https://d-fault.nl/cidrtoregex'
    # Make a request to initiate a session variable $RequestForm
    $_ = Invoke-WebRequest -Method GET -Uri $Uri -SessionVariable RequestForm
    # Get values from response used for form submission validation
    $responseInputFields = Invoke-WebRequest -Method Get -Uri $Uri -WebSession $RequestForm | 
        Select-Object -ExpandProperty inputfields | 
        Select-Object Name, Value

    # Craft a new form to submit, using the state and validation parameters from our previous request
    # 
    $NewRequestFields = @{
        '__EVENTTARGET' = ""
        '__EVENTARGUMENT' = ""
        '__VIEWSTATE' = ($responseInputFields.Where{$_.name -eq '__VIEWSTATE'}).Value
        '__VIEWSTATEGENERATOR' = ($responseInputFields.Where{$_.name -eq '__VIEWSTATEGENERATOR'}).Value
        '__EVENTVALIDATION' = ($responseInputFields.Where{$_.name -eq '__EVENTVALIDATION'}).Value
        'ctl00$MainContent$tbIP' = $Cidr
        'ctl00$MainContent$cbDuplicates' = 'on'
        'ctl00$MainContent$btnSumbit' = 'Convert'
    }

    $response = Invoke-WebRequest -Uri $Uri -WebSession $RequestForm -Method POST -Body $NewRequestFields -ContentType 'application/x-www-form-urlencoded; charset=utf-8' 
    # The output comes as 
    #<pre id="Output">^(40\.(?:9[2-3])\.(?:[0-9]|[1-9][0-9]|1(?:[0-9][0-9])|2(?:[0-4][0-9]|5[0-5]))\.(?:[0-9]|[1-9][0-9]|1(?:[0-9][0-9])|2(?:[0-4][0-9]|5[0-5])))$
    #</pre>

    # Regex match until end of regex $
    if ($response.Content -match '<pre id="Output">\^.+\$') {
        # Trim the HTML tag
        $regex = $matches[0] -replace '<pre id="Output">',''
    }
    return $regex
}```