From 028a860beccdd04e6a1210d704900d66591a7ac4 Mon Sep 17 00:00:00 2001 From: braginini Date: Wed, 14 Apr 2021 14:29:21 +0200 Subject: [PATCH] refactor: remove unused code --- nat/discovery.go | 317 ----------------------------------------------- nat/nat.go | 83 ------------- relay/client.go | 159 ------------------------ 3 files changed, 559 deletions(-) delete mode 100644 nat/discovery.go delete mode 100644 nat/nat.go delete mode 100644 relay/client.go diff --git a/nat/discovery.go b/nat/discovery.go deleted file mode 100644 index 17ac1a9fa..000000000 --- a/nat/discovery.go +++ /dev/null @@ -1,317 +0,0 @@ -package nat - -import ( - "errors" - "github.com/pion/stun" - log "github.com/sirupsen/logrus" - "net" - "time" -) - -// Most of the code of this file is taken from the https://github.com/pion/stun/tree/master/cmd/stun-nat-behaviour package -// Copyright 2018 Pion LLC - -const ( - messageHeaderSize = 20 -) - -//taken from https://github.com/pion/stun/tree/master/cmd/stun-nat-behaviour -var ( - errResponseMessage = errors.New("error reading from response message channel") - errTimedOut = errors.New("timed out waiting for response") - errNoOtherAddress = errors.New("no OTHER-ADDRESS in the STUN response message") -) - -type Discovery struct { - stunAddr string - // a STUN server connection timeout - timeout time.Duration -} - -func NewDiscovery(stunAddr string, timeout time.Duration) *Discovery { - return &Discovery{ - stunAddr: stunAddr, - timeout: timeout, - } -} - -type Candidate struct { - Ip net.IP - Port int - // a type of the candidate [host, srflx, prflx, relay] - see WebRTC spec - Type string -} - -type Behaviour struct { - // indicates whether NAT is hard - address dependent or address and port dependent - IsStrict bool - // a list of external addresses (IP:port) received from the STUN server while testing NAT - // these can be used for the Wireguard connection in case IsStrict = false - Candidates []*Candidate - - LocalPort int -} - -//taken from https://github.com/pion/stun/tree/master/cmd/stun-nat-behaviour -type stunServerConn struct { - conn net.PacketConn - LocalAddr net.Addr - RemoteAddr *net.UDPAddr - OtherAddr *net.UDPAddr - messageChan chan *stun.Message -} - -func (c *stunServerConn) Close() error { - return c.conn.Close() -} - -// Discovers connection candidates and NAT behaviour by probing STUN server. -// For proper NAT behaviour it is required for the The STUN server to have multiple IPs (for probing different destinations). -// See https://github.com/pion/stun/tree/master/cmd/stun-nat-behaviour and https://tools.ietf.org/html/rfc5780 for details. -// In case the returned Behaviour.IsStrict = false the Behaviour.LocalPort and any of the Probes can be used for the Wireguard communication -// since the hole has been already punched. -// When Behaviour.IsStrict = true the hole punching requires extra actions. -func (d *Discovery) Discover() (*Behaviour, error) { - - // get a local address (candidate) - localConn, err := net.Dial("udp", "8.8.8.8:53") - if err != nil { - log.Errorf("Error getting local address: %s\n", err.Error()) - return nil, err - } - log.Infof("Local address %s", localConn.LocalAddr().String()) - err = localConn.Close() - if err != nil { - return nil, err - } - - lAddr, err := net.ResolveUDPAddr("udp4", localConn.LocalAddr().String()) - - mapTestConn, err := connect(d.stunAddr, lAddr) - if err != nil { - log.Errorf("Error creating STUN connection: %s\n", err.Error()) - return nil, err - } - - defer mapTestConn.Close() - - var candidates = []*Candidate{{Ip: lAddr.IP, Port: lAddr.Port, Type: "host"}} - - // Test I: Regular binding request - log.Info("Mapping Test I: Regular binding request") - request := stun.MustBuild(stun.TransactionID, stun.BindingRequest) - - resp, err := mapTestConn.roundTrip(request, mapTestConn.RemoteAddr, d.timeout) - if err != nil { - return nil, err - } - - // Parse response message for XOR-MAPPED-ADDRESS and make sure OTHER-ADDRESS valid - resps1 := parse(resp) - if resps1.xorAddr == nil || resps1.otherAddr == nil { - log.Warn("Error: NAT discovery feature not supported by this STUN server") - return nil, errNoOtherAddress - } - addr, err := net.ResolveUDPAddr("udp4", resps1.otherAddr.String()) - if err != nil { - log.Errorf("Failed resolving OTHER-ADDRESS: %v\n", resps1.otherAddr) - return nil, err - } - mapTestConn.OtherAddr = addr - log.Infof("Received XOR-MAPPED-ADDRESS: %v\n", resps1.xorAddr) - - candidates = append(candidates, &Candidate{resps1.xorAddr.IP, resps1.xorAddr.Port, "srflx"}) - - // Assert mapping behavior - if resps1.xorAddr.String() == mapTestConn.LocalAddr.String() { - log.Info("=> NAT mapping behavior: endpoint independent (no NAT)") - return &Behaviour{ - IsStrict: false, - Candidates: candidates, - LocalPort: mapTestConn.LocalAddr.(*net.UDPAddr).Port, - }, nil - } - - // Test II: Send binding request to the other address but primary port - log.Info("Mapping Test II: Send binding request to the other address but primary port") - oaddr := *mapTestConn.OtherAddr - oaddr.Port = mapTestConn.RemoteAddr.Port - resp, err = mapTestConn.roundTrip(request, &oaddr, d.timeout) - if err != nil { - return nil, err - } - - resps2 := parse(resp) - candidates = append(candidates, &Candidate{resps2.xorAddr.IP, resps2.xorAddr.Port, "srflx"}) - log.Infof("Received XOR-MAPPED-ADDRESS: %v\n", resps2.xorAddr) - - // Assert mapping behavior - if resps2.xorAddr.String() == resps1.xorAddr.String() { - log.Info("=> NAT mapping behavior: endpoint independent") - return &Behaviour{ - IsStrict: false, - Candidates: candidates, - LocalPort: mapTestConn.LocalAddr.(*net.UDPAddr).Port, - }, nil - } - - // Test III: Send binding request to the other address and port - log.Info("Mapping Test III: Send binding request to the other address and port") - resp, err = mapTestConn.roundTrip(request, mapTestConn.OtherAddr, d.timeout) - if err != nil { - return nil, err - } - - resps3 := parse(resp) - candidates = append(candidates, &Candidate{resps3.xorAddr.IP, resps3.xorAddr.Port, "srflx"}) - log.Infof("Received XOR-MAPPED-ADDRESS: %v\n", resps3.xorAddr) - - // Assert mapping behavior - if resps3.xorAddr.String() == resps2.xorAddr.String() { - log.Info("=> NAT mapping behavior: address dependent") - } else { - log.Info("=> NAT mapping behavior: address and port dependent") - } - - return &Behaviour{ - IsStrict: true, - Candidates: candidates, - LocalPort: mapTestConn.LocalAddr.(*net.UDPAddr).Port, - }, nil -} - -//taken from https://github.com/pion/stun/tree/master/cmd/stun-nat-behaviour -func connect(stunAddr string, lAddr *net.UDPAddr) (*stunServerConn, error) { - log.Debugf("connecting to STUN server: %s\n", stunAddr) - addr, err := net.ResolveUDPAddr("udp4", stunAddr) - if err != nil { - log.Errorf("Error resolving address: %s\n", err.Error()) - return nil, err - } - - c, err := net.ListenUDP("udp4", lAddr) - if err != nil { - return nil, err - } - log.Debugf("Local address: %s\n", c.LocalAddr()) - log.Debugf("Remote address: %s\n", addr.String()) - - mChan := listen(c) - - return &stunServerConn{ - conn: c, - LocalAddr: c.LocalAddr(), - RemoteAddr: addr, - messageChan: mChan, - }, nil -} - -//taken from https://github.com/pion/stun/tree/master/cmd/stun-nat-behaviour -func listen(conn *net.UDPConn) (messages chan *stun.Message) { - messages = make(chan *stun.Message) - go func() { - for { - buf := make([]byte, 1024) - - n, addr, err := conn.ReadFromUDP(buf) - if err != nil { - close(messages) - return - } - log.Debugf("Response from %v: (%v bytes)\n", addr, n) - buf = buf[:n] - - m := new(stun.Message) - m.Raw = buf - err = m.Decode() - if err != nil { - log.Debugf("Error decoding message: %v\n", err) - close(messages) - return - } - - messages <- m - } - }() - return -} - -// Send request and wait for response or timeout -//taken from https://github.com/pion/stun/tree/master/cmd/stun-nat-behaviour -func (c *stunServerConn) roundTrip(msg *stun.Message, addr net.Addr, timeout time.Duration) (*stun.Message, error) { - _ = msg.NewTransactionID() - log.Debugf("Sending to %v: (%v bytes)\n", addr, msg.Length+messageHeaderSize) - log.Debugf("%v\n", msg) - for _, attr := range msg.Attributes { - log.Debugf("\t%v (l=%v)\n", attr, attr.Length) - } - _, err := c.conn.WriteTo(msg.Raw, addr) - if err != nil { - log.Errorf("Error sending request to %v\n", addr) - return nil, err - } - - // Wait for response or timeout - select { - case m, ok := <-c.messageChan: - if !ok { - return nil, errResponseMessage - } - return m, nil - //todo configure timeout - case <-time.After(timeout): - log.Warnf("Timed out waiting for response from server %v\n", addr) - return nil, errTimedOut - } -} - -// Parse a STUN message -//taken from https://github.com/pion/stun/tree/master/cmd/stun-nat-behaviour -func parse(msg *stun.Message) (ret struct { - xorAddr *stun.XORMappedAddress - otherAddr *stun.OtherAddress - //respOrigin *stun.ResponseOrigin - mappedAddr *stun.MappedAddress - software *stun.Software -}) { - ret.mappedAddr = &stun.MappedAddress{} - ret.xorAddr = &stun.XORMappedAddress{} - //ret.respOrigin = &stun.ResponseOrigin{} - ret.otherAddr = &stun.OtherAddress{} - ret.software = &stun.Software{} - if ret.xorAddr.GetFrom(msg) != nil { - ret.xorAddr = nil - } - if ret.otherAddr.GetFrom(msg) != nil { - ret.otherAddr = nil - } - /*if ret.respOrigin.GetFrom(msg) != nil { - ret.respOrigin = nil - }*/ - if ret.mappedAddr.GetFrom(msg) != nil { - ret.mappedAddr = nil - } - if ret.software.GetFrom(msg) != nil { - ret.software = nil - } - log.Debugf("%v\n", msg) - log.Debugf("\tMAPPED-ADDRESS: %v\n", ret.mappedAddr) - log.Debugf("\tXOR-MAPPED-ADDRESS: %v\n", ret.xorAddr) - //log.Debugf("\tRESPONSE-ORIGIN: %v\n", ret.respOrigin) - log.Debugf("\tOTHER-ADDRESS: %v\n", ret.otherAddr) - log.Debugf("\tSOFTWARE: %v\n", ret.software) - for _, attr := range msg.Attributes { - switch attr.Type { - case - stun.AttrXORMappedAddress, - stun.AttrOtherAddress, - //stun.AttrResponseOrigin, - stun.AttrMappedAddress, - stun.AttrSoftware: - break //nolint: staticcheck - default: - log.Debugf("\t%v (l=%v)\n", attr, attr.Length) - } - } - return ret -} diff --git a/nat/nat.go b/nat/nat.go deleted file mode 100644 index fc8602751..000000000 --- a/nat/nat.go +++ /dev/null @@ -1,83 +0,0 @@ -package nat - -import ( - "errors" - "fmt" - "github.com/pion/webrtc/v3" - log "github.com/sirupsen/logrus" - "github.com/wiretrustee/wiretrustee-signal/proto" - "time" -) - -// A set of tools to punch a UDP hole in NAT - -// Uses WebRTC to probe the Network and gather connection Candidates. -// It is important to request this method with multiple STUN server URLs because NAT type can be detected out of the multiple Probes (candidates) -func PunchHole(stuns []string) ([]*proto.Candidate, error) { - log.Debugf("starting to punch a NAT hole...") - - pConn, err := newPeerConnection(stuns) - if err != nil { - return nil, err - } - defer pConn.Close() - - var candidates []*proto.Candidate - pConn.OnICEConnectionStateChange(func(connectionState webrtc.ICEConnectionState) { - log.Debugf("ICE Connection State has changed: %s\n", connectionState.String()) - }) - pConn.OnICECandidate(func(candidate *webrtc.ICECandidate) { - log.Debugf("got new ICE candidate: %s", candidate) - if candidate != nil { - candidates = append(candidates, &proto.Candidate{ - //Address: fmt.Sprintf("%s:%d", candidate.Address, candidate.Port), - Proto: candidate.Protocol.String(), - }) - } - }) - - // Create an offer to send to the other process - offer, err := pConn.CreateOffer(nil) - if err != nil { - return nil, err - } - // Sets the LocalDescription, and starts our UDP listeners - // Note: this will start the gathering of ICE candidates - if err = pConn.SetLocalDescription(offer); err != nil { - panic(err) - } - - gatherComplete := webrtc.GatheringCompletePromise(pConn) - //wait for all the ICE candidates to be collected - select { - case <-gatherComplete: - - log.Debugf("collected %d candidates", len(candidates)) - - return candidates, nil - case <-time.After(time.Duration(10) * time.Second): //todo better timeout handling, or no timeout at all? - return nil, errors.New(fmt.Sprintf("timeout of %v seconds reached while waiting for hole punching", 10)) - } -} - -func newPeerConnection(stuns []string) (*webrtc.PeerConnection, error) { - - log.Debugf("creating new peer connection ...") - config := webrtc.Configuration{ - ICEServers: []webrtc.ICEServer{ - { - URLs: stuns, - }, - }, - } - settingEngine := webrtc.SettingEngine{} - settingEngine.SetNetworkTypes([]webrtc.NetworkType{ - webrtc.NetworkTypeUDP4, - }) - api := webrtc.NewAPI( - webrtc.WithSettingEngine(settingEngine), - ) - log.Debugf("created new peer connection") - - return api.NewPeerConnection(config) -} diff --git a/relay/client.go b/relay/client.go deleted file mode 100644 index faa9ec064..000000000 --- a/relay/client.go +++ /dev/null @@ -1,159 +0,0 @@ -package relay - -import ( - "fmt" - "github.com/pion/logging" - "github.com/pion/turn/v2" - log "github.com/sirupsen/logrus" - "net" -) - -//Client has no doc yet -type Client struct { - TurnC *turn.Client - // remote peer to reply to - peerAddr net.Addr - // local Wireguard connection - localWgConn net.Conn -} - -func (c *Client) Close() error { - c.TurnC.Close() - if c.localWgConn != nil { - err := c.localWgConn.Close() - if err != nil { - return err - } - } - - return nil -} - -func NewClient(turnAddr string, user string, pwd string) (*Client, error) { - // a local UDP proxy to forward Wireguard's packets to the relay server - // This endpoint should be specified in the Peer's Wireguard config - proxyConn, err := net.ListenPacket("udp4", "0.0.0.0:0") - if err != nil { - return nil, err - } - - cfg := &turn.ClientConfig{ - STUNServerAddr: turnAddr, - TURNServerAddr: turnAddr, - Conn: proxyConn, - Username: user, - Password: pwd, - Realm: "wiretrustee.com", - LoggerFactory: logging.NewDefaultLoggerFactory(), - } - - client, err := turn.NewClient(cfg) - if err != nil { - return nil, err - } - // Both, client and peer needs to listen to Turn packets - err = client.Listen() - - if err != nil { - return nil, err - } - log.Infof("local address %s", proxyConn.LocalAddr().String()) - return &Client{ - TurnC: client, - }, err -} - -// Start relaying packets: -// Incoming traffic from the relay sent by the other peer will be forwarded to local Wireguard -// Outgoing traffic from local Wireguard will be intercepted and forwarded back to relayed connection -// returns a relayed address (turn) to be used on the other side (peer) -func (c *Client) Start(remoteAddr string, wgPort int) (*net.UDPAddr, *net.UDPAddr, error) { - - udpRemoteAddr, err := net.ResolveUDPAddr("udp", remoteAddr) - if err != nil { - return nil, nil, err - } - - // Allocate a relay socket on the TURN server - relayConn, err := c.TurnC.Allocate() - if err != nil { - return nil, nil, err - } - // create a connection to a local Wireguard port to forward traffic to - c.localWgConn, err = net.Dial("udp", fmt.Sprintf("127.0.0.1:%d", +wgPort)) - if err != nil { - return nil, nil, err - } - - log.Infof("allocated a new relay address [%s]", relayConn.LocalAddr().String()) - - // read from relay and write to local Wireguard - c.relayPeerToLocalDst(relayConn, c.localWgConn) - // read from local Wireguard and write to relay - c.relayLocalDstToPeer(c.localWgConn, relayConn) - - // Punch a UDP hole for the relayConn by sending a data to the udpRemoteAddr. - // This will trigger a TURN client to generate a permission request to the - // TURN server. After this, packets from the IP address will be accepted by - // the TURN server. - _, err = relayConn.WriteTo([]byte("Hello"), udpRemoteAddr) - if err != nil { - return nil, nil, err - } - log.Infof("Punched a hole on [%s:%s]", udpRemoteAddr.IP, udpRemoteAddr.Port) - - relayAddr, err := net.ResolveUDPAddr("udp", relayConn.LocalAddr().String()) - if err != nil { - return nil, nil, err - } - - wgAddr, err := net.ResolveUDPAddr("udp", c.localWgConn.LocalAddr().String()) - if err != nil { - return nil, nil, err - } - - return relayAddr, wgAddr, nil -} - -func (c *Client) relayPeerToLocalDst(relayConn net.PacketConn, localConn net.Conn) { - go func() { - buf := make([]byte, 1500) - var n int - var err error - for { - n, c.peerAddr, err = relayConn.ReadFrom(buf) - if err != nil { - // log.Warnln("Error reading from peer: ", err.Error()) - continue - } - n, err = localConn.Write(buf[:n]) - if err != nil { - log.Warnln("Error writing to local destination: ", err.Error()) - } - } - }() -} - -func (c *Client) relayLocalDstToPeer(localConn net.Conn, relayConn net.PacketConn) { - go func() { - buf := make([]byte, 1500) - var n int - var err error - for { - n, err = localConn.Read(buf) - if err != nil { - // log.Warnln("Error reading from local destination: ", err.Error()) - continue - } - if c.peerAddr == nil { - log.Warnln("We didn't received any peer connection yet") - continue - } - // log.Infoln("Received message from Local: ", string(buf[:n])) - _, err = relayConn.WriteTo(buf[:n], c.peerAddr) - if err != nil { - log.Warnln("Error writing to peer: ", err.Error()) - } - } - }() -}