5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-22 20:00:27 +00:00

support socks proxy in peer url and decouple explicit tor/i2p routing

This commit is contained in:
Jeff Becker 2018-04-26 10:23:21 -04:00
parent 769b058004
commit 7756891510
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05
5 changed files with 74 additions and 61 deletions

View File

@ -19,7 +19,6 @@ type Core struct {
tun tunDevice tun tunDevice
admin admin admin admin
searches searches searches searches
Dialer Dialer
tcp *tcpInterface tcp *tcpInterface
udp *udpInterface udp *udpInterface
log *log.Logger log *log.Logger

View File

@ -8,9 +8,13 @@ package yggdrasil
import _ "golang.org/x/net/ipv6" // TODO put this somewhere better import _ "golang.org/x/net/ipv6" // TODO put this somewhere better
import "golang.org/x/net/proxy"
import "fmt" import "fmt"
import "net" import "net"
import "net/url"
import "log" import "log"
import "strings"
import "regexp" import "regexp"
// Core // Core
@ -307,6 +311,54 @@ func (c *Core) DEBUG_maybeSendUDPKeys(saddr string) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
func (c *Core) DEBUG_addPeer(addr string) {
u, err := url.Parse(addr)
if err != nil {
panic(err)
}
if len(u.Opaque) == 0 {
switch strings.ToLower(u.Scheme) {
case "tcp":
c.DEBUG_addTCPConn(u.Host)
case "udp":
c.DEBUG_maybeSendUDPKeys(u.Host)
case "socks":
c.DEBUG_addSOCKSConn(u.Host, u.Path[1:])
default:
panic("invalid peer: " + addr)
}
} else {
// no url scheme provided
addr = strings.ToLower(addr)
if strings.HasPrefix(addr, "udp:") {
c.DEBUG_maybeSendUDPKeys(addr[4:])
} else {
if strings.HasPrefix(addr, "tcp:") {
addr = addr[4:]
}
c.DEBUG_addTCPConn(addr)
}
}
}
func (c *Core) DEBUG_addSOCKSConn(socksaddr, peeraddr string) {
go func() {
dialer, err := proxy.SOCKS5("tcp", socksaddr, nil, proxy.Direct)
if err == nil {
conn, err := dialer.Dial("tcp", peeraddr)
if err == nil {
c.tcp.callWithConn(&wrappedConn{
c: conn,
raddr: &wrappedAddr{
network: "tcp",
addr: peeraddr,
},
})
}
}
}()
}
//* //*
func (c *Core) DEBUG_setupAndStartGlobalTCPInterface(addrport string) { func (c *Core) DEBUG_setupAndStartGlobalTCPInterface(addrport string) {
iface := tcpInterface{} iface := tcpInterface{}

View File

@ -1,23 +1,10 @@
package yggdrasil package yggdrasil
import ( import (
"errors"
"golang.org/x/net/proxy"
"net" "net"
"strings"
"time" "time"
"yggdrasil/config"
) )
type Dialer = proxy.Dialer
// muxedDialer implements proxy.Dialer (aka Dialer)
type muxedDialer struct {
conf config.NetConfig
tor Dialer
direct Dialer
}
// wrappedConn implements net.Conn // wrappedConn implements net.Conn
type wrappedConn struct { type wrappedConn struct {
c net.Conn c net.Conn
@ -69,39 +56,3 @@ func (c *wrappedConn) LocalAddr() net.Addr {
func (c *wrappedConn) RemoteAddr() net.Addr { func (c *wrappedConn) RemoteAddr() net.Addr {
return c.raddr return c.raddr
} }
func (d *muxedDialer) Dial(network, addr string) (net.Conn, error) {
host, _, _ := net.SplitHostPort(addr)
if d.conf.Tor.UseForAll || strings.HasSuffix(host, ".onion") {
if !d.conf.Tor.Enabled {
return nil, errors.New("tor not enabled")
}
c, err := d.tor.Dial(network, addr)
if err == nil {
c = &wrappedConn{
c: c,
raddr: &wrappedAddr{
network: network,
addr: addr,
},
}
}
return c, err
} else {
return d.direct.Dial(network, addr)
}
}
// NewDialer creates a Dialer from a NetConfig
func NewDialer(c config.NetConfig) Dialer {
if c.Tor.Enabled {
tor, _ := proxy.SOCKS5("tcp", c.Tor.SocksAddr, nil, proxy.Direct)
return &muxedDialer{
conf: c,
tor: tor,
direct: proxy.Direct,
}
} else {
return proxy.Direct
}
}

View File

@ -66,6 +66,26 @@ func (iface *tcpInterface) listener() {
} }
} }
func (iface *tcpInterface) callWithConn(conn net.Conn) {
go func() {
raddr := conn.RemoteAddr().String()
iface.mutex.Lock()
_, isIn := iface.calls[raddr]
iface.mutex.Unlock()
if !isIn {
iface.mutex.Lock()
iface.calls[raddr] = struct{}{}
iface.mutex.Unlock()
defer func() {
iface.mutex.Lock()
delete(iface.calls, raddr)
iface.mutex.Unlock()
}()
iface.handler(conn)
}
}()
}
func (iface *tcpInterface) call(saddr string) { func (iface *tcpInterface) call(saddr string) {
go func() { go func() {
quit := false quit := false
@ -82,7 +102,7 @@ func (iface *tcpInterface) call(saddr string) {
} }
iface.mutex.Unlock() iface.mutex.Unlock()
if !quit { if !quit {
conn, err := iface.core.Dialer.Dial("tcp", saddr) conn, err := net.Dial("tcp", saddr)
if err != nil { if err != nil {
return return
} }

View File

@ -59,8 +59,6 @@ func (n *node) init(cfg *nodeConfig, logger *log.Logger) {
} }
n.core.DEBUG_setIfceExpr(ifceExpr) n.core.DEBUG_setIfceExpr(ifceExpr)
n.core.Dialer = yggdrasil.NewDialer(cfg.Net)
logger.Println("Starting interface...") logger.Println("Starting interface...")
n.core.DEBUG_setupAndStartGlobalTCPInterface(cfg.Listen) // Listen for peers on TCP n.core.DEBUG_setupAndStartGlobalTCPInterface(cfg.Listen) // Listen for peers on TCP
n.core.DEBUG_setupAndStartGlobalUDPInterface(cfg.Listen) // Also listen on UDP, TODO allow separate configuration for ip/port to listen on each of these n.core.DEBUG_setupAndStartGlobalUDPInterface(cfg.Listen) // Also listen on UDP, TODO allow separate configuration for ip/port to listen on each of these
@ -74,14 +72,7 @@ func (n *node) init(cfg *nodeConfig, logger *log.Logger) {
} }
for { for {
for _, p := range cfg.Peers { for _, p := range cfg.Peers {
switch { n.core.DEBUG_addPeer(p)
case len(p) >= 4 && p[:4] == "udp:":
n.core.DEBUG_maybeSendUDPKeys(p[4:])
case len(p) >= 4 && p[:4] == "tcp:":
n.core.DEBUG_addTCPConn(p[4:])
default:
n.core.DEBUG_addTCPConn(p)
}
time.Sleep(time.Second) time.Sleep(time.Second)
} }
time.Sleep(time.Minute) time.Sleep(time.Minute)