A library for working with IP addresses and networks in Go

Overview

IPLib

Documentation CircleCI Go Report Card Coverage Status

I really enjoy Python's ipaddress library and Ruby's ipaddr, I think you can write a lot of neat software if some of the little problems around manipulating IP addresses and netblocks are taken care of for you, so I set out to write something like them for my language of choice, Go. This is what I've come up with.

IPLib is a hopefully useful, aspirationally full-featured library built around and on top of the address primitives found in the net package, it seeks to make them more accessible and easier to manipulate.

It includes:

net.IP tools

Some simple tools for performing common tasks against IP objects:

  • Compare two addresses
  • Get the delta between two addresses
  • Sort
  • Decrement or increment addresses
  • Print v4 as a hexadecimal string
  • Print v6 in fully expanded form
  • Convert between net.IP, integer and hexadecimal
  • Get the version of a v4 address or force a IPv4-mapped IPv6address to be a v4 address
iplib.IPNet

An enhancement of net.IPNet providing features such as:

  • Retrieve the wildcard mask
  • Get the network, broadcast, first and last usable addresses
  • Increment or decrement an address within the boundaries of a netblock
  • Enumerate all or part of a netblock to []net.IP
  • Allocate subnets and supernets

Sub-modules

Installing

go get -u github.com/c-robinson/iplib

Using IPLib

There are a series of functions for working with v4 or v6 net.IP objects:

package main

import (
	"fmt"
	"net"
	"sort"
	
	"github.com/c-robinson/iplib"
)


func main() {
	ipa := net.ParseIP("192.168.1.1")
	ipb := iplib.IncrementIPBy(ipa, 15)      // ipb is 192.168.1.16
	ipc := iplib.NextIP(ipa)                 // ipc is 192.168.1.2

	fmt.Println(iplib.CompareIPs(ipa, ipb))  // -1
    
	fmt.Println(iplib.DeltaIP(ipa, ipb))     // 15
    
	fmt.Println(iplib.IPToHexString(ipc))    // "c0a80102"

	iplist := []net.IP{ ipb, ipc, ipa }
	sort.Sort(iplib.ByIP(iplist))            // []net.IP{ipa, ipc, ipb}

	fmt.Println(iplib.IP4ToUint32(ipa))      // 3232235777
	fmt.Println(iplib.IPToBinaryString(ipa))  // 11000000.10101000.00000001.00000001
	ipd := iplib.Uint32ToIP4(iplib.IP4ToUint32(ipa)+20) // ipd is 192.168.1.21
	fmt.Println(iplib.IP4ToARPA(ipa))        // 1.1.168.192.in-addr.arpa
}

Addresses that require or return a count default to using uint32, which is sufficient for working with the entire IPv4 space. As a rule these functions are just lowest-common wrappers around IPv4- or IPv6-specific functions. The IPv6-specific variants use big.Int so they can access the entire v6 space:

package main

import (
	"fmt"
	"math/big"
	"net"
	"sort"
	
	"github.com/c-robinson/iplib"
)


func main() {
	ipa := net.ParseIP("2001:db8::1")
	ipb := iplib.IncrementIPBy(ipa, 15)      // ipb is 2001:db8::16
	ipc := iplib.NextIP(ipa)                 // ipc is 2001:db8::2

	fmt.Println(iplib.CompareIPs(ipa, ipb))  // -1
    
	fmt.Println(iplib.DeltaIP6(ipa, ipb))     // 15
    
	fmt.Println(iplib.ExpandIP6(ipa))        // "2001:0db8:0000:0000:0000:0000:0000:0001"
	fmt.Println(iplib.IPToBigint(ipa))       // 42540766411282592856903984951653826561 
	fmt.Println(iplib.IPToBinaryString(ipa)) // 00100000.00000001.00001101.10111000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001
    
	iplist := []net.IP{ ipb, ipc, ipa }
	sort.Sort(iplib.ByIP(iplist))            // []net.IP{ipa, ipc, ipb}

	m := big.NewInt(int64(iplib.MaxIPv4))    // e.g. 4,294,967,295
	ipd := iplib.IncrementIP6By(ipa, m)      // ipd is 2001:db8::1:0:0

	fmt.Println(iplib.DeltaIP6(ipb, ipd))    // 4294967274
	fmt.Println(iplib.IP6ToARPA(ipa))        // 1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa
}

