diff --git a/config/peer.go b/config/peer.go
index 5bcfa49af2c68951ed5aecb12d2402e6284a42f2..5f151fe56c59ffa4ca410eb174745e755b15c09d 100644
--- a/config/peer.go
+++ b/config/peer.go
@@ -1,20 +1,21 @@
 package config
 
 import (
-	"net"
 	"time"
 
+	bnet "github.com/bio-routing/bio-rd/net"
 	"github.com/bio-routing/bio-rd/routingtable"
 	"github.com/bio-routing/bio-rd/routingtable/filter"
 )
 
+// Peer defines the configuration for a BGP session
 type Peer struct {
 	AdminEnabled      bool
 	ReconnectInterval time.Duration
 	KeepAlive         time.Duration
 	HoldTime          time.Duration
-	LocalAddress      net.IP
-	PeerAddress       net.IP
+	LocalAddress      bnet.IP
+	PeerAddress       bnet.IP
 	LocalAS           uint32
 	PeerAS            uint32
 	Passive           bool
diff --git a/main.go b/main.go
index 7c5bd7f1ba15450a5679688079307d3e0428e626..6b924601418c4335d5c7ccb7878eb4281d29710c 100644
--- a/main.go
+++ b/main.go
@@ -42,8 +42,8 @@ func main() {
 		AdminEnabled:      true,
 		LocalAS:           65200,
 		PeerAS:            65300,
-		PeerAddress:       net.IP([]byte{172, 17, 0, 3}),
-		LocalAddress:      net.IP([]byte{169, 254, 200, 0}),
+		PeerAddress:       bnet.IPv4FromOctets(172, 17, 0, 3),
+		LocalAddress:      bnet.IPv4FromOctets(169, 254, 200, 0),
 		ReconnectInterval: time.Second * 15,
 		HoldTime:          time.Second * 90,
 		KeepAlive:         time.Second * 30,
@@ -61,8 +61,8 @@ func main() {
 		AdminEnabled:      true,
 		LocalAS:           65200,
 		PeerAS:            65100,
-		PeerAddress:       net.IP([]byte{172, 17, 0, 2}),
-		LocalAddress:      net.IP([]byte{169, 254, 100, 1}),
+		PeerAddress:       bnet.IPv4FromOctets(172, 17, 0, 2),
+		LocalAddress:      bnet.IPv4FromOctets(169, 254, 100, 1),
 		ReconnectInterval: time.Second * 15,
 		HoldTime:          time.Second * 90,
 		KeepAlive:         time.Second * 30,
diff --git a/net/ip.go b/net/ip.go
index 143505ca49eb2d2868bc31ce4fee04b1a26ff3aa..46b7350dd8a10fe3fa2359073f2a6ce69874ea6b 100644
--- a/net/ip.go
+++ b/net/ip.go
@@ -2,6 +2,7 @@ package net
 
 import (
 	"fmt"
+	"net"
 )
 
 // IP represents an IPv4 or IPv6 address
@@ -45,9 +46,14 @@ func (ip *IP) ToUint32() uint32 {
 	return uint32(^uint64(0) >> 32 & ip.lower)
 }
 
+// Equal returns true if ip is equal to other
+func (ip IP) Equal(other IP) bool {
+	return ip == other
+}
+
 // Compare compares two IP addresses (returns 0 if equal, -1 if `ip` is smaller than `other`, 1 if `ip` is greater than `other`)
 func (ip IP) Compare(other IP) int {
-	if ip == other {
+	if ip.Equal(other) {
 		return 0
 	}
 
@@ -133,3 +139,8 @@ func (ip IP) bytesIPv6() []byte {
 		byte(ip.lower & 0x00000000000000FF),
 	}
 }
+
+// ToNetIP converts the IP address in a `net.IP`
+func (ip IP) ToNetIP() net.IP {
+	return net.IP(ip.Bytes())
+}
diff --git a/net/ip_test.go b/net/ip_test.go
index c6358d069b287bc539aab07fb837772ff95787c2..a10019322f390dab4890ffe2c3f4eafbd0ade8fb 100644
--- a/net/ip_test.go
+++ b/net/ip_test.go
@@ -2,6 +2,7 @@ package net
 
 import (
 	"math"
+	"net"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -254,3 +255,36 @@ func TestIPv6FromBlocks(t *testing.T) {
 		})
 	}
 }
+
+func TestToNetIP(t *testing.T) {
+	tests := []struct {
+		name     string
+		ip       IP
+		expected net.IP
+	}{
+		{
+			name:     "IPv4",
+			ip:       IPv4FromOctets(192, 168, 1, 1),
+			expected: net.IP{192, 168, 1, 1},
+		},
+		{
+			name: "IPv6",
+			ip: IPv6FromBlocks(
+				0x2001,
+				0x678,
+				0x1e0,
+				0x1234,
+				0x5678,
+				0xdead,
+				0xbeef,
+				0xcafe),
+			expected: net.IP{32, 1, 6, 120, 1, 224, 18, 52, 86, 120, 222, 173, 190, 239, 202, 254},
+		},
+	}
+
+	for _, test := range tests {
+		t.Run(test.name, func(t *testing.T) {
+			assert.Equal(t, test.expected, test.ip.ToNetIP())
+		})
+	}
+}
diff --git a/protocols/bgp/server/fsm.go b/protocols/bgp/server/fsm.go
index e85bda8cc21d6c47ac2c300639177aab8623859f..991f1b60853631a7b88d7fbb38c0e81ff551cc6e 100644
--- a/protocols/bgp/server/fsm.go
+++ b/protocols/bgp/server/fsm.go
@@ -170,7 +170,7 @@ func (fsm *FSM) tcpConnector() error {
 	for {
 		select {
 		case <-fsm.initiateCon:
-			c, err := net.DialTCP("tcp", &net.TCPAddr{IP: fsm.local}, &net.TCPAddr{IP: fsm.peer.addr, Port: BGPPORT})
+			c, err := net.DialTCP("tcp", &net.TCPAddr{IP: fsm.local}, &net.TCPAddr{IP: fsm.peer.addr.ToNetIP(), Port: BGPPORT})
 			if err != nil {
 				select {
 				case fsm.conErrCh <- err:
diff --git a/protocols/bgp/server/fsm_established.go b/protocols/bgp/server/fsm_established.go
index feaf1ee14badba4dae6ff8648a9308380c7db92a..40694d339c2b7b263b2c8b5ce8496fb5106a6bd4 100644
--- a/protocols/bgp/server/fsm_established.go
+++ b/protocols/bgp/server/fsm_established.go
@@ -73,7 +73,7 @@ func (s *establishedState) init() error {
 
 	n := &routingtable.Neighbor{
 		Type:              route.BGPPathType,
-		Address:           bnet.IPv4(bnet.IPv4ToUint32(s.fsm.peer.addr)),
+		Address:           s.fsm.peer.addr,
 		IBGP:              s.fsm.peer.localASN == s.fsm.peer.peerASN,
 		LocalASN:          s.fsm.peer.localASN,
 		RouteServerClient: s.fsm.peer.routeServerClient,
@@ -219,7 +219,7 @@ func (s *establishedState) updates(u *packet.BGPUpdate) {
 		path := &route.Path{
 			Type: route.BGPPathType,
 			BGPPath: &route.BGPPath{
-				Source: bnet.IPv4(bnet.IPv4ToUint32(s.fsm.peer.addr)),
+				Source: s.fsm.peer.addr,
 				EBGP:   s.fsm.peer.localASN != s.fsm.peer.peerASN,
 			},
 		}
diff --git a/protocols/bgp/server/fsm_test.go b/protocols/bgp/server/fsm_test.go
index 9cff29b3706dc30d11a1017a7d963d30bafcb1f2..2af938822e25b265831033c1b74fd690eef4e90d 100644
--- a/protocols/bgp/server/fsm_test.go
+++ b/protocols/bgp/server/fsm_test.go
@@ -1,7 +1,6 @@
 package server
 
 import (
-	"net"
 	"sync"
 	"testing"
 	"time"
@@ -10,12 +9,14 @@ import (
 	"github.com/bio-routing/bio-rd/routingtable/filter"
 	"github.com/bio-routing/bio-rd/routingtable/locRIB"
 	"github.com/stretchr/testify/assert"
+
+	bnet "github.com/bio-routing/bio-rd/net"
 )
 
 // TestFSM100Updates emulates receiving 100 BGP updates and withdraws. Checks route counts.
 func TestFSM100Updates(t *testing.T) {
 	fsmA := newFSM2(&peer{
-		addr:         net.ParseIP("169.254.100.100"),
+		addr:         bnet.IPv4FromOctets(169, 254, 100, 100),
 		rib:          locRIB.New(),
 		importFilter: filter.NewAcceptAllFilter(),
 		exportFilter: filter.NewAcceptAllFilter(),
diff --git a/protocols/bgp/server/peer.go b/protocols/bgp/server/peer.go
index 125393fb8fbfbfb5ed4bb626a5bc0aa352094d82..2772903061d6180c6d49ff48c70e3f96af4dfc33 100644
--- a/protocols/bgp/server/peer.go
+++ b/protocols/bgp/server/peer.go
@@ -1,11 +1,11 @@
 package server
 
 import (
-	"net"
 	"sync"
 	"time"
 
 	"github.com/bio-routing/bio-rd/config"
+	bnet "github.com/bio-routing/bio-rd/net"
 	"github.com/bio-routing/bio-rd/protocols/bgp/packet"
 	"github.com/bio-routing/bio-rd/routingtable"
 	"github.com/bio-routing/bio-rd/routingtable/filter"
@@ -13,14 +13,14 @@ import (
 )
 
 type PeerInfo struct {
-	PeerAddr net.IP
+	PeerAddr bnet.IP
 	PeerASN  uint32
 	LocalASN uint32
 }
 
 type peer struct {
 	server   *bgpServer
-	addr     net.IP
+	addr     bnet.IP
 	peerASN  uint32
 	localASN uint32
 
@@ -184,7 +184,7 @@ func filterOrDefault(f *filter.Filter) *filter.Filter {
 }
 
 // GetAddr returns the IP address of the peer
-func (p *peer) GetAddr() net.IP {
+func (p *peer) GetAddr() bnet.IP {
 	return p.addr
 }
 
diff --git a/protocols/bgp/server/server_test.go b/protocols/bgp/server/server_test.go
index baf30a19344cb12c284ec22eb364809d7dc4cd72..fffe879ce078deaa77a6a795d357f64ef74e3796 100644
--- a/protocols/bgp/server/server_test.go
+++ b/protocols/bgp/server/server_test.go
@@ -1,7 +1,6 @@
 package server
 
 import (
-	"net"
 	"testing"
 	"time"
 
@@ -9,6 +8,8 @@ import (
 	"github.com/bio-routing/bio-rd/routingtable"
 	"github.com/bio-routing/bio-rd/routingtable/filter"
 	"github.com/bio-routing/bio-rd/routingtable/locRIB"
+
+	bnet "github.com/bio-routing/bio-rd/net"
 )
 
 func TestBgpServerPeerSnapshot(t *testing.T) {
@@ -30,8 +31,8 @@ func TestBgpServerPeerSnapshot(t *testing.T) {
 	pc := config.Peer{
 		AdminEnabled:      true,
 		PeerAS:            65300,
-		PeerAddress:       net.IP([]byte{169, 254, 200, 1}),
-		LocalAddress:      net.IP([]byte{169, 254, 200, 0}),
+		PeerAddress:       bnet.IPv4FromOctets(169, 254, 200, 1),
+		LocalAddress:      bnet.IPv4FromOctets(169, 254, 200, 0),
 		ReconnectInterval: time.Second * 15,
 		HoldTime:          time.Second * 90,
 		KeepAlive:         time.Second * 30,
@@ -56,7 +57,7 @@ func TestBgpServerPeerSnapshot(t *testing.T) {
 		break
 	}
 
-	if want, got := net.ParseIP("169.254.200.1"), peer.PeerAddr; !want.Equal(got) {
+	if want, got := bnet.IPv4FromOctets(169, 254, 200, 1), peer.PeerAddr; !want.Equal(got) {
 		t.Errorf("PeerAddr: got %v, want %v", got, want)
 	}
 	if want, got := uint32(65300), peer.PeerASN; want != got {