How do the rest of you test Public vs Private IP addresses?

Everything else that doesn't fall into one of the other PB categories.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

How do the rest of you test Public vs Private IP addresses?

Post by SFSxOI »

This is a quickly put together utility thing to test for public vs private IP addresses I needed to come up with in a hurry earlier today for a temporary use:

Code: Select all

; private IPv4 IP ranges
; 10.0.0.0 - 10.255.255.255 Class A
; 172.16.0.0 - 172.31.255.255 Class B
; 192.168.0.0 - 192.168.255.255 Class C

; IPv6 private local prefixs are 
; fe80: And FC00::/7

Procedure.s TestForPrivatePublicIP(ip_in$)
  Protected ipmid.l, priv10.l, priv172.l, priv192.l, privLnkLoc.l, ip$, loopip$ 

ip$ = ip_in$

If FindString(ip$, "10.", 1) <> 0 And Left(ip$,2) = "10"
  priv10 = #True
EndIf

If FindString(ip$, "172.", 1) <> 0 And Left(ip$,3) = "172"
  For ipmid = 16 To 31
    loopip$ = "." + Str(ipmid) + "."
    If Mid(ip$, 4, 4) = loopip$
      priv172 = #True
    EndIf
  Next
EndIf

If FindString(ip$, "192.", 1) <> 0 And Left(ip$,3) = "192" And Mid(ip$, 4, 5) = ".168."
  priv192 = #True
EndIf

; ipv6 test for private local - per RFC 4193 - http://tools.ietf.org/html/rfc4193
If (FindString(ip$, "fe80:", 1) <> 0 Or FindString(ip$, "FC00::/7", 1) <> 0) And (Left(ip$, 5) = "fe80:" Or Left(ip$, 8) = "FC00::/7")
  privLnkLoc = #True
EndIf

Debug priv10
Debug priv172
Debug priv192
Debug privLnkLoc

If priv10 = #True Or priv172 = #True Or priv192 = #True Or privLnkLoc = #True
  ProcedureReturn "This is a Private IP address" ;#True
Else
  ProcedureReturn "This is a Public IP address" ;#False
EndIf

EndProcedure


;Debug TestForPrivatePublicIP("fe80::c56f:23df:e8fe:626a%15") ; ipv6
Debug TestForPrivatePublicIP("192.168.255.255") ; ipv4
Just wondering how others are testing programatically for public vs private IP addresses?
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
User avatar
Michael Vogel
Addict
Addict
Posts: 2807
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: How do the rest of you test Public vs Private IP address

Post by Michael Vogel »

I've no idea why you need to check for private/public addresses, but (at least IP4) addresses could be tested simply by using boolean logic, here's an example to check for the available 16 private class B networks (the IPString function has been used for better readability)...

Code: Select all


IP.s="172.31.32.33"

IP4=MakeIPAddress(Val(StringField(IP,1,".")),Val(StringField(IP,2,".")),Val(StringField(IP,3,".")),Val(StringField(IP,4,".")))

If IPString(IP4 & $00000F0FF)="172.16.0.0"
	Debug "Private"
EndIf
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: How do the rest of you test Public vs Private IP address

Post by SFSxOI »

Michael Vogel wrote:I've no idea why you need to check for private/public addresses...
Thanks for your post Michael

Because the capability is a requirement for detection of malformed, corrupted, rouge, or unauthorized addresses in analyzing and profiling networks under certain types of attacks. It will actually be more than just public vs private, thats just a small part of the beginning.

For example, this is something from a log of a previous incarnation of the detection module, where some activity of malware was detected for a workstation in a network when it started changing IP address entries for the network card, didn't get much further than that though. It forced things to a default condition to kill off the network monitoring of the system via its IPv6 remote sniffer monitoring so the foreign country bound outgoing packets activity from the system would not trigger an alarm or logging other than a loss of comm with the workstation:

Code: Select all

