github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/p2p/listener.go (about)

     1  /*
     2   * Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package p2p
    19  
    20  import (
    21  	"context"
    22  	"fmt"
    23  	"net"
    24  	"sync"
    25  	"time"
    26  
    27  	nats_lib "github.com/nats-io/nats.go"
    28  	"github.com/rs/zerolog/log"
    29  	"google.golang.org/protobuf/proto"
    30  
    31  	"github.com/mysteriumnetwork/node/communication/nats"
    32  	"github.com/mysteriumnetwork/node/core/ip"
    33  	"github.com/mysteriumnetwork/node/eventbus"
    34  	"github.com/mysteriumnetwork/node/identity"
    35  	"github.com/mysteriumnetwork/node/market"
    36  	"github.com/mysteriumnetwork/node/nat/traversal"
    37  	"github.com/mysteriumnetwork/node/p2p/compat"
    38  	"github.com/mysteriumnetwork/node/p2p/nat"
    39  	"github.com/mysteriumnetwork/node/pb"
    40  	"github.com/mysteriumnetwork/node/trace"
    41  )
    42  
    43  // Listener knows how to exchange p2p keys and encrypted configuration and creates ready to use p2p channels.
    44  type Listener interface {
    45  	// Listen listens for incoming peer connections to establish new p2p channels. Establishes p2p channel and passes it
    46  	// to channelHandlers
    47  	Listen(providerID identity.Identity, serviceType string, channelHandler func(ch Channel)) (func(), error)
    48  
    49  	// GetContact returns contract which is later can be added to proposal contacts definition so consumer can
    50  	// know how to connect to this p2p listener.
    51  	GetContact() market.Contact
    52  }
    53  
    54  // NewListener creates new p2p communication listener which is used on provider side.
    55  func NewListener(brokerConn nats.Connection, signer identity.SignerFactory, verifier identity.Verifier, ipResolver ip.Resolver, eventBus eventbus.EventBus) Listener {
    56  	return &listener{
    57  		brokerConn:     brokerConn,
    58  		pendingConfigs: map[PublicKey]p2pConnectConfig{},
    59  		ipResolver:     ipResolver,
    60  		signer:         signer,
    61  		verifier:       verifier,
    62  		eventBus:       eventBus,
    63  	}
    64  }
    65  
    66  // listener implements Listener interface.
    67  type listener struct {
    68  	eventBus   eventbus.EventBus
    69  	brokerConn nats.Connection
    70  	signer     identity.SignerFactory
    71  	verifier   identity.Verifier
    72  	ipResolver ip.Resolver
    73  
    74  	// Keys holds pendingConfigs temporary configs for provider side since it
    75  	// need to handle key exchange in two steps.
    76  	pendingConfigs   map[PublicKey]p2pConnectConfig
    77  	pendingConfigsMu sync.Mutex
    78  }
    79  
    80  type p2pConnectConfig struct {
    81  	publicIP         string
    82  	peerPublicIP     string
    83  	compatibility    int
    84  	peerPorts        []int
    85  	localPorts       []int
    86  	publicPorts      []int
    87  	publicKey        PublicKey
    88  	privateKey       PrivateKey
    89  	peerPubKey       PublicKey
    90  	tracer           *trace.Tracer
    91  	upnpPortsRelease func()
    92  	start            nat.StartPorts
    93  	peerID           identity.Identity
    94  }
    95  
    96  func (c *p2pConnectConfig) peerIP() string {
    97  	if c.publicIP == c.peerPublicIP {
    98  		// Assume that both peers are on the same network.
    99  		return "127.0.0.1"
   100  	}
   101  	return c.peerPublicIP
   102  }
   103  
   104  func (m *listener) GetContact() market.Contact {
   105  	return market.Contact{
   106  		Type:       ContactTypeV1,
   107  		Definition: ContactDefinition{BrokerAddresses: m.brokerConn.Servers()},
   108  	}
   109  }
   110  
   111  // Listen listens for incoming peer connections to establish new p2p channels. Establishes p2p channel and passes it
   112  // to channelHandlers.
   113  func (m *listener) Listen(providerID identity.Identity, serviceType string, channelHandlers func(ch Channel)) (func(), error) {
   114  	configSignedSubject, err := nats.SignedSubject(m.signer(providerID), configExchangeSubject(providerID, serviceType))
   115  	if err != nil {
   116  		return func() {}, fmt.Errorf("cannot sign config topic: %w", err)
   117  	}
   118  
   119  	configSub, err := m.brokerConn.Subscribe(configSignedSubject, func(msg *nats_lib.Msg) {
   120  		if err := m.providerStartConfigExchange(providerID, msg); err != nil {
   121  			log.Err(err).Msg("Could not handle initial exchange")
   122  			return
   123  		}
   124  	})
   125  	if err != nil {
   126  		return func() {}, fmt.Errorf("could not get subscribe to config exchange topic: %w", err)
   127  	}
   128  
   129  	ackSignedSubject, err := nats.SignedSubject(m.signer(providerID), configExchangeACKSubject(providerID, serviceType))
   130  	if err != nil {
   131  		return func() {}, fmt.Errorf("cannot sign ack topic: %w", err)
   132  	}
   133  
   134  	ackSub, err := m.brokerConn.Subscribe(ackSignedSubject, func(msg *nats_lib.Msg) {
   135  		config, err := m.providerAckConfigExchange(msg)
   136  		if err != nil {
   137  			log.Err(err).Msg("Could not handle exchange ack")
   138  			return
   139  		}
   140  
   141  		trace := config.tracer.StartStage("Provider P2P exchange ack")
   142  		// Send ack in separate goroutine and start pinging.
   143  		// It is important that provider starts sending pings first otherwise
   144  		// providers router can think that consumer is sending DDoS packets.
   145  		go func(reply string) {
   146  			// race condition still happens when consumer starts to ping until provider did not manage to complete required number of pings
   147  			// this might be provider / consumer performance dependent
   148  			// make sleep time dependent on pinger interval and wait for 2 ping iterations
   149  			// TODO: either reintroduce eventual increase of TTL on consumer or maintain some sane delay
   150  			dur := traversal.DefaultPingConfig().Interval.Milliseconds() * int64(len(config.localPorts)) / 2
   151  			log.Debug().Msgf("Delaying pings from consumer for %v ms", dur)
   152  			time.Sleep(time.Duration(dur) * time.Millisecond)
   153  
   154  			if err := m.brokerConn.Publish(reply, []byte("OK")); err != nil {
   155  				log.Err(err).Msg("Could not publish exchange ack")
   156  			}
   157  			config.tracer.EndStage(trace)
   158  		}(msg.Reply)
   159  
   160  		var conn1, conn2 *net.UDPConn
   161  		if config.start != nil {
   162  			traceDial := config.tracer.StartStage("Provider P2P dial (preparation)")
   163  			log.Debug().Msgf("Pinging consumer using ports %v:%v initial ttl: %v", config.localPorts, config.peerPorts, 1)
   164  
   165  			conns, err := config.start(context.Background(), config.peerIP(), config.peerPorts, config.localPorts)
   166  			if err != nil {
   167  				log.Err(err).Msg("Could not ping peer")
   168  				return
   169  			}
   170  
   171  			if len(conns) != requiredConnCount {
   172  				log.Err(err).Msg("Could not get required number of connections")
   173  				return
   174  			}
   175  
   176  			conn1 = conns[0]
   177  			conn2 = conns[1]
   178  			config.tracer.EndStage(traceDial)
   179  		} else {
   180  			traceDial := config.tracer.StartStage("Provider P2P dial (direct)")
   181  			log.Debug().Msg("Skipping consumer ping")
   182  			conn1, err = net.DialUDP("udp4", &net.UDPAddr{Port: config.localPorts[0]}, &net.UDPAddr{IP: net.ParseIP(config.peerIP()), Port: config.peerPorts[0]})
   183  			if err != nil {
   184  				log.Err(err).Msg("Could not create UDP conn for p2p channel")
   185  				return
   186  			}
   187  			conn2, err = net.DialUDP("udp4", &net.UDPAddr{Port: config.localPorts[1]}, &net.UDPAddr{IP: net.ParseIP(config.peerIP()), Port: config.peerPorts[1]})
   188  			if err != nil {
   189  				log.Err(err).Msg("Could not create UDP conn for service")
   190  				return
   191  			}
   192  			config.tracer.EndStage(traceDial)
   193  		}
   194  
   195  		traceAck := config.tracer.StartStage("Provider P2P dial ack")
   196  		channel, err := newChannel(conn1, config.privateKey, config.peerPubKey, config.compatibility)
   197  		if err != nil {
   198  			log.Err(err).Msg("Could not create channel")
   199  			return
   200  		}
   201  		channel.setTracer(config.tracer)
   202  		channel.setServiceConn(conn2)
   203  		channel.setPeerID(config.peerID)
   204  		channel.setUpnpPortsRelease(config.upnpPortsRelease)
   205  
   206  		channelHandlers(channel)
   207  
   208  		channel.launchReadSendLoops()
   209  
   210  		// Send handlers ready to consumer.
   211  		if err := m.providerChannelHandlersReady(providerID, serviceType); err != nil {
   212  			log.Err(err).Msg("Could not handle channel handlers ready")
   213  			channel.Close()
   214  			return
   215  		}
   216  		config.tracer.EndStage(traceAck)
   217  	})
   218  	if err != nil {
   219  		if err := configSub.Unsubscribe(); err != nil {
   220  			log.Err(err).Msg("Failed to unsubscribe from config exchange topic")
   221  		}
   222  		return func() {}, fmt.Errorf("could not get subscribe to config exchange acknowledge topic: %w", err)
   223  	}
   224  
   225  	return func() {
   226  		if err := configSub.Unsubscribe(); err != nil {
   227  			log.Err(err).Msg("Failed to unsubscribe from config exchange topic")
   228  		}
   229  		if err := ackSub.Unsubscribe(); err != nil {
   230  			log.Err(err).Msg("Failed to unsubscribe from config exchange acknowledge topic")
   231  		}
   232  	}, nil
   233  }
   234  
   235  func (m *listener) providerStartConfigExchange(providerID identity.Identity, msg *nats_lib.Msg) error {
   236  	tracer := trace.NewTracer("Provider whole Connect")
   237  
   238  	trace := tracer.StartStage("Provider P2P exchange")
   239  	defer tracer.EndStage(trace)
   240  
   241  	pubKey, privateKey, err := GenerateKey()
   242  	if err != nil {
   243  		return fmt.Errorf("could not generate provider p2p keys: %w", err)
   244  	}
   245  
   246  	// Get initial peer exchange with it's public key.
   247  	signedMsg, peerID, err := unpackSignedMsg(m.verifier, msg.Data)
   248  	if err != nil {
   249  		return fmt.Errorf("could not unpack signed msg: %w", err)
   250  	}
   251  	var peerExchangeMsg pb.P2PConfigExchangeMsg
   252  	if err := proto.Unmarshal(signedMsg.Data, &peerExchangeMsg); err != nil {
   253  		return err
   254  	}
   255  	peerPubKey, err := DecodePublicKey(peerExchangeMsg.PublicKey)
   256  	if err != nil {
   257  		return err
   258  	}
   259  	log.Debug().Msgf("Received consumer public key %s", peerPubKey.Hex())
   260  
   261  	publicIP, localPorts, portsRelease, start, err := m.prepareLocalPorts(providerID.Address, tracer)
   262  	if err != nil {
   263  		return fmt.Errorf("could not prepare ports: %w", err)
   264  	}
   265  
   266  	p2pConnConfig := p2pConnectConfig{
   267  		publicIP:         publicIP,
   268  		localPorts:       localPorts,
   269  		publicPorts:      stunPorts(providerID, m.eventBus, localPorts...),
   270  		publicKey:        pubKey,
   271  		privateKey:       privateKey,
   272  		peerPubKey:       peerPubKey,
   273  		tracer:           tracer,
   274  		upnpPortsRelease: portsRelease,
   275  		peerPublicIP:     "",
   276  		peerPorts:        nil,
   277  		start:            start,
   278  		peerID:           peerID,
   279  	}
   280  	m.setPendingConfig(p2pConnConfig)
   281  
   282  	config := pb.P2PConnectConfig{
   283  		PublicIP:      publicIP,
   284  		Ports:         intToInt32Slice(p2pConnConfig.publicPorts),
   285  		Compatibility: compat.Compatibility,
   286  	}
   287  	configCiphertext, err := encryptConnConfigMsg(&config, privateKey, peerPubKey)
   288  	if err != nil {
   289  		return fmt.Errorf("could not encrypt config msg: %w", err)
   290  	}
   291  	exchangeMsg := pb.P2PConfigExchangeMsg{
   292  		PublicKey:        pubKey.Hex(),
   293  		ConfigCiphertext: configCiphertext,
   294  	}
   295  	log.Debug().Msgf("Sending reply with public key %s and encrypted config to consumer", exchangeMsg.PublicKey)
   296  	packedMsg, err := packSignedMsg(m.signer, providerID, &exchangeMsg)
   297  	if err != nil {
   298  		return fmt.Errorf("could not pack signed message: %w", err)
   299  	}
   300  	err = m.brokerConn.Publish(msg.Reply, packedMsg)
   301  	if err != nil {
   302  		return fmt.Errorf("could not publish message via broker: %w", err)
   303  	}
   304  	return nil
   305  }
   306  
   307  // prepareLocalPorts acquires ports for p2p connections. It tries to acquire only
   308  // required ports count for actual p2p and service connections and fallback to
   309  // acquiring extra ports for nat pinger if provider is behind nat, port mapping failed
   310  // and no manual port forwarding is enabled.
   311  func (m *listener) prepareLocalPorts(id string, tracer *trace.Tracer) (string, []int, func(), nat.StartPorts, error) {
   312  	trace := tracer.StartStage("Provider P2P exchange (ports)")
   313  	defer tracer.EndStage(trace)
   314  
   315  	publicIP, err := m.ipResolver.GetPublicIP()
   316  	if err != nil {
   317  		return "", nil, nil, nil, fmt.Errorf("could not get public IP: %w", err)
   318  	}
   319  
   320  	for _, p := range nat.OrderedPortProviders() {
   321  		ports, release, start, err := p.Provider.PreparePorts()
   322  		if err == nil {
   323  			m.eventBus.Publish(nat.AppTopicNATTraversalMethod, nat.NATTraversalMethod{
   324  				Identity: id,
   325  				Method:   p.Method,
   326  				Success:  true,
   327  			})
   328  			return publicIP, ports, release, start, nil
   329  		}
   330  
   331  		m.eventBus.Publish(nat.AppTopicNATTraversalMethod, nat.NATTraversalMethod{
   332  			Identity: id,
   333  			Method:   p.Method,
   334  			Success:  false,
   335  		})
   336  	}
   337  
   338  	return "", nil, nil, nil, fmt.Errorf("failed to prepare local ports")
   339  }
   340  
   341  func (m *listener) providerAckConfigExchange(msg *nats_lib.Msg) (*p2pConnectConfig, error) {
   342  	signedMsg, peerID, err := unpackSignedMsg(m.verifier, msg.Data)
   343  	if err != nil {
   344  		return nil, fmt.Errorf("could not unpack signed msg: %w", err)
   345  	}
   346  	var peerExchangeMsg pb.P2PConfigExchangeMsg
   347  	if err := proto.Unmarshal(signedMsg.Data, &peerExchangeMsg); err != nil {
   348  		return nil, fmt.Errorf("could not unmarshal exchange msg: %w", err)
   349  	}
   350  	peerPubKey, err := DecodePublicKey(peerExchangeMsg.PublicKey)
   351  	if err != nil {
   352  		return nil, err
   353  	}
   354  
   355  	defer m.deletePendingConfig(peerPubKey)
   356  	config, ok := m.pendingConfig(peerPubKey)
   357  	if !ok {
   358  		return nil, fmt.Errorf("pending config not found for key %s", peerPubKey.Hex())
   359  	}
   360  	if peerID != config.peerID {
   361  		return nil, fmt.Errorf("acknowledged config signed by unexpected identity: %s", peerID.ToCommonAddress())
   362  	}
   363  
   364  	peerConfig, err := decryptConnConfigMsg(peerExchangeMsg.ConfigCiphertext, config.privateKey, peerPubKey)
   365  	if err != nil {
   366  		return nil, fmt.Errorf("could not decrypt peer conn config: %w", err)
   367  	}
   368  
   369  	return &p2pConnectConfig{
   370  		peerPublicIP:     peerConfig.PublicIP,
   371  		peerPorts:        int32ToIntSlice(peerConfig.Ports),
   372  		compatibility:    int(peerConfig.Compatibility),
   373  		localPorts:       config.localPorts,
   374  		publicKey:        config.publicKey,
   375  		privateKey:       config.privateKey,
   376  		peerPubKey:       config.peerPubKey,
   377  		publicIP:         config.publicIP,
   378  		tracer:           config.tracer,
   379  		upnpPortsRelease: config.upnpPortsRelease,
   380  		start:            config.start,
   381  		peerID:           config.peerID,
   382  	}, nil
   383  }
   384  
   385  func (m *listener) providerChannelHandlersReady(providerID identity.Identity, serviceType string) error {
   386  	handlersReadyMsg := pb.P2PChannelHandlersReady{Value: "HANDLERS READY"}
   387  
   388  	message, err := proto.Marshal(&handlersReadyMsg)
   389  	if err != nil {
   390  		return fmt.Errorf("could not marshal exchange msg: %w", err)
   391  	}
   392  
   393  	signedSubject, err := nats.SignedSubject(m.signer(providerID), channelHandlersReadySubject(providerID, serviceType))
   394  	if err != nil {
   395  		return fmt.Errorf("unable to sign p2p-channel-handlers-ready subject: %w", err)
   396  	}
   397  
   398  	log.Debug().Msgf("Sending handlers ready message")
   399  	return m.brokerConn.Publish(signedSubject, message)
   400  }
   401  
   402  func (m *listener) pendingConfig(peerPubKey PublicKey) (p2pConnectConfig, bool) {
   403  	m.pendingConfigsMu.Lock()
   404  	defer m.pendingConfigsMu.Unlock()
   405  	config, ok := m.pendingConfigs[peerPubKey]
   406  	return config, ok
   407  }
   408  
   409  func (m *listener) setPendingConfig(config p2pConnectConfig) {
   410  	m.pendingConfigsMu.Lock()
   411  	defer m.pendingConfigsMu.Unlock()
   412  	m.pendingConfigs[config.peerPubKey] = config
   413  }
   414  
   415  func (m *listener) deletePendingConfig(peerPubKey PublicKey) {
   416  	m.pendingConfigsMu.Lock()
   417  	defer m.pendingConfigsMu.Unlock()
   418  	delete(m.pendingConfigs, peerPubKey)
   419  }