To work with networks simply create an iplib.IPNet object:

package main

import (
	"fmt"
	"net"
	"sort"
	
	"github.com/c-robinson/iplib"
)

func main() {
	// this calls net.ParseCIDR() under the hood, but returns an iplib.Net object
	_, ipna, err := iplib.ParseCIDR("192.168.1.0/22")
	if err != nil {
		// this will be an error from the net package 
	}
	
	// NewNet() wants a net.IP and is waaaaaaaaaaaaaaaaay faster
	ipb := net.ParseIP("192.168.2.0")
	ipnb := iplib.NewNet(ipb, 22)
    
	// ...works for IPv6 too
	ipc := net.ParseIP("2001:db8::1")
	ipnc := iplib.NewNet(ipc, 64)

	fmt.Println(ipna.Count())                  // 1022 -- good enough for ipv4, but...
    
	fmt.Println(ipnc.Count())                  // 4294967295 -- ...sigh
	fmt.Println(ipnc.Count6())                 // 18446744073709551616 -- yay Count6() !

	fmt.Println(iplib.CompareNets(ipna, ipnb)) // -1

	ipnlist := []iplib.Net{ipnb, ipna, ipnc}
	sort.Sort(iplib.ByNet(ipnlist))            // []iplib.Net{ ipna, ipnb, ipnc } 
    
	elist := ipna.Enumerate(0, 0)
	fmt.Println(len(elist))                    // 1022
    
	fmt.Println(ipna.ContainsNet(ipnb))        // true
    
	fmt.Println(ipna.NetworkAddress())         // 192.168.1.0
	fmt.Println(ipna.FirstAddress())           // 192.168.1.1
	fmt.Println(ipna.LastAddress())            // 192.168.3.254
	fmt.Println(ipna.BroadcastAddress())       // 192.168.3.255
    
	fmt.Println(ipnc.NetworkAddress())         // 2001:db8::1 -- meaningless in IPv6
	fmt.Println(ipnc.FirstAddress())           // 2001:db8::1
	fmt.Println(ipnc.LastAddress())            // 2001:db8::ffff:ffff:ffff:ffff
	fmt.Println(ipnc.BroadcastAddress())       // 2001:db8::ffff:ffff:ffff:ffff
    
	ipa1 := net.ParseIP("2001:db8::2")
	ipa1, err = ipna.PreviousIP(ipa1)         //  net.IP{2001:db8::1}, nil
	ipa1, err = ipna.PreviousIP(ipa1)         //  net.IP{}, ErrAddressAtEndOfRange
}

iplib.IPNet objects can be used to generate subnets and supernets:

package main

import (
	"fmt"
	
	"github.com/c-robinson/iplib"
)

