diff --git a/config.default.json b/config.default.json
index bf4fcd9ef7beed579ed7f18be8253e78391b3385..25816877fa7f7861cec47e6db5a2be922f4076e8 100644
--- a/config.default.json
+++ b/config.default.json
@@ -14,8 +14,7 @@
     "entryNodes": [
       "MRCJTGX9x+PPiT3um1DQSHXvALaUg/tCH/oQr6mliGo=@35.246.104.243:14626"
     ],
-    "port": 14626,
-    "version": 1
+    "port": 14626
   },
   "dashboard": {
     "bindAddress": "127.0.0.1:8081",
diff --git a/go.mod b/go.mod
index 0dbff93702cc3c219d93d38413c19ea26a9cf060..a838712d43511b98bdcd369ec46a791d14904901 100644
--- a/go.mod
+++ b/go.mod
@@ -10,7 +10,7 @@ require (
 	github.com/googollee/go-engine.io v1.4.3-0.20190924125625-798118fc0dd2
 	github.com/googollee/go-socket.io v1.4.3-0.20191204093753-683f8725b6d0
 	github.com/gorilla/websocket v1.4.1
-	github.com/iotaledger/hive.go v0.0.0-20200316213914-76b7a4169e64
+	github.com/iotaledger/hive.go v0.0.0-20200323150914-f38e680ea7d1
 	github.com/iotaledger/iota.go v1.0.0-beta.14
 	github.com/labstack/echo v3.3.10+incompatible
 	github.com/labstack/gommon v0.3.0 // indirect
@@ -21,7 +21,7 @@ require (
 	github.com/pkg/errors v0.9.1
 	github.com/spf13/pflag v1.0.5
 	github.com/spf13/viper v1.6.2
-	github.com/stretchr/testify v1.4.0
+	github.com/stretchr/testify v1.5.1
 	github.com/valyala/fasttemplate v1.1.0 // indirect
 	go.uber.org/atomic v1.6.0
 	go.uber.org/zap v1.14.0
@@ -29,3 +29,5 @@ require (
 	golang.org/x/net v0.0.0-20200301022130-244492dfa37a
 	gopkg.in/src-d/go-git.v4 v4.13.1
 )
+
+replace github.com/iotaledger/hive.go v0.0.0 => ../hive.go
diff --git a/go.sum b/go.sum
index 18faf70e16059b5918e94f6078f178f1d63feba0..9fca25e7e54c8f86f4d906784e0aa79f4f34d934 100644
--- a/go.sum
+++ b/go.sum
@@ -130,8 +130,10 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T
 github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/iotaledger/hive.go v0.0.0-20200316213914-76b7a4169e64 h1:O+1g39PWKzskXCViRD07ePv6183gDbH81XoShbPTzuc=
-github.com/iotaledger/hive.go v0.0.0-20200316213914-76b7a4169e64/go.mod h1:0LQvxKmfU4bcQcjYIAq3PRfsA5584U0AioAAas6/QU8=
+github.com/iotaledger/hive.go v0.0.0-20200319204115-e052cf07c81d h1:bwrSVMHIVROkg6wkdg2MmMRrzRwGORjNBl7LHJzp3+0=
+github.com/iotaledger/hive.go v0.0.0-20200319204115-e052cf07c81d/go.mod h1:EfH+ZcYGFJzzoFpO7NHGi2k7+Xc84ASyp1EwjhI3eJc=
+github.com/iotaledger/hive.go v0.0.0-20200323150914-f38e680ea7d1 h1:ActziRcYMPDnccHya7NKtwsPCIL5B9WcSE/g6ZFcAew=
+github.com/iotaledger/hive.go v0.0.0-20200323150914-f38e680ea7d1/go.mod h1:EfH+ZcYGFJzzoFpO7NHGi2k7+Xc84ASyp1EwjhI3eJc=
 github.com/iotaledger/iota.go v1.0.0-beta.9/go.mod h1:F6WBmYd98mVjAmmPVYhnxg8NNIWCjjH8VWT9qvv3Rc8=
 github.com/iotaledger/iota.go v1.0.0-beta.14 h1:Oeb28MfBuJEeXcGrLhTCJFtbsnc8y1u7xidsAmiOD5A=
 github.com/iotaledger/iota.go v1.0.0-beta.14/go.mod h1:F6WBmYd98mVjAmmPVYhnxg8NNIWCjjH8VWT9qvv3Rc8=
@@ -289,6 +291,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
diff --git a/packages/database/versioning.go b/packages/database/versioning.go
index a848eb0e508a7ecbf3b9c61773700fdfdaa79b1c..5150bc624dcd1bbdea419dffab416c7105fd562c 100644
--- a/packages/database/versioning.go
+++ b/packages/database/versioning.go
@@ -8,7 +8,7 @@ import (
 const (
 	// DBVersion defines the version of the database schema this version of GoShimmer supports.
 	// everytime there's a breaking change regarding the stored data, this version flag should be adjusted.
-	DBVersion = 1
+	DBVersion = 2
 )
 
 var (
diff --git a/packages/gossip/common.go b/packages/gossip/common.go
index 237e11ab3608c0d557ee7e84533e8ef4f21afea4..854d7214deccf4d4e64bd4df3e4d7c9fc4f481b3 100644
--- a/packages/gossip/common.go
+++ b/packages/gossip/common.go
@@ -1,6 +1,9 @@
 package gossip
 
 import (
+	"net"
+	"strconv"
+
 	"github.com/iotaledger/hive.go/autopeering/peer"
 	"github.com/iotaledger/hive.go/autopeering/peer/service"
 )
@@ -12,9 +15,9 @@ func IsSupported(p *peer.Peer) bool {
 
 // GetAddress returns the address of the gossip service.
 func GetAddress(p *peer.Peer) string {
-	gossip := p.Services().Get(service.GossipKey)
-	if gossip == nil {
-		panic("peer does not support gossip")
+	gossipEndpoint := p.Services().Get(service.GossipKey)
+	if gossipEndpoint == nil {
+		panic("peer does not support gossipEndpoint")
 	}
-	return gossip.String()
+	return net.JoinHostPort(p.IP().String(), strconv.Itoa(gossipEndpoint.Port()))
 }
diff --git a/packages/gossip/manager_test.go b/packages/gossip/manager_test.go
index f91adc10327492e87fcd33423c15653fa626a72c..220f55134afb7dffb6c5d7eff0a5ac800af5ccca 100644
--- a/packages/gossip/manager_test.go
+++ b/packages/gossip/manager_test.go
@@ -380,18 +380,17 @@ func newTestDB(t require.TestingT) *peer.DB {
 func newTestManager(t require.TestingT, name string) (*Manager, func(), *peer.Peer) {
 	l := log.Named(name)
 
-	services := service.New()
-	services.Update(service.PeeringKey, "peering", name)
-	local, err := peer.NewLocal(services, newTestDB(t))
-	require.NoError(t, err)
-
 	laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0")
 	require.NoError(t, err)
 	lis, err := net.ListenTCP("tcp", laddr)
 	require.NoError(t, err)
 
-	// enable TCP gossipping
-	require.NoError(t, local.UpdateService(service.GossipKey, lis.Addr().Network(), lis.Addr().String()))
+	services := service.New()
+	services.Update(service.PeeringKey, "peering", 0)
+	services.Update(service.GossipKey, lis.Addr().Network(), lis.Addr().(*net.TCPAddr).Port)
+
+	local, err := peer.NewLocal(lis.Addr().(*net.TCPAddr).IP, services, newTestDB(t))
+	require.NoError(t, err)
 
 	srv := server.ServeTCP(local, lis, l)
 
@@ -404,7 +403,7 @@ func newTestManager(t require.TestingT, name string) (*Manager, func(), *peer.Pe
 		srv.Close()
 		_ = lis.Close()
 	}
-	return mgr, detach, &local.Peer
+	return mgr, detach, local.Peer
 }
 
 func newEventMock(t mock.TestingT) (*eventMock, func()) {
diff --git a/packages/gossip/neighbor_test.go b/packages/gossip/neighbor_test.go
index 36c61534baf178c3fd637406302661e6b75687bd..2ec1a2be9349dae2367d831b4367ae58b1baec00 100644
--- a/packages/gossip/neighbor_test.go
+++ b/packages/gossip/neighbor_test.go
@@ -1,6 +1,7 @@
 package gossip
 
 import (
+	"crypto/ed25519"
 	"net"
 	"sync"
 	"sync/atomic"
@@ -118,15 +119,16 @@ func TestNeighborParallelWrite(t *testing.T) {
 }
 
 func newTestNeighbor(name string, conn net.Conn) *Neighbor {
-	return NewNeighbor(newTestPeer(name, conn.LocalAddr()), conn, log.Named(name))
+	return NewNeighbor(newTestPeer(name, conn), conn, log.Named(name))
 }
 
-func newTestPeer(name string, addr net.Addr) *peer.Peer {
+func newTestPeer(name string, conn net.Conn) *peer.Peer {
 	services := service.New()
-	services.Update(service.PeeringKey, addr.Network(), addr.String())
-	services.Update(service.GossipKey, addr.Network(), addr.String())
-
-	return peer.NewPeer([]byte(name), services)
+	services.Update(service.PeeringKey, conn.LocalAddr().Network(), 0)
+	services.Update(service.GossipKey, conn.LocalAddr().Network(), 0)
+	key := make([]byte, ed25519.PublicKeySize)
+	copy(key, name)
+	return peer.NewPeer(key, net.IPv4zero, services)
 }
 
 func newPipe() (net.Conn, net.Conn, func()) {
diff --git a/packages/gossip/server/handshake.go b/packages/gossip/server/handshake.go
index 719ff0dea33ce26994ba2bf83b4bea904a8ed356..86bef3f74ad82ab7aea532c1476661bf713ba4a1 100644
--- a/packages/gossip/server/handshake.go
+++ b/packages/gossip/server/handshake.go
@@ -50,13 +50,6 @@ func (t *TCP) validateHandshakeRequest(reqData []byte) bool {
 		)
 		return false
 	}
-	if m.GetTo() != t.publicAddr.String() {
-		t.log.Debugw("invalid handshake",
-			"to", m.GetTo(),
-			"want", t.publicAddr.String(),
-		)
-		return false
-	}
 	if isExpired(m.GetTimestamp()) {
 		t.log.Debugw("invalid handshake",
 			"timestamp", time.Unix(m.GetTimestamp(), 0),
diff --git a/packages/gossip/server/server.go b/packages/gossip/server/server.go
index 6fe98d5363f6eb4ea87e09c13fb54f8d9fc88b67..80a1d183b1258a7f1a28434790a0d13759b6300b 100644
--- a/packages/gossip/server/server.go
+++ b/packages/gossip/server/server.go
@@ -7,6 +7,7 @@ import (
 	"fmt"
 	"io"
 	"net"
+	"strconv"
 	"strings"
 	"sync"
 	"time"
@@ -46,10 +47,9 @@ var dialRetryPolicy = backoff.ConstantBackOff(500 * time.Millisecond).With(backo
 
 // TCP establishes verified incoming and outgoing TCP connections to other peers.
 type TCP struct {
-	local      *peer.Local
-	publicAddr net.Addr
-	listener   *net.TCPListener
-	log        *zap.SugaredLogger
+	local    *peer.Local
+	listener *net.TCPListener
+	log      *zap.SugaredLogger
 
 	addAcceptMatcher chan *acceptMatcher
 	acceptReceived   chan accept
@@ -81,16 +81,12 @@ type accept struct {
 func ServeTCP(local *peer.Local, listener *net.TCPListener, log *zap.SugaredLogger) *TCP {
 	t := &TCP{
 		local:            local,
-		publicAddr:       local.Services().Get(service.GossipKey),
 		listener:         listener,
 		log:              log,
 		addAcceptMatcher: make(chan *acceptMatcher),
 		acceptReceived:   make(chan accept),
 		closing:          make(chan struct{}),
 	}
-	if t.publicAddr == nil {
-		panic(ErrNoGossip)
-	}
 
 	t.log.Debugw("server started",
 		"network", listener.Addr().Network(),
@@ -123,21 +119,22 @@ func (t *TCP) LocalAddr() net.Addr {
 // DialPeer establishes a gossip connection to the given peer.
 // If the peer does not accept the connection or the handshake fails, an error is returned.
 func (t *TCP) DialPeer(p *peer.Peer) (net.Conn, error) {
-	gossipAddr := p.Services().Get(service.GossipKey)
-	if gossipAddr == nil {
+	gossipEndpoint := p.Services().Get(service.GossipKey)
+	if gossipEndpoint == nil {
 		return nil, ErrNoGossip
 	}
 
 	var conn net.Conn
 	if err := backoff.Retry(dialRetryPolicy, func() error {
 		var err error
-		conn, err = net.DialTimeout(gossipAddr.Network(), gossipAddr.String(), dialTimeout)
+		address := net.JoinHostPort(p.IP().String(), strconv.Itoa(gossipEndpoint.Port()))
+		conn, err = net.DialTimeout("tcp", address, dialTimeout)
 		if err != nil {
-			return fmt.Errorf("dial %s / %s failed: %w", gossipAddr.String(), p.ID(), err)
+			return fmt.Errorf("dial %s / %s failed: %w", address, p.ID(), err)
 		}
 
-		if err = t.doHandshake(p.PublicKey(), gossipAddr.String(), conn); err != nil {
-			return fmt.Errorf("handshake %s / %s failed: %w", gossipAddr.String(), p.ID(), err)
+		if err = t.doHandshake(p.PublicKey(), address, conn); err != nil {
+			return fmt.Errorf("handshake %s / %s failed: %w", address, p.ID(), err)
 		}
 		return nil
 	}); err != nil {
@@ -154,15 +151,15 @@ func (t *TCP) DialPeer(p *peer.Peer) (net.Conn, error) {
 // AcceptPeer awaits an incoming connection from the given peer.
 // If the peer does not establish the connection or the handshake fails, an error is returned.
 func (t *TCP) AcceptPeer(p *peer.Peer) (net.Conn, error) {
-	gossipAddr := p.Services().Get(service.GossipKey)
-	if gossipAddr == nil {
+	gossipEndpoint := p.Services().Get(service.GossipKey)
+	if gossipEndpoint == nil {
 		return nil, ErrNoGossip
 	}
 
 	// wait for the connection
 	connected := <-t.acceptPeer(p)
 	if connected.err != nil {
-		return nil, fmt.Errorf("accept %s / %s failed: %w", gossipAddr.String(), p.ID(), connected.err)
+		return nil, fmt.Errorf("accept %s / %s failed: %w", net.JoinHostPort(p.IP().String(), strconv.Itoa(gossipEndpoint.Port())), p.ID(), connected.err)
 	}
 
 	t.log.Debugw("incoming connection established",
diff --git a/packages/gossip/server/server_test.go b/packages/gossip/server/server_test.go
index 602968e3dda75974e86cf43c7964940f85d08ae2..983856704860aaa927a444461ada7838f09fc8da 100644
--- a/packages/gossip/server/server_test.go
+++ b/packages/gossip/server/server_test.go
@@ -19,7 +19,7 @@ const graceTime = 5 * time.Millisecond
 var log = logger.NewExampleLogger("server")
 
 func getPeer(t *TCP) *peer.Peer {
-	return &t.local.Peer
+	return t.local.Peer
 }
 
 func TestClose(t *testing.T) {
@@ -57,8 +57,8 @@ func TestUnansweredDial(t *testing.T) {
 
 	// create peer with invalid gossip address
 	services := getPeer(transA).Services().CreateRecord()
-	services.Update(service.GossipKey, "tcp", "localhost:0")
-	unreachablePeer := peer.NewPeer(getPeer(transA).PublicKey(), services)
+	services.Update(service.GossipKey, "tcp", 0)
+	unreachablePeer := peer.NewPeer(getPeer(transA).PublicKey(), net.ParseIP("127.0.0.1"), services)
 
 	_, err := transA.DialPeer(unreachablePeer)
 	assert.Error(t, err)
@@ -81,8 +81,8 @@ func TestNoHandshakeResponse(t *testing.T) {
 
 	// create peer for the listener
 	services := getPeer(transA).Services().CreateRecord()
-	services.Update(service.GossipKey, lis.Addr().Network(), lis.Addr().String())
-	p := peer.NewPeer(getPeer(transA).PublicKey(), services)
+	services.Update(service.GossipKey, lis.Addr().Network(), lis.Addr().(*net.TCPAddr).Port)
+	p := peer.NewPeer(getPeer(transA).PublicKey(), lis.Addr().(*net.TCPAddr).IP, services)
 
 	_, err = transA.DialPeer(p)
 	assert.Error(t, err)
@@ -174,18 +174,17 @@ func newTestDB(t require.TestingT) *peer.DB {
 func newTestServer(t require.TestingT, name string) (*TCP, func()) {
 	l := log.Named(name)
 
-	services := service.New()
-	services.Update(service.PeeringKey, "peering", name)
-	local, err := peer.NewLocal(services, newTestDB(t))
-	require.NoError(t, err)
-
 	laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0")
 	require.NoError(t, err)
 	lis, err := net.ListenTCP("tcp", laddr)
 	require.NoError(t, err)
 
-	// enable TCP gossipping
-	require.NoError(t, local.UpdateService(service.GossipKey, lis.Addr().Network(), lis.Addr().String()))
+	services := service.New()
+	services.Update(service.PeeringKey, "peering", 0)
+	services.Update(service.GossipKey, lis.Addr().Network(), lis.Addr().(*net.TCPAddr).Port)
+
+	local, err := peer.NewLocal(lis.Addr().(*net.TCPAddr).IP, services, newTestDB(t))
+	require.NoError(t, err)
 
 	srv := ServeTCP(local, lis, l)
 
diff --git a/plugins/autopeering/autopeering.go b/plugins/autopeering/autopeering.go
index 78392512d9f26c4282a339a1019eb16283ded86c..658c39be6c7063fcf39041ac4ce660bf5c2bb41b 100644
--- a/plugins/autopeering/autopeering.go
+++ b/plugins/autopeering/autopeering.go
@@ -4,21 +4,28 @@ import (
 	"encoding/base64"
 	"errors"
 	"fmt"
+	"hash/fnv"
 	"net"
+	"strconv"
 	"strings"
 
+	"github.com/iotaledger/goshimmer/plugins/autopeering/local"
+	"github.com/iotaledger/goshimmer/plugins/banner"
+	"github.com/iotaledger/goshimmer/plugins/config"
+	"github.com/iotaledger/goshimmer/plugins/gossip"
 	"github.com/iotaledger/hive.go/autopeering/discover"
 	"github.com/iotaledger/hive.go/autopeering/peer"
 	"github.com/iotaledger/hive.go/autopeering/peer/service"
 	"github.com/iotaledger/hive.go/autopeering/selection"
 	"github.com/iotaledger/hive.go/autopeering/server"
-	"github.com/iotaledger/hive.go/autopeering/transport"
 	"github.com/iotaledger/hive.go/logger"
 	"github.com/iotaledger/hive.go/node"
+)
 
-	"github.com/iotaledger/goshimmer/plugins/autopeering/local"
-	"github.com/iotaledger/goshimmer/plugins/config"
-	"github.com/iotaledger/goshimmer/plugins/gossip"
+// autopeering constants
+const (
+	ProtocolVersion = 0      // update on protocol changes
+	NetworkVersion  = "v0.2" // update on network changes
 )
 
 var (
@@ -27,11 +34,32 @@ var (
 	// Selection is the peer selection protocol.
 	Selection *selection.Protocol
 
-	ErrParsingMasterNode = errors.New("can't parse master node")
+	// ErrParsingMasterNode is returned for an invalid master node
+	ErrParsingMasterNode = errors.New("cannot parse master node")
+
+	// NetworkID specifies the autopeering network identifier
+	NetworkID = hash32([]byte(banner.AppVersion + NetworkVersion))
 
 	log *logger.Logger
 )
 
+func hash32(b []byte) uint32 {
+	hash := fnv.New32()
+	_, err := hash.Write(b)
+	if err != nil {
+		panic(err)
+	}
+	return hash.Sum32()
+}
+
+// GetBindAddress returns the string form of the autopeering bind address.
+func GetBindAddress() string {
+	peering := local.GetInstance().Services().Get(service.PeeringKey)
+	host := config.Node.GetString(local.CFG_BIND)
+	port := strconv.Itoa(peering.Port())
+	return net.JoinHostPort(host, port)
+}
+
 func configureAP() {
 	masterPeers, err := parseEntryNodes()
 	if err != nil {
@@ -39,13 +67,11 @@ func configureAP() {
 	}
 	log.Debugf("Master peers: %v", masterPeers)
 
-	Discovery = discover.New(local.GetInstance(),
+	Discovery = discover.New(local.GetInstance(), ProtocolVersion, NetworkID,
 		discover.Logger(log.Named("disc")),
-		discover.Version(config.Node.GetUint32(CFG_VERSION)),
 		discover.MasterPeers(masterPeers),
 	)
 
-	log.Infof("Protocol Version: %v", discover.VersionNum)
 	// enable peer selection only when gossip is enabled
 	if !node.IsSkipped(gossip.PLUGIN) {
 		Selection = selection.New(local.GetInstance(), Discovery,
@@ -58,57 +84,42 @@ func configureAP() {
 // isValidNeighbor checks whether a peer is a valid neighbor.
 func isValidNeighbor(p *peer.Peer) bool {
 	// gossip must be supported
-	gossipAddr := p.Services().Get(service.GossipKey)
-	if gossipAddr == nil {
+	gossipService := p.Services().Get(service.GossipKey)
+	if gossipService == nil {
 		return false
 	}
-	// the host for the gossip and peering service must be identical
-	gossipHost, _, err := net.SplitHostPort(gossipAddr.String())
-	if err != nil {
+	// gossip service must be valid
+	if gossipService.Network() != "tcp" || gossipService.Port() < 0 || gossipService.Port() > 65535 {
 		return false
 	}
-	peeringAddr := p.Services().Get(service.PeeringKey)
-	peeringHost, _, err := net.SplitHostPort(peeringAddr.String())
-	if err != nil {
-		return false
-	}
-	return gossipHost == peeringHost
+	return true
 }
 
 func start(shutdownSignal <-chan struct{}) {
 	defer log.Info("Stopping " + name + " ... done")
 
 	lPeer := local.GetInstance()
-	// use the port of the peering service
-	peeringAddr := lPeer.Services().Get(service.PeeringKey)
-	_, peeringPort, err := net.SplitHostPort(peeringAddr.String())
-	if err != nil {
-		panic(err)
-	}
+	peering := lPeer.Services().Get(service.PeeringKey)
+
 	// resolve the bind address
-	address := net.JoinHostPort(config.Node.GetString(local.CFG_BIND), peeringPort)
-	localAddr, err := net.ResolveUDPAddr(peeringAddr.Network(), address)
+	localAddr, err := net.ResolveUDPAddr(peering.Network(), GetBindAddress())
 	if err != nil {
 		log.Fatalf("Error resolving %s: %v", local.CFG_BIND, err)
 	}
 
-	conn, err := net.ListenUDP(peeringAddr.Network(), localAddr)
+	conn, err := net.ListenUDP(peering.Network(), localAddr)
 	if err != nil {
 		log.Fatalf("Error listening: %v", err)
 	}
 	defer conn.Close()
 
-	// use the UDP connection for transport
-	trans := transport.Conn(conn, func(network, address string) (net.Addr, error) { return net.ResolveUDPAddr(network, address) })
-	defer trans.Close()
-
 	handlers := []server.Handler{Discovery}
 	if Selection != nil {
 		handlers = append(handlers, Selection)
 	}
 
 	// start a server doing discovery and peering
-	srv := server.Serve(lPeer, trans, log.Named("srv"), handlers...)
+	srv := server.Serve(lPeer, conn, log.Named("srv"), handlers...)
 	defer srv.Close()
 
 	// start the discovery on that connection
@@ -121,7 +132,7 @@ func start(shutdownSignal <-chan struct{}) {
 		defer Selection.Close()
 	}
 
-	log.Infof("%s started: ID=%s Address=%s/%s", name, lPeer.ID(), peeringAddr.String(), peeringAddr.Network())
+	log.Infof("%s started: ID=%s Address=%s/%s", name, lPeer.ID(), localAddr.String(), localAddr.Network())
 
 	<-shutdownSignal
 
@@ -143,13 +154,17 @@ func parseEntryNodes() (result []*peer.Peer, err error) {
 		}
 		pubKey, err := base64.StdEncoding.DecodeString(parts[0])
 		if err != nil {
-			return nil, fmt.Errorf("%w: can't decode public key: %s", ErrParsingMasterNode, err)
+			return nil, fmt.Errorf("%w: invalid public key: %s", ErrParsingMasterNode, err)
+		}
+		addr, err := net.ResolveUDPAddr("udp", parts[1])
+		if err != nil {
+			return nil, fmt.Errorf("%w: host cannot be resolved: %s", ErrParsingMasterNode, err)
 		}
 
 		services := service.New()
-		services.Update(service.PeeringKey, "udp", parts[1])
+		services.Update(service.PeeringKey, addr.Network(), addr.Port)
 
-		result = append(result, peer.NewPeer(pubKey, services))
+		result = append(result, peer.NewPeer(pubKey, addr.IP, services))
 	}
 
 	return result, nil
diff --git a/plugins/autopeering/local/local.go b/plugins/autopeering/local/local.go
index 1586cbff8862e41177d918c4b18b6409800aada3..4a7c7e84515491ea2a071200aad6f1eaccc235cd 100644
--- a/plugins/autopeering/local/local.go
+++ b/plugins/autopeering/local/local.go
@@ -4,14 +4,12 @@ import (
 	"crypto/ed25519"
 	"encoding/base64"
 	"net"
-	"strconv"
 	"strings"
 	"sync"
 
 	"github.com/iotaledger/hive.go/autopeering/peer"
 	"github.com/iotaledger/hive.go/autopeering/peer/service"
 	"github.com/iotaledger/hive.go/logger"
-	"github.com/iotaledger/hive.go/netutil"
 
 	"github.com/iotaledger/goshimmer/packages/database"
 	"github.com/iotaledger/goshimmer/plugins/config"
@@ -25,30 +23,28 @@ var (
 func configureLocal() *peer.Local {
 	log := logger.NewLogger("Local")
 
-	var externalIP net.IP
+	var peeringIP net.IP
 	if str := config.Node.GetString(CFG_EXTERNAL); strings.ToLower(str) == "auto" {
-		log.Info("Querying external IP ...")
-		ip, err := netutil.GetPublicIP(false)
-		if err != nil {
-			log.Fatalf("Error querying external IP: %s", err)
-		}
-		log.Infof("External IP queried: address=%s", ip.String())
-		externalIP = ip
+		// let the autopeering discover the IP
+		peeringIP = net.IPv4zero
 	} else {
-		externalIP = net.ParseIP(str)
-		if externalIP == nil {
+		peeringIP = net.ParseIP(str)
+		if peeringIP == nil {
 			log.Fatalf("Invalid IP address (%s): %s", CFG_EXTERNAL, str)
 		}
-	}
-	if !externalIP.IsGlobalUnicast() {
-		log.Warnf("IP is not a global unicast address: %s", externalIP.String())
+		if !peeringIP.IsGlobalUnicast() {
+			log.Warnf("IP is not a global unicast address: %s", peeringIP.String())
+		}
 	}
 
-	peeringPort := strconv.Itoa(config.Node.GetInt(CFG_PORT))
+	peeringPort := config.Node.GetInt(CFG_PORT)
+	if 0 > peeringPort || peeringPort > 65535 {
+		log.Fatalf("Invalid port number (%s): %d", CFG_PORT, peeringPort)
+	}
 
 	// announce the peering service
 	services := service.New()
-	services.Update(service.PeeringKey, "udp", net.JoinHostPort(externalIP.String(), peeringPort))
+	services.Update(service.PeeringKey, "udp", peeringPort)
 
 	// set the private key from the seed provided in the config
 	var seed [][]byte
@@ -75,7 +71,7 @@ func configureLocal() *peer.Local {
 	// key, _ := peerDB.LocalPrivateKey()
 	// fmt.Println(base64.StdEncoding.EncodeToString(ed25519.PrivateKey(key).Seed()))
 
-	local, err := peer.NewLocal(services, peerDB, seed...)
+	local, err := peer.NewLocal(peeringIP, services, peerDB, seed...)
 	if err != nil {
 		log.Fatalf("Error creating local: %s", err)
 	}
diff --git a/plugins/autopeering/parameters.go b/plugins/autopeering/parameters.go
index bafa1e0b6220f66bec79f6cd30368b0163b6c32b..138b8d56e451c9024fd85c1b4296965337061c4d 100644
--- a/plugins/autopeering/parameters.go
+++ b/plugins/autopeering/parameters.go
@@ -6,10 +6,8 @@ import (
 
 const (
 	CFG_ENTRY_NODES = "autopeering.entryNodes"
-	CFG_VERSION     = "autopeering.version"
 )
 
 func init() {
 	flag.StringSlice(CFG_ENTRY_NODES, []string{"V8LYtWWcPYYDTTXLeIEFjJEuWlsjDiI0+Pq/Cx9ai6g=@116.202.49.178:14626"}, "list of trusted entry nodes for auto peering")
-	flag.Uint32(CFG_VERSION, 0, "Autopeering Protocol Version")
 }
diff --git a/plugins/gossip/gossip.go b/plugins/gossip/gossip.go
index c32d37d8ceb990965a4b78c7f7c902e7cbe11a38..d611032d64f0dc8890189f819f27cefb9ab0c330 100644
--- a/plugins/gossip/gossip.go
+++ b/plugins/gossip/gossip.go
@@ -7,6 +7,7 @@ import (
 
 	"github.com/iotaledger/hive.go/autopeering/peer/service"
 	"github.com/iotaledger/hive.go/logger"
+	"github.com/iotaledger/hive.go/netutil"
 
 	"github.com/iotaledger/goshimmer/packages/binary/tangle/model/message"
 	gp "github.com/iotaledger/goshimmer/packages/gossip"
@@ -25,19 +26,15 @@ var (
 func configureGossip() {
 	lPeer := local.GetInstance()
 
-	peeringAddr := lPeer.Services().Get(service.PeeringKey)
-	external, _, err := net.SplitHostPort(peeringAddr.String())
-	if err != nil {
-		panic(err)
+	// announce the gossip service
+	gossipPort := config.Node.GetInt(GOSSIP_PORT)
+	if !netutil.IsValidPort(gossipPort) {
+		log.Fatalf("Invalid port number (%s): %d", GOSSIP_PORT, gossipPort)
 	}
 
-	// announce the gossip service
-	gossipPort := strconv.Itoa(config.Node.GetInt(GOSSIP_PORT))
-	err = lPeer.UpdateService(service.GossipKey, "tcp", net.JoinHostPort(external, gossipPort))
-	if err != nil {
+	if err := lPeer.UpdateService(service.GossipKey, "tcp", gossipPort); err != nil {
 		log.Fatalf("could not update services: %s", err)
 	}
-
 	mgr = gp.NewManager(lPeer, getTransaction, log)
 }
 
@@ -45,20 +42,18 @@ func start(shutdownSignal <-chan struct{}) {
 	defer log.Info("Stopping " + name + " ... done")
 
 	lPeer := local.GetInstance()
+
 	// use the port of the gossip service
-	gossipAddr := lPeer.Services().Get(service.GossipKey)
-	_, gossipPort, err := net.SplitHostPort(gossipAddr.String())
-	if err != nil {
-		panic(err)
-	}
+	gossipEndpoint := lPeer.Services().Get(service.GossipKey)
+
 	// resolve the bind address
-	address := net.JoinHostPort(config.Node.GetString(local.CFG_BIND), gossipPort)
-	localAddr, err := net.ResolveTCPAddr(gossipAddr.Network(), address)
+	address := net.JoinHostPort(config.Node.GetString(local.CFG_BIND), strconv.Itoa(gossipEndpoint.Port()))
+	localAddr, err := net.ResolveTCPAddr(gossipEndpoint.Network(), address)
 	if err != nil {
 		log.Fatalf("Error resolving %s: %v", local.CFG_BIND, err)
 	}
 
-	listener, err := net.ListenTCP(gossipAddr.Network(), localAddr)
+	listener, err := net.ListenTCP(gossipEndpoint.Network(), localAddr)
 	if err != nil {
 		log.Fatalf("Error listening: %v", err)
 	}
@@ -70,7 +65,7 @@ func start(shutdownSignal <-chan struct{}) {
 	mgr.Start(srv)
 	defer mgr.Close()
 
-	log.Infof("%s started: Address=%s/%s", name, gossipAddr.String(), gossipAddr.Network())
+	log.Infof("%s started: Address=%s/%s", name, localAddr.String(), localAddr.Network())
 
 	<-shutdownSignal
 	log.Info("Stopping " + name + " ...")
diff --git a/plugins/portcheck/plugin.go b/plugins/portcheck/plugin.go
index 09f25947361b5145329dbe9f8087ea7a99e45481..202c8bb4593cd3f72fad996d5ed50f2959ae6c77 100644
--- a/plugins/portcheck/plugin.go
+++ b/plugins/portcheck/plugin.go
@@ -2,18 +2,14 @@ package portcheck
 
 import (
 	"net"
-	"sync"
 
-	"github.com/iotaledger/goshimmer/packages/gossip/server"
 	"github.com/iotaledger/goshimmer/plugins/autopeering"
 	"github.com/iotaledger/goshimmer/plugins/autopeering/local"
 	"github.com/iotaledger/goshimmer/plugins/banner"
-	"github.com/iotaledger/goshimmer/plugins/config"
-	"github.com/iotaledger/goshimmer/plugins/gossip"
-
+	"github.com/iotaledger/hive.go/autopeering/discover"
 	"github.com/iotaledger/hive.go/autopeering/peer/service"
+	"github.com/iotaledger/hive.go/autopeering/server"
 	"github.com/iotaledger/hive.go/logger"
-	"github.com/iotaledger/hive.go/netutil"
 	"github.com/iotaledger/hive.go/node"
 )
 
@@ -26,99 +22,51 @@ var (
 	log    *logger.Logger
 )
 
-func configure(plugin *node.Plugin) {
+func configure(*node.Plugin) {
 	log = logger.NewLogger(PLUGIN_NAME)
 }
 
-func run(ctx *node.Plugin) {
-	if !node.IsSkipped(autopeering.PLUGIN) {
-		log.Info("Testing autopeering service ...")
-		checkAutopeeringConnection()
-		log.Info("Testing autopeering service ... done")
-	}
-
-	if !node.IsSkipped(gossip.PLUGIN) {
-		log.Info("Testing gossip service ...")
-		checkGossipConnection()
-		log.Info("Testing gossip service ... done")
-	}
+func run(*node.Plugin) {
+	log.Info("Testing autopeering service ...")
+	checkAutopeeringConnection()
+	log.Info("Testing autopeering service ... done")
 }
 
 // check that discovery is working and the port is open
 func checkAutopeeringConnection() {
 	peering := local.GetInstance().Services().Get(service.PeeringKey)
 
-	// use the port of the peering service
-	_, peeringPort, err := net.SplitHostPort(peering.String())
-	if err != nil {
-		panic(err)
-	}
-
-	// resolve the bind address
-	address := net.JoinHostPort(config.Node.GetString(local.CFG_BIND), peeringPort)
-	localAddr, err := net.ResolveUDPAddr(peering.Network(), address)
-	if err != nil {
-		log.Fatalf("Error resolving %s: %v", local.CFG_BIND, err)
-	}
-
-	remoteAddr, err := net.ResolveUDPAddr(peering.Network(), peering.String())
-	if err != nil {
-		panic(err)
-	}
-
-	// do not check address and port as a NAT may change them for local connections
-	err = netutil.CheckUDP(localAddr, remoteAddr, false, false)
-	if err != nil {
-		log.Errorf("Error testing autopeering service: %s", err)
-		log.Panicf("Please check that %s is publicly reachable at %s/%s",
-			banner.AppName, peering.String(), peering.Network())
-	}
-}
-
-// check that the gossip server is working and the port is open
-func checkGossipConnection() {
-	// listen on TCP gossip port
-	lPeer := local.GetInstance()
-	// use the port of the gossip service
-	gossipAddr := lPeer.Services().Get(service.GossipKey)
-	_, gossipPort, err := net.SplitHostPort(gossipAddr.String())
-	if err != nil {
-		panic(err)
-	}
-
 	// resolve the bind address
-	address := net.JoinHostPort(config.Node.GetString(local.CFG_BIND), gossipPort)
-	localAddr, err := net.ResolveTCPAddr(gossipAddr.Network(), address)
+	localAddr, err := net.ResolveUDPAddr(peering.Network(), autopeering.GetBindAddress())
 	if err != nil {
 		log.Fatalf("Error resolving %s: %v", local.CFG_BIND, err)
 	}
-
-	listener, err := net.ListenTCP(gossipAddr.Network(), localAddr)
+	// open a connection
+	conn, err := net.ListenUDP(peering.Network(), localAddr)
 	if err != nil {
 		log.Fatalf("Error listening: %v", err)
 	}
-	defer listener.Close()
+	defer conn.Close()
 
-	srv := server.ServeTCP(lPeer, listener, log)
+	// create a new discovery server for the port check
+	disc := discover.New(local.GetInstance(), autopeering.ProtocolVersion, autopeering.NetworkID, discover.Logger(log))
+	srv := server.Serve(local.GetInstance(), conn, log, disc)
 	defer srv.Close()
 
-	// do the actual check
-	var wg sync.WaitGroup
-	wg.Add(1)
-	go func() {
-		defer wg.Done()
-		conn, acceptErr := srv.AcceptPeer(&lPeer.Peer)
-		if acceptErr != nil {
-			return
+	disc.Start(srv)
+	defer disc.Close()
+
+	for _, master := range autopeering.Discovery.GetMasterPeers() {
+		err = disc.Ping(master)
+		if err == nil {
+			log.Infof("Pong received from %s", master.IP())
+			break
 		}
-		_ = conn.Close()
-	}()
-	conn, err := srv.DialPeer(&lPeer.Peer)
+		log.Warnf("Error pinging entry node %s: %s", master.IP(), err)
+	}
+
 	if err != nil {
-		log.Errorf("Error testing: %s", err)
-		log.Panicf("Please check that %s is publicly reachable at %s/%s",
-			banner.AppName, gossipAddr.String(), gossipAddr.Network())
+		log.Fatalf("Please check that %s is publicly reachable at port %d/%s",
+			banner.AppName, peering.Port(), peering.Network())
 	}
-	_ = conn.Close()
-	wg.Wait()
 }
diff --git a/plugins/spa/plugin.go b/plugins/spa/plugin.go
index 0f63236a74c684b728bd45ffba0564134d211ca7..191b03ebc7d649e4110d0ab7bea63d5cdb431b2a 100644
--- a/plugins/spa/plugin.go
+++ b/plugins/spa/plugin.go
@@ -1,8 +1,10 @@
 package spa
 
 import (
+	"net"
 	"net/http"
 	"runtime"
+	"strconv"
 	"sync"
 	"time"
 
@@ -183,9 +185,12 @@ func neighborMetrics() []neighbormetric {
 				break
 			}
 		}
+
+		host := neighbor.Peer.IP().String()
+		port := neighbor.Peer.Services().Get(service.GossipKey).Port()
 		stats = append(stats, neighbormetric{
 			ID:               neighbor.Peer.ID().String(),
-			Address:          neighbor.Peer.Services().Get(service.GossipKey).String(),
+			Address:          net.JoinHostPort(host, strconv.Itoa(port)),
 			BytesRead:        neighbor.BytesRead(),
 			BytesWritten:     neighbor.BytesWritten(),
 			ConnectionOrigin: origin,
diff --git a/plugins/webapi/getNeighbors/plugin.go b/plugins/webapi/getNeighbors/plugin.go
index fe9c397196235d99dde63a7c5b2b467b3965e11e..5f4f45677c361007c3d080bfe19b67552f05c00d 100644
--- a/plugins/webapi/getNeighbors/plugin.go
+++ b/plugins/webapi/getNeighbors/plugin.go
@@ -2,7 +2,9 @@ package getNeighbors
 
 import (
 	"encoding/base64"
+	"net"
 	"net/http"
+	"strconv"
 
 	"github.com/iotaledger/goshimmer/plugins/autopeering"
 	"github.com/iotaledger/goshimmer/plugins/webapi"
@@ -83,12 +85,14 @@ type peerService struct {
 }
 
 func getServices(p *peer.Peer) []peerService {
-	services := []peerService{}
+	var services []peerService
+
+	host := p.IP().String()
 	peeringService := p.Services().Get(service.PeeringKey)
 	if peeringService != nil {
 		services = append(services, peerService{
 			ID:      "peering",
-			Address: peeringService.String(),
+			Address: net.JoinHostPort(host, strconv.Itoa(peeringService.Port())),
 		})
 	}
 
@@ -96,7 +100,7 @@ func getServices(p *peer.Peer) []peerService {
 	if gossipService != nil {
 		services = append(services, peerService{
 			ID:      "gossip",
-			Address: gossipService.String(),
+			Address: net.JoinHostPort(host, strconv.Itoa(gossipService.Port())),
 		})
 	}
 
@@ -104,7 +108,7 @@ func getServices(p *peer.Peer) []peerService {
 	if fpcService != nil {
 		services = append(services, peerService{
 			ID:      "FPC",
-			Address: fpcService.String(),
+			Address: net.JoinHostPort(host, strconv.Itoa(fpcService.Port())),
 		})
 	}