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
  • 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.3)
  • 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 264 Nov 15, 2022
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 264 Nov 15, 2022
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 12.1k Nov 23, 2022
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 487 Nov 22, 2022
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.6k Nov 22, 2022
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 991 Nov 22, 2022
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 445 Oct 22, 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 346 Nov 13, 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 Nov 19, 2022
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.7k Nov 19, 2022