func main() {
    _, ipna, _ := iplib.ParseCIDR("192.168.4.0/22")
    fmt.Println(ipna.Subnet(24))   // []iplib.Net{ 192.168.4.0/24, 192.168.5.0/24, 
                                   //              192.168.6.0/24, 192.168.7.0/24 }
    ipnb, err := ipna.Supernet(21) // 192.168.0.0/21
    
    ipnc := ipna.PreviousNet(21)   // 192.168.0.0/21
    
    ipnd := ipna.NextNet(21)       // 192.168.8.0/21
}
Comments
  • NextNet seems to return the wrong value

    NextNet seems to return the wrong value

    See this example:

    package main
    
    import (
    	"fmt"
    
    	"github.com/c-robinson/iplib"
    )
    
    func GetNextSubnet(lastCIDR string, nextSize int) {
    	lastNet := iplib.Net4FromStr(lastCIDR)
    
    	if nextSize == 0 {
    		nextSize, _ = lastNet.Mask().Size()
    	}
    	nextNet := lastNet.NextNet(nextSize)
    	fmt.Printf("Next net: %s\n", nextNet)
    }
    
    func main() {
    	GetNextSubnet("10.80.6.0/24", 18)
    }
    

    Outputs:

    Next net: 10.80.0.0/18
    

    Am I doing something wrong?

    If I use the same subnet size, I get an expected result

    GetNextSubnet("10.80.6.0/24", 0) // 0 default to the same size
    

    output:

    Next net: 10.80.7.0/24
    

    and with:

    GetNextSubnet("10.80.6.0/24", 22)
    

    it goes backwards?

    Next net: 10.80.4.0/22
    
    bug 
    opened by luisdavim 2
  • test suite issue on 32-bit archs: cannot use MaxIPv4 (untyped int constant 4294967295) as int value in argument to t.Errorf (overflows)

    test suite issue on 32-bit archs: cannot use MaxIPv4 (untyped int constant 4294967295) as int value in argument to t.Errorf (overflows)

    Hi,

    I'm packaging your software for Debian (as a build-dependency for https://www.crowdsec.net/) and I'm seeing the following test failure on 32-bit archs (e.g. armel, armhf, i386 as seen on https://ci.debian.net/packages/g/golang-github-c-robinson-iplib/):

       dh_auto_test -O--builddirectory=_build -O--buildsystem=golang
    	cd _build && go test -vet=off -v -p 32 github.com/c-robinson/iplib github.com/c-robinson/iplib/iana github.com/c-robinson/iplib/iid
    # github.com/c-robinson/iplib [github.com/c-robinson/iplib.test]
    src/github.com/c-robinson/iplib/iplib_test.go:362:30: cannot use MaxIPv4 (untyped int constant 4294967295) as int value in argument to t.Errorf (overflows)
    FAIL	github.com/c-robinson/iplib [build failed]
    

    It can be trivially reproduced in an i386 chroot on an amd64 machine.

    Casting the constant explicitly to uint in that error message does the trick, but maybe it should or could have been declared a uint32 in the first place? That being said, I don't know anything about Go, so I'll just mention the patch I'm considering applying to iplib_test.go in the Debian package until I've gotten some feedback here:

    -               t.Errorf("want %d got %d", MaxIPv4, i)
    +               t.Errorf("want %d got %d", uint(MaxIPv4), i)
    
    opened by CyrilBrulebois 1
  • Integer overflow on 32bit targets

    Integer overflow on 32bit targets

    This line causes an integer overflow when compiling for arm.

    https://github.com/c-robinson/iplib/blob/d4ce4cb249581363ae573157898db9f904c971fa/net6.go#L337

    The solution would be to use uint32 instead of int for the datatype.

    The error message is: vendor/github.com/c-robinson/iplib/net6.go:337:21: constant 4294967295 overflows int

    opened by 0xd61 1
  • Incorrect Example Using iplib.Net4

    Incorrect Example Using iplib.Net4

    Hi,

    I found incorrect dos in readme file related to using iplib.Net4. In this line:

    n := NewNet4(net.ParseIP("192.168.0.0"), 16)

    it should be:

    n := iplib.NewNet4(net.ParseIP("192.168.0.0"), 16)

    and in this one:

    fmt.Println(n.Network()) // 192.168.0.0

    it should be:

    fmt.Println(n.IP()) // 192.168.0.0

    opened by ikandars 1
  • Many, many changes

    Many, many changes

    • iplib.Net is now an interface
    • the original iplib.Net is now iplib.Net4
    • new v6-centric iplib.Net6
    • introducing HostMask for v6 networks, which is like a netmask except it masks bits from the right of the address, excluding them from methods like NextIP, PreviousIP, Enumerate, etc
    • Enumerate now parallelized
    • updated README
    • updated documentation
    • now includes example-tests
    • much fuller test coverage
    opened by c-robinson 0
  • Fix two iid issues

    Fix two iid issues

    • MakeEUI64Addr() requires a net.HardwareAddr as input and it was modifying that variable in-place before using the result. This modified it for the caller as well

    • not strictly a bug but GenerateRFC7217Addr() in the iid package used 'iid' as a variable, which seemed dangerous or at least inadvisable. This has been changed

    opened by c-robinson 0
  • Iid

    Iid

    New iid submodule for creating and verifying IPv6 Interface Identifiers

    • make Modified EUI64 addresses
    • make "semantically opaque" addresses
    • check for collisions with IANA reserved IIDs
    • change make iana/README and iid/README look similar
    • small improvement in iplib test coverage
    • remove completed items from TODO
    opened by c-robinson 0
Releases(v1.0.6)
  • v1.0.6(Jan 2, 2023)

    https://github.com/c-robinson/iplib/compare/v1.0.5...v1.0.6

    • exported previously internal function CopyIP() which will create a copy of an IP address
    • Net4 and Net6 now have RandomIP() functions that will return a random address within the given netblock. They both use crypto/rand because that package works gracefully with *big.Int
    Source code(tar.gz)
    Source code(zip)
  • v1.0.5(Dec 31, 2022)

    https://github.com/c-robinson/iplib/compare/v1.0.4...v1.0.5

    • fix IPv4 NextNext returning the wrong value if the supplied netmask is lower than the current one, by @luisdavim
    Source code(tar.gz)
    Source code(zip)
  • v1.0.4(Nov 28, 2022)

    https://github.com/c-robinson/iplib/compare/v1.0.3...v1.0.4

    • fix an integer overflow on 32bit CPU's caused by MaxIPv4 being an int instead of uint32 found by @CyrilBrulebois
    Source code(tar.gz)
    Source code(zip)
  • v1.0.3(Nov 2, 2021)

    https://github.com/c-robinson/iplib/compare/v1.0.2...v1.0.3

    • fix an integer overflow on 32bit CPU's caused by using int, discovered and remediated by @0xd61
    • fix two typos in the README found by @ikanders

    Thanks to both for the discovery, and thanks @0xd61 for the fix!

    Source code(tar.gz)
    Source code(zip)
  • v1.0.2(Sep 25, 2021)

  • v1.0.1(Sep 5, 2021)

    https://github.com/c-robinson/iplib/compare/v1.0.0...v1.0.1

    Small documentation fix, plus avoid problems caused by a poorly-thought-out git force push.

    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Sep 5, 2021)

    https://github.com/c-robinson/iplib/compare/v0.3.1...v1.0.0

    Many, many changes

    • iplib.Net is now an interface
    • the original iplib.Net is now iplib.Net4
    • new v6-centric iplib.Net6
    • introducing HostMask for v6 networks, which is like a netmask except it masks bits from the right of the address, excluding them from methods like NextIP, PreviousIP, Enumerate, etc
    • Enumerate now parallelized
    • updated README
    • updated documentation
    • now includes example-tests
    • much fuller test coverage
    Source code(tar.gz)
    Source code(zip)
  • v0.3.1(Apr 16, 2020)

  • v0.3.0(Jun 16, 2019)

    https://github.com/c-robinson/iplib/compare/v0.2.0...v0.3.0

    • add IID submodule for generating IPv6 Interface Identifiers
    • small bugfixes and corrections
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(May 24, 2019)

    https://github.com/c-robinson/iplib/compare/v0.1.0...v0.2.0

    • add iana submodule for reporting on reserved IP address space
    • first pass at subnet and supernet handling
    • conversions to inaddr-arpa and binary string representations
    • go module support
    • small bugfixes and corrections
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(May 9, 2019)