Intel(R) Gigabit CT Desktop Adapter Prefix Address (IPv6) > fe80::%15 
Intel(R) Gigabit CT Desktop Adapter Prefix Address (IPv6) > fe80::c56e:22df:e9fe:626a%15 (This is a Private IPv6 address) WARNING !!! Does not match records - changed on 9/1/2011 at 00:03:46 hours via non-admin methods - should be Public Address.
Intel(R) Gigabit CT Desktop Adapter Prefix Address (IPv6) > ff00::%15 (Multicast IPv6 - routing related.)
Intel(R) Gigabit CT Desktop Adapter Prefix Address (IPv4) > xx.xx.xxx.x(This is a Public or other IPv4 Address assignment)
Intel(R) Gigabit CT Desktop Adapter Prefix Address (IPv4) > xx.xx.xxx.x(This is a Public or other IPv4 Address assignment)
Intel(R) Gigabit CT Desktop Adapter Prefix Address (IPv4) > xx.xx.xxx.x(This is a Public or other IPv4 Address assignment)
Intel(R) Gigabit CT Desktop Adapter Prefix Address (IPv4) > 224.0.0.0 (Multicast Base address (reserved) - Local Network Control Block)
Intel(R) Gigabit CT Desktop Adapter Prefix Address (IPv4) > 255.255.255.255 (This is a Zero Network IP Address)
(NOTE: the xx's are mine to not expose IP addresses)
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
User avatar
Joakim Christiansen
Addict
Addict
Posts: 2452
Joined: Wed Dec 22, 2004 4:12 pm
Location: Norway
Contact:

Re: How do the rest of you test Public vs Private IP address

Post by Joakim Christiansen »

Not really helping here, but couldn't this:

Code: Select all

If FindString(ip$, "10.", 1) <> 0 And Left(ip$,2) = "10"
  priv10 = #True
EndIf
be written like this?:

Code: Select all

If Left(ip$,3) = "10."
  priv10 = #True
EndIf
:mrgreen:
I like logic, hence I dislike humans but love computers.
User avatar
Michael Vogel
Addict
Addict
Posts: 2807
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: How do the rest of you test Public vs Private IP address

Post by Michael Vogel »

I am not sure, if strings, like "010.001.002.003" or "10 . 1 . 2 . 3" could also appear, that's why I would convert IP4 addresses to a long integer, that makes all further checks easier (if you take care where that the first byte of the string will be the lowest byte in the long) and faster...
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: How do the rest of you test Public vs Private IP address

Post by Demivec »

Here's your original code using a slightly different method (just for variety).

Code: Select all

; private IPv4 IP ranges
; 10.0.0.0 - 10.255.255.255 Class A
; 172.16.0.0 - 172.31.255.255 Class B
; 192.168.0.0 - 192.168.255.255 Class C

; IPv6 private local prefixs are 
; fe80: And FC00::/7

Procedure.s TestForPrivatePublicIP(ip_in$)
  Protected ipmid.l, priv10.l, priv172.l, priv192.l, privLnkLoc.l, ip$, loopip$ 

  ip$ = ip_in$

  Select Val(Left(ip$, 3))
    Case 10
      priv10 = #True
    Case 172
      ipmid = Val(Mid(ip$, 4, 4))
      If ipmid >= 16 And ipmid <= 31
        priv172 = #True
      EndIf 
    Case 192
      If Mid(ip$, 4, 5) = ".168."
        priv192 = #True
      EndIf 
    Case 0
      ; ipv6 test for private local - per RFC 4193 - http://tools.ietf.org/html/rfc4193
      If LCase(Left(ip$, 5)) = "fe80:" Or LCase(Left(ip$, 8)) = "fc00::/7"
        privLnkLoc = #True
      EndIf 
  EndSelect
    
  Debug priv10
  Debug priv172
  Debug priv192
  Debug privLnkLoc
  
  If priv10 = #True Or priv172 = #True Or priv192 = #True Or privLnkLoc = #True
    ProcedureReturn "This is a Private IP address" ;#True
  Else
    ProcedureReturn "This is a Public IP address" ;#False
  EndIf

EndProcedure


;Debug TestForPrivatePublicIP("fe80::c56f:23df:e8fe:626a%15") ; ipv6
Debug TestForPrivatePublicIP("192.168.255.255") ; ipv4
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: How do the rest of you test Public vs Private IP address

Post by SFSxOI »

Yes, Demivec, thats sort of what I am going with. Except that I will not use the LCase - because on current windows systems the system should always present an IPv6 address in all lower case in compliance with RFC specs if everything is working correctly, and if something comes back in upper case you know you either have a problem or something is not compliant which is something we want to know. If I used the LCase, if there was a problem or something was not compliant and it was returning upper case we would never see it because the LCase would have converted it to lower case thus making it look "normal" when in reality a problem could possibly exist.

Thanks for the input everyone. :)
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
User avatar
Demivec
Addict
Addict
Posts: 4270
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: How do the rest of you test Public vs Private IP address

