Skip to content

Commit

Permalink
feat(modp2p): websocket transport with TLS (#3560)
Browse files Browse the repository at this point in the history
  • Loading branch information
vgonkivs authored Aug 6, 2024
1 parent 62190ac commit 2ff58bf
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 12 deletions.
6 changes: 3 additions & 3 deletions nodebuilder/p2p/addrs.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import (
)

// Listen returns invoke function that starts listening for inbound connections with libp2p.Host.
func Listen(listen []string) func(h hst.Host) (err error) {
func Listen(cfg *Config) func(h hst.Host) (err error) {
return func(h hst.Host) (err error) {
maListen := make([]ma.Multiaddr, len(listen))
for i, addr := range listen {
maListen := make([]ma.Multiaddr, len(cfg.ListenAddresses))
for i, addr := range cfg.ListenAddresses {
maListen[i], err = ma.NewMultiaddr(addr)
if err != nil {
return fmt.Errorf("failure to parse config.P2P.ListenAddresses: %w", err)
Expand Down
15 changes: 15 additions & 0 deletions nodebuilder/p2p/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,18 @@ func (cfg *Config) Validate() error {
}
return nil
}

// Upgrade updates the `ListenAddresses` and `NoAnnounceAddresses` to
// include support for websocket connections.
func (cfg *Config) Upgrade() {
cfg.ListenAddresses = append(
cfg.ListenAddresses,
"/ip4/0.0.0.0/tcp/2122/wss",
"/ip6/::/tcp/2122/wss",
)
cfg.NoAnnounceAddresses = append(
cfg.NoAnnounceAddresses,
"/ip4/127.0.0.1/tcp/2122/wss",
"/ip6/::/tcp/2122/wss",
)
}
20 changes: 19 additions & 1 deletion nodebuilder/p2p/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import (
"github.com/libp2p/go-libp2p/core/routing"
routedhost "github.com/libp2p/go-libp2p/p2p/host/routed"
"github.com/libp2p/go-libp2p/p2p/net/conngater"
quic "github.com/libp2p/go-libp2p/p2p/transport/quic"
"github.com/libp2p/go-libp2p/p2p/transport/tcp"
webtransport "github.com/libp2p/go-libp2p/p2p/transport/webtransport"
"github.com/prometheus/client_golang/prometheus"
"go.uber.org/fx"

Expand Down Expand Up @@ -67,6 +70,15 @@ func (ua *UserAgent) String() string {
func host(params hostParams) (HostBase, error) {
ua := newUserAgent().WithNetwork(params.Net).WithNodeType(params.Tp)

tlsCfg, isEnabled, err := tlsEnabled()
if err != nil {
return nil, err
}

if isEnabled {
params.Cfg.Upgrade()
}

opts := []libp2p.Option{
libp2p.NoListenAddrs, // do not listen automatically
libp2p.AddrsFactory(params.AddrF),
Expand All @@ -79,9 +91,14 @@ func host(params hostParams) (HostBase, error) {
libp2p.DisableRelay(),
libp2p.BandwidthReporter(params.Bandwidth),
libp2p.ResourceManager(params.ResourceManager),
libp2p.ChainOptions(
libp2p.Transport(tcp.NewTCPTransport),
libp2p.Transport(quic.NewTransport),
libp2p.Transport(webtransport.New),
wsTransport(tlsCfg),
),
// to clearly define what defaults we rely upon
libp2p.DefaultSecurity,
libp2p.DefaultTransports,
libp2p.DefaultMuxers,
}

Expand Down Expand Up @@ -113,6 +130,7 @@ type HostBase hst.Host
type hostParams struct {
fx.In

Cfg *Config
Net Network
Lc fx.Lifecycle
ID peer.ID
Expand Down
2 changes: 1 addition & 1 deletion nodebuilder/p2p/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func defaultConnManagerConfig(tp node.Type) connManagerConfig {
}

// connectionManager provides a constructor for ConnectionManager.
func connectionManager(cfg Config, bpeers Bootstrappers) (connmgri.ConnManager, error) {
func connectionManager(cfg *Config, bpeers Bootstrappers) (connmgri.ConnManager, error) {
fpeers, err := cfg.mutualPeers()
if err != nil {
return nil, err
Expand Down
5 changes: 2 additions & 3 deletions nodebuilder/p2p/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ var log = logging.Logger("module/p2p")
func ConstructModule(tp node.Type, cfg *Config) fx.Option {
// sanitize config values before constructing module
cfgErr := cfg.Validate()

baseComponents := fx.Options(
fx.Supply(*cfg),
fx.Error(cfgErr),
fx.Supply(cfg),
fx.Provide(Key),
fx.Provide(id),
fx.Provide(peerStore),
Expand All @@ -34,7 +33,7 @@ func ConstructModule(tp node.Type, cfg *Config) fx.Option {
fx.Provide(addrsFactory(cfg.AnnounceAddresses, cfg.NoAnnounceAddresses)),
fx.Provide(metrics.NewBandwidthCounter),
fx.Provide(newModule),
fx.Invoke(Listen(cfg.ListenAddresses)),
fx.Invoke(Listen(cfg)),
fx.Provide(resourceManager),
fx.Provide(resourceManagerOpt(allowList)),
)
Expand Down
4 changes: 2 additions & 2 deletions nodebuilder/p2p/pubsub.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func init() {
}

// pubSub provides a constructor for PubSub protocol with GossipSub routing.
func pubSub(cfg Config, params pubSubParams) (*pubsub.PubSub, error) {
func pubSub(cfg *Config, params pubSubParams) (*pubsub.PubSub, error) {
fpeers, err := cfg.mutualPeers()
if err != nil {
return nil, err
Expand Down Expand Up @@ -122,7 +122,7 @@ func topicScoreParams(params pubSubParams) map[string]*pubsub.TopicScoreParams {
return mp
}

func peerScoreParams(bootstrappers Bootstrappers, cfg Config) (*pubsub.PeerScoreParams, error) {
func peerScoreParams(bootstrappers Bootstrappers, cfg *Config) (*pubsub.PeerScoreParams, error) {
bootstrapperSet := map[peer.ID]struct{}{}
for _, b := range bootstrappers {
bootstrapperSet[b.ID] = struct{}{}
Expand Down
2 changes: 1 addition & 1 deletion nodebuilder/p2p/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func autoscaleResources() rcmgr.ConcreteLimitConfig {
return limits.AutoScale()
}

func allowList(ctx context.Context, cfg Config, bootstrappers Bootstrappers) (rcmgr.Option, error) {
func allowList(ctx context.Context, cfg *Config, bootstrappers Bootstrappers) (rcmgr.Option, error) {
mutual, err := cfg.mutualPeers()
if err != nil {
return nil, err
Expand Down
2 changes: 1 addition & 1 deletion nodebuilder/p2p/routing.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func contentRouting(r routing.PeerRouting) routing.ContentRouting {

// peerRouting provides constructor for PeerRouting over DHT.
// Basically, this provides a way to discover peer addresses by respecting public keys.
func peerRouting(cfg Config, tp node.Type, params routingParams) (routing.PeerRouting, error) {
func peerRouting(cfg *Config, tp node.Type, params routingParams) (routing.PeerRouting, error) {
opts := []dht.Option{
dht.BootstrapPeers(params.Peers...),
dht.ProtocolPrefix(protocol.ID(fmt.Sprintf("/celestia/%s", params.Net))),
Expand Down
60 changes: 60 additions & 0 deletions nodebuilder/p2p/tls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package p2p

import (
"crypto/tls"
"os"
"path/filepath"

"github.com/libp2p/go-libp2p"
ws "github.com/libp2p/go-libp2p/p2p/transport/websocket"

"github.com/celestiaorg/celestia-node/libs/utils"
)

const (
cert = "cert.pem"
key = "key.pem"
)

var tlsPath = "CELESTIA_TLS_PATH"

// tlsEnabled checks whether `tlsPath` is not empty and creates a certificate.
// it returns the cfg itself, the bool flag that specifies whether the config was created
// and an error.
func tlsEnabled() (*tls.Config, bool, error) {
path := os.Getenv(tlsPath)
if path == "" {
log.Debug("the CELESTIA_TLS_PATH was not set")
return nil, false, nil
}

certPath := filepath.Join(path, cert)
keyPath := filepath.Join(path, key)
exist := utils.Exists(certPath) && utils.Exists(keyPath)
if !exist {
return nil, false, nil
}

cert, err := tls.LoadX509KeyPair(certPath, keyPath)
if err != nil {
return nil, false, err
}

return &tls.Config{
MinVersion: tls.VersionTLS12,
Certificates: []tls.Certificate{cert},
}, true, nil
}

// wsTransport enables a support for the secure websocket connection
// using the passed tls config. The connection will be insecure in case
// config is empty.
func wsTransport(config *tls.Config) libp2p.Option {
if config == nil {
log.Info("using a default ws transport")
return libp2p.Transport(ws.New)
}

log.Info("using a wss transport with tlsConfig")
return libp2p.Transport(ws.New, ws.WithTLSConfig(config))
}

0 comments on commit 2ff58bf

Please sign in to comment.