Owner
Chad Robinson
Chad Robinson
Given a list of domains, you resolve them and get the IP addresses.

resolveDomains Given a list of domains, you resolve them and get the IP addresses. Installation If you want to make modifications locally and compile

Josué Encinar 33 Oct 19, 2022
A little tool to test IP addresses quickly against a geolocation and a reputation API

iptester A little tool to test IP addresses quickly against a geolocation and a

Axel Vanzaghi 2 May 19, 2022
oniongrok forwards ports on the local host to remote Onion addresses as Tor hidden services and vice-versa

oniongrok Onion addresses for anything. oniongrok forwards ports on the local host to remote Onion addresses as Tor hidden services and vice-versa. Wh

Casey Marshall 270 Jan 1, 2023
Vanitytorgen - Vanity Tor keys/onion addresses generator

Vanity Tor keys/onion addresses generator Assumptions You know what you are doing. You know where to copy the output files. You know how to set up a H

kexkey 2 May 12, 2022
Onion addresses for anything.

onionpipe Onion addresses for anything. onionpipe forwards ports on the local host to remote Onion addresses as Tor hidden services and vice-versa. Wh

Casey Marshall 270 Jan 1, 2023
The Swiss Army knife for 802.11, BLE and Ethernet networks reconnaissance and MITM attacks.