Post by Demivec »

SFSxOI wrote:Yes, Demivec, thats sort of what I am going with. Except that I will not use the LCase - because on current windows systems the system should always present an IPv6 address in all lower case in compliance with RFC specs if everything is working correctly, and if something comes back in upper case you know you either have a problem or something is not compliant which is something we want to know. If I used the LCase, if there was a problem or something was not compliant and it was returning upper case we would never see it because the LCase would have converted it to lower case thus making it look "normal" when in reality a problem could possibly exist.
That's a good point on the LCase potentially hiding a problem. I had put it in because I noticed in your original code you used uppercase for one comparison ("FC00::/7")and lowercase for the other ("fe80:"). Was that a typo, should one of them be in uppercase?
User avatar
Michael Vogel
Addict
Addict
Posts: 2807
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: How do the rest of you test Public vs Private IP address

Post by Michael Vogel »

Haven't read the RFC 5952, and because it's not a standard, it is more important, how network companies are interpreting the paper (in this case section 4 or so) -- when I started with networking, I wondered how many products ignored the well defined output format for MAC addresses (01:02:03:04:05:06 or 01-02-03-04-05-06)...

...back to IPv6, I would be generous when checking the input string, or add a "repair filter" to convert typos to get perfect address strings.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Re: How do the rest of you test Public vs Private IP address

Post by SFSxOI »

Michael Vogel wrote:Haven't read the RFC 5952, and because it's not a standard, it is more important, how network companies are interpreting the paper (in this case section 4 or so) -- when I started with networking, I wondered how many products ignored the well defined output format for MAC addresses (01:02:03:04:05:06 or 01-02-03-04-05-06)...

...back to IPv6, I would be generous when checking the input string, or add a "repair filter" to convert typos to get perfect address strings.
Since this is intended for windows systems, we are monitoring via the RFC as MS interpets and designed the OS systems. Someone else is working on the modules for linux/unix flavors (which i'm happy for because not all of the linux flavors interpet the same way all the time, for example, some may return upper case in the IPv6 address and some lower case, at times), and the MAC versions (which I believe uses all lower case in its text representations also but i'm not up to date on the MAC systems).

The interpetation of the RFC by MS is not really their interpetation, they used RFC 5952, Section 4.3, which states that only lower case alphabetics must be used in IPv6 addresses - in text representations. RFC 5952 (a "recommendation", and was dated August 2010) specifies a set of rules for generating the preferred textual representation of an IPv6 address. The third sentence of RFC 5952's section 4 reads: "The recommendation in this section SHOULD be followed by systems when generating an address to be represented as text, but all implementations MUST accept and be able to handle any legitimate RFC4291 format." , "handling" and generating a textual representation are two different things and if you feed in uppercase it will "handle" it but when it gives a text representation it will give lower case for what we are monitoring and if the uppercase is there in what we monitor then we may have a problem. In RFC 5952, section 4.3, it reads:

"4.3. Lowercase

The characters "a", "b", "c", "d", "e", and "f" in an IPv6 address MUST be represented in lowercase."

it does say "MUST be" (its refering to the text representation). True, its a recommendation and there was errata for the RFC which made a case for using all uppercase but the eratta was not accepted and its unlikely it will be accepted.

I forget right now which one, but there is another RFC that states in a small blurp that only IPv6 addresses used in documentation or examples should use uppercase. Since windows systems give lowercase in its text representations of an IPv6 address, and some malware activity is known to alter the IP addresses or place such in tables and logs with uppercase in the address, if we find one in tables or logs or in monitoring parts of the system, with uppercase its a pretty good bet the windows system did not produce it.

My favorite so far is a certain IPv6 prefix of which we catch a lot. Another issue is rogue IPv6 Router Advertisements. IPv6 RA's are used to determine node configuration, rogue RAs can cause partial or complete failure of hosts on an IPv6 link or can be used for denial-of-service or man-in-the-middle attacks. But its not just malware that can create a rogue RA and most are caused, either intentionally or not, via user misconfiguration. Rogue RA's can also hijack a wireless system (on which Rogue RA's are more common), where a laptop has enabled the Windows Internet Connection Sharing (ICS) service, which can turn a host into a 6to4 gateway, its a useful feature until it runs when not intended and some malware attempt to start an IPv4 DHCPv4 server on the host via use of a rogue RA. Its also suprising to learn that a lot of malware that alters an IPv6 address will over use a certain letter or combination of letters in altering the address (which I will not disclose the letter, combination, frequency, or placement here). I just started on the part for detecting the rogue IPv6 RA's.

Thanks for your post Michael, you reminded me of something I need to do with this as well.
The advantage of a 64 bit operating system over a 32 bit operating system comes down to only being twice the headache.
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: How do the rest of you test Public vs Private IP address

Post by Keya »

IPv4
here is my version for private IPv4 addresses
I have a feeling it'd be better to use bitmasks (can probably halve the comparisons then?) but i think this is still a reasonably efficient method, and my googling for examples with bitmasks failed anyway!
[edit]ive included a procedure for building IP4 addresses but later discovered PB has its own MakeIPAddress() :)

Code: Select all

;Macro MAKE_IP4(a,b,c,d)
;  (((( (a << 8) | b) <<8) | c) <<8) | d
;EndMacro

Procedure.q MAKE_IP4(a,b,c,d)
  ProcedureReturn (((( (a << 8) | b) <<8) | c) <<8) | d
EndProcedure

Procedure.i IsPrivateIPv4(ip_addr.q) ;using quad to accomodate comparisons on unsigned dword
  Select ip_addr
    Case $0 To $00FFFFFF,        ;0.0.0.0 - 0.255.255.255        (16,777,216)
         $0A000000 To $0AFFFFFF, ;10.0.0.0 - 10.255.255.255      (16,777,216)
         $7F000000 To $7FFFFFFF, ;127.0.0.0 - 127.255.255.255    (16,777,216)
         $A9FE0000 To $A9FEFFFF, ;169.254.0.0 - 169.254.255.255  (65,536)
         $AC100000 To $AC1FFFFF, ;172.16.0.0 - 172.31.255.255    (1,048,576)
         $C0000000 To $C00000FF, ;192.0.0.0 - 192.0.0.255        (256)
         $C0000200 To $C00002FF, ;192.0.2.0 - 192.0.2.255        (256)
         $C0A80000 To $C0A8FFFF, ;192.168.0.0 - 192.168.255.255  (65,536)
         $C6120000 To $C613FFFF, ;198.18.0.0 - 198.19.255.255    (131,072)
         $C6336400 To $C63364FF, ;198.51.100.0 - 198.51.100.255  (256)
         $CB007100 To $CB0071FF: ;203.0.113.0 - 203.0.113.255    (256)    
      ProcedureReturn 1
  EndSelect
  ProcedureReturn 0
