Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate Rosenpass #1153

Merged
merged 100 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
1a978d3
initial package integration
pascal-fischer Aug 18, 2023
818f42a
add some todos
pascal-fischer Aug 18, 2023
70d798a
fix order
pascal-fischer Aug 18, 2023
002cec5
Add 1st flow implementation
braginini Aug 18, 2023
ba3bfc6
Add rosenpass config generation
braginini Aug 18, 2023
0846551
GO mod tidy
braginini Aug 18, 2023
11cbf13
Fix roenpass pub key exchange
braginini Aug 18, 2023
51dd21b
Fix rp key generation
braginini Aug 18, 2023
0001009
Fix rosenpass config
braginini Aug 23, 2023
1f79677
Add rosenpass key debug
braginini Aug 24, 2023
0363ac1
Fix rosenpass key exchange
braginini Aug 24, 2023
8d7bf16
Add onDisconected rosenpass handler
braginini Aug 25, 2023
f25c0dd
Exchange ports between rosenpass peers
braginini Aug 28, 2023
b9755f3
Update rosenpass version to main
braginini Aug 28, 2023
1995b8c
Avoid restarting rosenpass server when peers didn't establish a conne…
braginini Aug 28, 2023
7effc43
Add keyout handler
braginini Aug 28, 2023
29dc7e5
Add keyout handler filepath
braginini Aug 28, 2023
324c6d0
Add WireGuard handler
braginini Aug 28, 2023
a23d130
Add WireGuard handler
braginini Aug 28, 2023
121b302
update manager to avoid race condition and prepare refactor of go-ros…
pascal-fischer Aug 29, 2023
00f0d2a
fix interface name for macos so handler can apply pre-shared key
pascal-fischer Aug 30, 2023
a25a0b8
refactor to use runtime management of rosenpass peers [missing new li…
pascal-fischer Aug 30, 2023
4f97031
upgrade rosenpass-go lib
pascal-fischer Aug 30, 2023
733d45f
set env variable to enable rosenpass and handle communication with di…
pascal-fischer Sep 1, 2023
0541a4c
allow backwards compatibility with older clients that no not have thi…
pascal-fischer Sep 1, 2023
db4b990
fixing coding style issues
pascal-fischer Sep 1, 2023
782f02b
run go mod tidy
pascal-fischer Sep 1, 2023
25f09b9
update github actions flows to golang 1.21
pascal-fischer Sep 1, 2023
fc7c361
convert env variable into cmd flag and use pre-shared key in rosenpass
pascal-fischer Sep 13, 2023
745fa08
update go-rosenpass to v0.4.0
pascal-fischer Sep 13, 2023
2f7b30a
fix flag being overwritten by service run
pascal-fischer Sep 14, 2023
a2ba405
initial package integration
pascal-fischer Aug 18, 2023
31a9d3c
add some todos
pascal-fischer Aug 18, 2023
a751f59
fix order
pascal-fischer Aug 18, 2023
5a6b228
Add 1st flow implementation
braginini Aug 18, 2023
92ebe66
Add rosenpass config generation
braginini Aug 18, 2023
ac76de9
GO mod tidy
braginini Aug 18, 2023
0d36ba9
Fix roenpass pub key exchange
braginini Aug 18, 2023
fdfe303
Fix rp key generation
braginini Aug 18, 2023
f7bc99e
Fix rosenpass config
braginini Aug 23, 2023
0495100
Add rosenpass key debug
braginini Aug 24, 2023
8fcd1a2
Fix rosenpass key exchange
braginini Aug 24, 2023
817865c
Add onDisconected rosenpass handler
braginini Aug 25, 2023
cd403f0
Exchange ports between rosenpass peers
braginini Aug 28, 2023
78fb9cb
Update rosenpass version to main
braginini Aug 28, 2023
f2630d4
Avoid restarting rosenpass server when peers didn't establish a conne…
braginini Aug 28, 2023
e814582
Add keyout handler
braginini Aug 28, 2023
ef89a1f
Add keyout handler filepath
braginini Aug 28, 2023
af8641b
Add WireGuard handler
braginini Aug 28, 2023
37e5b37
Add WireGuard handler
braginini Aug 28, 2023
057173a
update manager to avoid race condition and prepare refactor of go-ros…
pascal-fischer Aug 29, 2023
bb1f5cc
fix interface name for macos so handler can apply pre-shared key
pascal-fischer Aug 30, 2023
9f90ad2
refactor to use runtime management of rosenpass peers [missing new li…
pascal-fischer Aug 30, 2023
29f3b17
upgrade rosenpass-go lib
pascal-fischer Aug 30, 2023
2dc32c6
set env variable to enable rosenpass and handle communication with di…
pascal-fischer Sep 1, 2023
e2cd274
allow backwards compatibility with older clients that no not have thi…
pascal-fischer Sep 1, 2023
1a40f71
fixing coding style issues
pascal-fischer Sep 1, 2023
a4b249b
run go mod tidy
pascal-fischer Sep 1, 2023
52a27ba
update github actions flows to golang 1.21
pascal-fischer Sep 1, 2023
b5c4c91
convert env variable into cmd flag and use pre-shared key in rosenpass
pascal-fischer Sep 13, 2023
12f9741
update go-rosenpass to v0.4.0
pascal-fischer Sep 13, 2023
2d651ea
fix flag being overwritten by service run
pascal-fischer Sep 14, 2023
f29e7db
Merge remote-tracking branch 'origin/feature/rosenpass-integration' i…
pascal-fischer Sep 15, 2023
adf695e
implement wireguard connection restart
pascal-fischer Sep 18, 2023
1bd5151
fix key updating
pascal-fischer Sep 18, 2023
c294185
fix preshared key fix
pascal-fischer Sep 19, 2023
b5a49bc
cleanup log messages
pascal-fischer Sep 19, 2023
58f6b8a
clean go.mod
pascal-fischer Sep 19, 2023
6841fa0
fix failing test
pascal-fischer Sep 19, 2023
a0db992
randomize rosenpass port
pascal-fischer Sep 19, 2023
b305048
update go verison in github actions workflow for android
pascal-fischer Sep 19, 2023
087854b
remove rand seed
pascal-fischer Sep 19, 2023
a381e7c
update cli command to explicitly show that this feature is experimental
pascal-fischer Sep 20, 2023
08716c6
Merge remote-tracking branch 'origin/main' into feature/rosenpass-int…
braginini Oct 9, 2023
9a842a8
Merge rosenpass
braginini Oct 9, 2023
e53f309
Update golang version in golang lint workflow
braginini Oct 9, 2023
e18a1ef
Merge remote-tracking branch 'origin/main' into feature/rosenpass-int…
braginini Oct 30, 2023
d8075f0
Fix build
braginini Oct 30, 2023
efc1cca
Merge branch 'main' into feature/rosenpass-integration-v2
mlsmaycon Nov 7, 2023
9d0b3d5
update main
mlsmaycon Nov 7, 2023
873d3cf
Merge remote-tracking branch 'origin/main' into feature/rosenpass-int…
braginini Nov 21, 2023
41bd4e8
Merge branch 'main' into feature/rosenpass-integration-v2
pascal-fischer Dec 11, 2023
6865b1d
fix proto generation
pascal-fischer Dec 11, 2023
9156fc7
Merge branch 'main' into feature/rosenpass-integration-v2
mlsmaycon Dec 17, 2023
bfc1e81
send enable rosenpass on change
mlsmaycon Dec 17, 2023
ea45e98
use grpc methods
mlsmaycon Dec 17, 2023
a28c14e
handle disabled rosenpass mode
mlsmaycon Dec 17, 2023
579e9cd
refactor findRandomAvailableUDPPort and rename hash func
mlsmaycon Dec 17, 2023
c58e477
fix flag init
mlsmaycon Dec 17, 2023
9176cb5
remove unnecessary flag
mlsmaycon Dec 17, 2023
0b83455
pass wg iface to handler
mlsmaycon Dec 17, 2023
072fa5d
do not support fallback if remote peer does not have rosenpass enabled
pascal-fischer Dec 18, 2023
a361a94
Merge branch 'main' into feature/rosenpass-integration-v2
pascal-fischer Jan 4, 2024
8a5c70c
update gomod
pascal-fischer Jan 5, 2024
fd076b0
update gomod
pascal-fischer Jan 5, 2024
3537104
update gomod
pascal-fischer Jan 5, 2024
5809cc0
fix sorting function
pascal-fischer Jan 5, 2024
db9f5d0
fix linter
pascal-fischer Jan 5, 2024
dcafdcd
update go mod
pascal-fischer Jan 5, 2024
4f0d036
update go mod
pascal-fischer Jan 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/android-build-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: "1.20.x"
go-version: "1.21.x"
- name: Setup Android SDK
uses: android-actions/setup-android@v2
- name: NDK Cache
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/golang-test-darwin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: "1.20.x"
go-version: "1.21.x"
- name: Checkout code
uses: actions/checkout@v3

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/golang-test-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: "1.20.x"
go-version: "1.21.x"


- name: Cache Go modules
Expand Down Expand Up @@ -50,7 +50,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: "1.20.x"
go-version: "1.21.x"

- name: Cache Go modules
uses: actions/cache@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/golang-test-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
uses: actions/setup-go@v4
id: go
with:
go-version: "1.20.x"
go-version: "1.21.x"

- name: Download wintun
uses: carlosperate/download-file-action@v2
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: golangci-lint
on: [pull_request]

permissions:
permissions:
contents: read
pull-requests: read

Expand Down Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: "1.20.x"
go-version: "1.21.x"
cache: false
- name: Install dependencies
if: matrix.os == 'ubuntu-latest'
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
name: Set up Go
uses: actions/setup-go@v4
with:
go-version: "1.20"
go-version: "1.21"
cache: false
-
name: Cache Go modules
Expand Down Expand Up @@ -120,7 +120,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: "1.20"
go-version: "1.21"
cache: false
- name: Cache Go modules
uses: actions/cache@v3
Expand Down Expand Up @@ -175,7 +175,7 @@ jobs:
name: Set up Go
uses: actions/setup-go@v4
with:
go-version: "1.20"
go-version: "1.21"
cache: false
-
name: Cache Go modules
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-infrastructure-files.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: Install Go
uses: actions/setup-go@v4
with:
go-version: "1.20.x"
go-version: "1.21.x"

- name: Cache Go modules
uses: actions/cache@v3
Expand Down
7 changes: 5 additions & 2 deletions client/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ import (
)

const (
externalIPMapFlag = "external-ip-map"
externalIPMapFlag = "external-ip-map"
dnsResolverAddress = "dns-resolver-address"
enableRosenpassFlag = "enable-rosenpass"
preSharedKeyFlag = "preshared-key"
dnsResolverAddress = "dns-resolver-address"
)

var (
Expand All @@ -50,6 +51,7 @@ var (
preSharedKey string
natExternalIPs []string
customDNSAddress string
rosenpassEnabled bool
rootCmd = &cobra.Command{
Use: "netbird",
Short: "",
Expand Down Expand Up @@ -119,6 +121,7 @@ func init() {
`An empty string "" clears the previous configuration. `+
`E.g. --dns-resolver-address 127.0.0.1:5053 or --dns-resolver-address ""`,
)
upCmd.PersistentFlags().BoolVar(&rosenpassEnabled, enableRosenpassFlag, false, "[Experimental] Enable Rosenpass feature. If enabled, the connection will be post-quantum secured via Rosenpass.")
}

// SetupCloseHandler handles SIGTERM signal and exits with success
Expand Down
8 changes: 8 additions & 0 deletions client/cmd/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ func runInForegroundMode(ctx context.Context, cmd *cobra.Command) error {
CustomDNSAddress: customDNSAddressConverted,
}

if rootCmd.PersistentFlags().Changed(enableRosenpassFlag) {
ic.RosenpassEnabled = &rosenpassEnabled
}

if rootCmd.PersistentFlags().Changed(preSharedKeyFlag) {
ic.PreSharedKey = &preSharedKey
}
Expand Down Expand Up @@ -153,6 +157,10 @@ func runInDaemonMode(ctx context.Context, cmd *cobra.Command) error {
Hostname: hostName,
}

if cmd.Flag(enableRosenpassFlag).Changed {
loginRequest.RosenpassEnabled = &rosenpassEnabled
}

var loginErr error

var loginResp *proto.LoginResponse
Expand Down
11 changes: 11 additions & 0 deletions client/internal/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type ConfigInput struct {
PreSharedKey *string
NATExternalIPs []string
CustomDNSAddress []byte
RosenpassEnabled *bool
}

// Config Configuration type
Expand All @@ -54,6 +55,7 @@ type Config struct {
WgPort int
IFaceBlackList []string
DisableIPv6Discovery bool
RosenpassEnabled bool
// SSHKey is a private SSH key in a PEM format
SSHKey string

Expand Down Expand Up @@ -169,6 +171,10 @@ func createNewConfig(input ConfigInput) (*Config, error) {
config.PreSharedKey = *input.PreSharedKey
}

if input.RosenpassEnabled != nil {
config.RosenpassEnabled = *input.RosenpassEnabled
}

defaultAdminURL, err := parseURL("Admin URL", DefaultAdminURL)
if err != nil {
return nil, err
Expand Down Expand Up @@ -247,6 +253,11 @@ func update(input ConfigInput) (*Config, error) {
refresh = true
}

if input.RosenpassEnabled != nil {
config.RosenpassEnabled = *input.RosenpassEnabled
refresh = true
}

if refresh {
// since we have new management URL, we need to update config file
if err := util.WriteJson(input.ConfigPath, config); err != nil {
Expand Down
1 change: 1 addition & 0 deletions client/internal/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ func createEngineConfig(key wgtypes.Key, config *Config, peerConfig *mgmProto.Pe
SSHKey: []byte(config.SSHKey),
NATExternalIPs: config.NATExternalIPs,
CustomDNSAddress: config.CustomDNSAddress,
RosenpassEnabled: config.RosenpassEnabled,
}

if config.PreSharedKey != "" {
Expand Down
95 changes: 88 additions & 7 deletions client/internal/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/netbirdio/netbird/client/internal/acl"
"github.com/netbirdio/netbird/client/internal/dns"
"github.com/netbirdio/netbird/client/internal/peer"
"github.com/netbirdio/netbird/client/internal/rosenpass"
"github.com/netbirdio/netbird/client/internal/routemanager"
"github.com/netbirdio/netbird/client/internal/wgproxy"
nbssh "github.com/netbirdio/netbird/client/ssh"
Expand Down Expand Up @@ -76,6 +77,8 @@ type EngineConfig struct {
NATExternalIPs []string

CustomDNSAddress string

RosenpassEnabled bool
}

// Engine is a mechanism responsible for reacting on Signal and Management stream events and managing connections to the remote peers.
Expand All @@ -86,6 +89,8 @@ type Engine struct {
mgmClient mgm.Client
// peerConns is a map that holds all the peers that are known to this peer
peerConns map[string]*peer.Conn
// rpManager is a Rosenpass manager
rpManager *rosenpass.Manager

// syncMsgMux is used to guarantee sequential Management Service message processing
syncMsgMux *sync.Mutex
Expand Down Expand Up @@ -185,6 +190,18 @@ func (e *Engine) Start() error {
}
e.wgInterface = wgIface

if e.config.RosenpassEnabled {
log.Infof("rosenpass is enabled")
e.rpManager, err = rosenpass.NewManager(e.config.PreSharedKey, e.config.WgIfaceName)
if err != nil {
return err
}
err := e.rpManager.Run()
if err != nil {
return err
}
}

initialRoutes, dnsServer, err := e.newDnsServer()
if err != nil {
e.close()
Expand Down Expand Up @@ -363,7 +380,8 @@ func sendSignal(message *sProto.Message, s signal.Client) error {
}

// SignalOfferAnswer signals either an offer or an answer to remote peer
func SignalOfferAnswer(offerAnswer peer.OfferAnswer, myKey wgtypes.Key, remoteKey wgtypes.Key, s signal.Client, isAnswer bool) error {
func SignalOfferAnswer(offerAnswer peer.OfferAnswer, myKey wgtypes.Key, remoteKey wgtypes.Key, s signal.Client,
isAnswer bool) error {
var t sProto.Body_Type
if isAnswer {
t = sProto.Body_ANSWER
Expand All @@ -374,7 +392,7 @@ func SignalOfferAnswer(offerAnswer peer.OfferAnswer, myKey wgtypes.Key, remoteKe
msg, err := signal.MarshalCredential(myKey, offerAnswer.WgListenPort, remoteKey, &signal.Credential{
UFrag: offerAnswer.IceCredentials.UFrag,
Pwd: offerAnswer.IceCredentials.Pwd,
}, t)
}, t, offerAnswer.RosenpassPubKey, offerAnswer.RosenpassAddr)
if err != nil {
return err
}
Expand Down Expand Up @@ -627,6 +645,7 @@ func (e *Engine) updateNetworkMap(networkMap *mgmProto.NetworkMap) error {
e.acl.ApplyFiltering(networkMap)
}
e.networkSerial = serial

return nil
}

Expand Down Expand Up @@ -796,6 +815,26 @@ func (e *Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, e
PreSharedKey: e.config.PreSharedKey,
}

if e.config.RosenpassEnabled {
lk := []byte(e.config.WgPrivateKey.PublicKey().String())
rk := []byte(wgConfig.RemoteKey)
var keyInput []byte
if string(lk) > string(rk) {
//nolint:gocritic
keyInput = append(lk[:16], rk[:16]...)
} else {
//nolint:gocritic
keyInput = append(rk[:16], lk[:16]...)
}

key, err := wgtypes.NewKey(keyInput)
if err != nil {
return nil, err
}

wgConfig.PreSharedKey = &key
}

// randomize connection timeout
timeout := time.Duration(rand.Intn(PeerConnectionTimeoutMax-PeerConnectionTimeoutMin)+PeerConnectionTimeoutMin) * time.Millisecond
config := peer.ConnConfig{
Expand All @@ -811,6 +850,8 @@ func (e *Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, e
LocalWgPort: e.config.WgPort,
NATExternalIPs: e.parseNATExternalIPMappings(),
UserspaceBind: e.wgInterface.IsUserspaceBind(),
RosenpassPubKey: e.getRosenpassPubKey(),
RosenpassAddr: e.getRosenpassAddr(),
}

peerConn, err := peer.NewConn(config, e.statusRecorder, e.wgProxyFactory, e.mobileDep.TunAdapter, e.mobileDep.IFaceDiscover)
Expand Down Expand Up @@ -842,6 +883,12 @@ func (e *Engine) createPeerConn(pubKey string, allowedIPs string) (*peer.Conn, e
return sendSignal(message, e.signal)
})

if e.rpManager != nil {

peerConn.SetOnConnected(e.rpManager.OnConnected)
peerConn.SetOnDisconnected(e.rpManager.OnDisconnected)
}

return peerConn, nil
}

Expand All @@ -867,29 +914,45 @@ func (e *Engine) receiveSignalEvents() {

conn.RegisterProtoSupportMeta(msg.Body.GetFeaturesSupported())

var rosenpassPubKey []byte
rosenpassAddr := ""
if msg.GetBody().GetRosenpassConfig() != nil {
rosenpassPubKey = msg.GetBody().GetRosenpassConfig().GetRosenpassPubKey()
rosenpassAddr = msg.GetBody().GetRosenpassConfig().GetRosenpassServerAddr()
}
conn.OnRemoteOffer(peer.OfferAnswer{
IceCredentials: peer.IceCredentials{
UFrag: remoteCred.UFrag,
Pwd: remoteCred.Pwd,
},
WgListenPort: int(msg.GetBody().GetWgListenPort()),
Version: msg.GetBody().GetNetBirdVersion(),
WgListenPort: int(msg.GetBody().GetWgListenPort()),
Version: msg.GetBody().GetNetBirdVersion(),
RosenpassPubKey: rosenpassPubKey,
RosenpassAddr: rosenpassAddr,
})
case sProto.Body_ANSWER:
remoteCred, err := signal.UnMarshalCredential(msg)
if err != nil {
return err
}

conn.RegisterProtoSupportMeta(msg.Body.GetFeaturesSupported())
conn.RegisterProtoSupportMeta(msg.GetBody().GetFeaturesSupported())

var rosenpassPubKey []byte
rosenpassAddr := ""
if msg.GetBody().GetRosenpassConfig() != nil {
rosenpassPubKey = msg.GetBody().GetRosenpassConfig().GetRosenpassPubKey()
rosenpassAddr = msg.GetBody().GetRosenpassConfig().GetRosenpassServerAddr()
}
conn.OnRemoteAnswer(peer.OfferAnswer{
IceCredentials: peer.IceCredentials{
UFrag: remoteCred.UFrag,
Pwd: remoteCred.Pwd,
},
WgListenPort: int(msg.GetBody().GetWgListenPort()),
Version: msg.GetBody().GetNetBirdVersion(),
WgListenPort: int(msg.GetBody().GetWgListenPort()),
Version: msg.GetBody().GetNetBirdVersion(),
RosenpassPubKey: rosenpassPubKey,
RosenpassAddr: rosenpassAddr,
})
case sProto.Body_CANDIDATE:
candidate, err := ice.UnmarshalCandidate(msg.GetBody().Payload)
Expand Down Expand Up @@ -1000,6 +1063,10 @@ func (e *Engine) close() {
log.Warnf("failed to reset firewall: %s", err)
}
}

if e.rpManager != nil {
_ = e.rpManager.Close()
}
}

func (e *Engine) readInitialSettings() ([]*route.Route, *nbdns.Config, error) {
Expand Down Expand Up @@ -1094,3 +1161,17 @@ func findIPFromInterface(iface *net.Interface) (net.IP, error) {
}
return nil, fmt.Errorf("interface %s don't have an ipv4 address", iface.Name)
}

func (e *Engine) getRosenpassPubKey() []byte {
if e.rpManager != nil {
return e.rpManager.GetPubKey()
}
return nil
}

func (e *Engine) getRosenpassAddr() string {
if e.rpManager != nil {
return e.rpManager.GetAddress().String()
}
return ""
}