bettercap is a powerful, easily extensible and portable framework written in Go which aims to offer to security researchers, red teamers and reverse e

bettercap 13.3k Jan 3, 2023
webrpc is a schema-driven approach to writing backend services for modern Web apps and networks

webrpc is a schema-driven approach to writing backend servers for the Web. Write your server's api interface in a schema format of RIDL or JSON, and t

null 505 Jan 7, 2023
Netmaker is a tool for creating and managing virtual networks

Netmaker is a tool for creating and managing virtual networks. The goal is to make virtual/overlay/mesh networking easy for non-networking people. It should be like clicking a button. Netmaker consists of a server, an agent, and a UI.

GRAVITL 5.8k Jan 2, 2023
A flexible configuration manager for Wireguard networks

Drago A flexible configuration manager for WireGuard networks Drago is a flexible configuration manager for WireGuard networks which is designed to ma

Seashell 1k Jan 7, 2023
Transfer 10Gbps http traffic over 1Gbps networks :)

httpteleport Teleports 10Gbps http traffic over 1Gbps networks. Built on top of fastrpc. Use cases httpteleport may significantly reduce inter-server

Aliaksandr Valialkin 447 Nov 30, 2022
A Lightweight VPN Built on top of Libp2p for Truly Distributed Networks.

Hyprspace A Lightweight VPN Built on top of Libp2p for Truly Distributed Networks. demo.mp4 Table of Contents A Bit of Backstory Use Cases A Digital N

Hyprspace 375 Dec 29, 2022
Data source provider for Terraform that interacts with the Solana networks

Terraform Solana Provider Registry Page Requirements Terraform >= 0.13.x Go 1.16.x (for building from source) Example Usage Full provider documentatio

Matthew Callens 8 Aug 6, 2022
Mount your podman container into WireGuard networks on spawn

wg-pod A tool to quickly join your podman container/pod into a WireGuard network. Explanation wg-pod wires up the tools ip,route,wg and podman. It cre

Maximilian Ehlers 13 Aug 14, 2022
Attach services to specified networks automatically

Docker swarm network attacher Description docker-swarm-network-attacher aims to solve the problem of sharing a network between unrelated services. Wit

Bruno Cascio 1 Nov 11, 2021
A memory-safe SSH server, focused on listening only on VPN networks such as Tailscale

Features Is tested to work with SCP Integrates well with systemd Quickstart Download binary for your architecture. We only support Linux. If you don't

function61.com 2 Jun 10, 2022
Overlay networks based on WebRTC.

weron Overlay networks based on WebRTC. ⚠️ weron has not yet been audited! While we try to make weron as secure as possible, it has not yet undergone

Felicitas Pojtinger 1.2k Jan 4, 2023
gh is GitHub on the command line. It brings pull requests, issues, and other GitHub concepts to the terminal next to where you are already working with git and your code

gh is GitHub on the command line. It brings pull requests, issues, and other GitHub concepts to the terminal next to where you are already working with git and your code

frenchy77 0 Jan 24, 2022
Go-wd - Get the same working directory path at 'go run' and after 'go build'

go-wd Get the same working directory path at 'go run' and after 'go build' Usage

kota oue 0 Jan 30, 2022
A new way of working with Protocol Buffers.

Buf All documentation is hosted at https://buf.build. Please head over there for more details. Goal Buf’s long-term goal is to enable schema-driven de

null 5.9k Jan 1, 2023