EndProcedure


Debug IsPrivateIPv4(MAKE_IP4(10,0,0,1))  ;priv
Debug IsPrivateIPv4(MAKE_IP4(127,0,0,1)) ;priv
Debug IsPrivateIPv4(MAKE_IP4(128,0,0,1)) ;pub
Debug IsPrivateIPv4(MAKE_IP4(200,0,0,1)) ;pub
hmm thats about 52 million valuable IP4 addresses reserved for private local use, who's having that big a LAN party!? apparently a single IPv4 address is worth about US$15 here in 2016, and thats when you buy in bulk!

Be aware that IP addresses from PB functions like GetClientIP() are stored in big-endian left-to-right format (127.0.0.1 = 7F 00 00 01), so we need to reverse that (ie. bswap) before treating them as a 32bit Unsigned Dword for comparisons like i did above. PB sadly doesnt support 32bit unsigned dword so we need to use Quad to accomodate that:

Code: Select all

Procedure.q BSWAPIP(IP.q)
  EnableASM
  Protected addr = @IP
  CompilerIf SizeOf(Integer)=8  ;x64
    mov rax, addr
    mov ecx, [rax]
    bswap ecx
    mov [rax], ecx
  CompilerElse   ;x86
    mov eax, addr
    mov ecx, [eax]
    bswap ecx
    mov [eax], ecx
  CompilerEndIf
  DisableASM
EndProcedure
Last edited by Keya on Thu Jun 09, 2016 6:00 am, edited 3 times in total.
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Re: How do the rest of you test Public vs Private IP address

Post by Keya »

IPv6
Here is my version for IPv6. My ISP doesnt support IPv6 so I can only test locally :( so i can't really test this! but it's detecting all my private addresses ok.

I'd very much appreciate it if some of you trendsetters with IPv6 access could test with Internet-based IPv6 addresses such as from ipv6.google.com etc, thanks! :)

Demo: Enumerate all local IPv6 addresses and check if they're private. The IPv6 address returned by PB functions (GetClientIP(), NextIPAddress() etc) simply return a buffer of 16 bytes - the 'raw' IPv6 address - so theyre nice and easy to read directly before calling FreeIP(IP) in situations where we don't want/need to convert it to a string.

Code: Select all

;https://en.wikipedia.org/wiki/Reserved_IP_addresses#IPv6

Structure IPv6addr
  StructureUnion
    octeta.a[16]
    octetw.u[8]
    octetq.q[2]
  EndStructureUnion
EndStructure

Procedure IsPrivateIPv6(*IP.IPv6addr)
  If *IP = 0: ProcedureReturn -1: EndIf  ;null ptr abort
  If *IP\octeta[0] = $FC              ;FC00-FDFF "Private network"
  ElseIf *IP\octeta[0] = $FD          ;FC00-FDFF "Private network"
  ElseIf *IP\octetw[0] => $80FE And   ;FE80-FEBF "Link"
         *IP\octetw[0] <= $BFFE       ;FE80-FEBF "Link"
  ElseIf *IP\octetw[0] = $0001        ;0100 "Discard prefix RFC 6666"
  ElseIf *IP\octetq[0] = $0           ;Loopback (::1) or unspecified address (::) etc
  Else: ProcedureReturn 0             ;Non-private (therefore assumed public)
  EndIf
  ProcedureReturn 1                   ;Confirmed private
EndProcedure

Procedure EnumIPv6IPs()
  If ExamineIPAddresses(#PB_Network_IPv6)
    Repeat
      IP = NextIPAddress()
      If IP      
        MessageRequester("Next IP", IPString(IP, #PB_Network_IPv6) + #CRLF$ + "Private=" + IsPrivateIPv6(IP))      
        FreeIP(IP)                                     
      EndIf
    Until IP = 0
  EndIf
EndProcedure

InitNetwork()
EnumIPv6IPs()
Post Reply