refactor: remove unused code

This commit is contained in:
braginini 2021-04-14 14:29:21 +02:00
parent a820d83a39
commit 028a860bec
3 changed files with 0 additions and 559 deletions

View File

@ -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
}

View File

@ -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)
}

View File

@ -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())
}
}
}()
}