5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-12-23 12:15:39 +00:00

tor auto config

This commit is contained in:
Jeff Becker 2018-04-19 10:30:40 -04:00
parent 48ced483d6
commit 3c4fee0492
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05
7 changed files with 186 additions and 56 deletions

View File

@ -0,0 +1,29 @@
package config
/**
* This is a very crude wrapper around src/yggdrasil
* It can generate a new config (--genconf)
* It can read a config from stdin (--useconf)
* It can run with an automatic config (--autoconf)
*/
type NodeConfig struct {
Listen string
AdminListen string
Peers []string
BoxPub string
BoxPriv string
SigPub string
SigPriv string
Multicast bool
LinkLocal string
IfName string
IfTAPMode bool
IfMTU int
Net NetConfig
}
type NetConfig struct {
Tor TorConfig
I2P I2PConfig
}

View File

@ -0,0 +1,7 @@
package config
type I2PConfig struct {
Keyfile string
Addr string
Enabled bool
}

View File

@ -0,0 +1,11 @@
package config
/**
*tor specific configuration
*/
type TorConfig struct {
OnionKeyfile string
SocksAddr string
UseForAll bool
Enabled bool
}

View File

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

99
src/yggdrasil/dial.go Normal file
View File

@ -0,0 +1,99 @@
package yggdrasil
import (
"errors"
"golang.org/x/net/proxy"
"net"
"strings"
"time"
"yggdrasil/config"
)
type Dialer = proxy.Dialer
type muxedDialer struct {
conf config.NetConfig
tor Dialer
direct Dialer
}
type wrappedConn struct {
c net.Conn
raddr net.Addr
}
type wrappedAddr struct {
network string
addr string
}
func (a *wrappedAddr) Network() string {
return a.network
}
func (a *wrappedAddr) String() string {
return a.addr
}
func (c *wrappedConn) Write(data []byte) (int, error) {
return c.c.Write(data)
}
func (c *wrappedConn) Read(data []byte) (int, error) {
return c.c.Read(data)
}
func (c *wrappedConn) SetDeadline(t time.Time) error {
return c.c.SetDeadline(t)
}
func (c *wrappedConn) SetReadDeadline(t time.Time) error {
return c.c.SetReadDeadline(t)
}
func (c *wrappedConn) SetWriteDeadline(t time.Time) error {
return c.c.SetWriteDeadline(t)
}
func (c *wrappedConn) Close() error {
return c.c.Close()
}
func (c *wrappedConn) LocalAddr() net.Addr {
return c.c.LocalAddr()
}
func (c *wrappedConn) RemoteAddr() net.Addr {
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)
}
}
func NewDialer(c config.NetConfig) Dialer {
tor, _ := proxy.SOCKS5("tcp", c.Tor.SocksAddr, nil, proxy.Direct)
return &muxedDialer{
conf: c,
tor: tor,
direct: proxy.Direct,
}
}

View File

@ -19,9 +19,17 @@ import "bufio"
const tcp_msgSize = 2048 + 65535 // TODO figure out what makes sense
// wrapper function for non tcp/ip connections
func setNoDelay(c net.Conn, delay bool) {
tcp, ok := c.(*net.TCPConn)
if ok {
tcp.SetNoDelay(delay)
}
}
type tcpInterface struct {
core *Core
serv *net.TCPListener
serv net.Listener
mutex sync.Mutex // Protecting the below
calls map[string]struct{}
conns map[tcpInfo](chan struct{})
@ -30,30 +38,27 @@ type tcpInterface struct {
type tcpInfo struct {
box boxPubKey
sig sigPubKey
localAddr string // net.IPAddr.String(), not TCPAddr, don't care about port
remoteAddr string
localAddr net.Addr
remoteAddr net.Addr
}
func (iface *tcpInterface) init(core *Core, addr string) {
func (iface *tcpInterface) init(core *Core, addr string) (err error) {
iface.core = core
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
panic(err)
iface.serv, err = net.Listen("tcp", addr)
if err == nil {
iface.calls = make(map[string]struct{})
iface.conns = make(map[tcpInfo](chan struct{}))
go iface.listener()
}
iface.serv, err = net.ListenTCP("tcp", tcpAddr)
if err != nil {
panic(err)
}
iface.calls = make(map[string]struct{})
iface.conns = make(map[tcpInfo](chan struct{}))
go iface.listener()
return
}
func (iface *tcpInterface) listener() {
defer iface.serv.Close()
iface.core.log.Println("Listening for TCP on:", iface.serv.Addr().String())
for {
sock, err := iface.serv.AcceptTCP()
sock, err := iface.serv.Accept()
if err != nil {
panic(err)
}
@ -77,17 +82,16 @@ func (iface *tcpInterface) call(saddr string) {
}
iface.mutex.Unlock()
if !quit {
conn, err := net.DialTimeout("tcp", saddr, 6*time.Second)
conn, err := iface.core.Dialer.Dial("tcp", saddr)
if err != nil {
return
}
sock := conn.(*net.TCPConn)
iface.handler(sock)
iface.handler(conn)
}
}()
}
func (iface *tcpInterface) handler(sock *net.TCPConn) {
func (iface *tcpInterface) handler(sock net.Conn) {
defer sock.Close()
// Get our keys
keys := []byte{}
@ -127,18 +131,8 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
return
}
// Check if we already have a connection to this node, close and block if yes
local := sock.LocalAddr().(*net.TCPAddr)
laddr := net.IPAddr{
IP: local.IP,
Zone: local.Zone,
}
info.localAddr = laddr.String()
remote := sock.RemoteAddr().(*net.TCPAddr)
raddr := net.IPAddr{
IP: remote.IP,
Zone: remote.Zone,
}
info.remoteAddr = raddr.String()
info.localAddr = sock.LocalAddr()
info.remoteAddr = sock.RemoteAddr()
iface.mutex.Lock()
if blockChan, isIn := iface.conns[info]; isIn {
iface.mutex.Unlock()
@ -224,7 +218,7 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
util_putBytes(msg)
}
}
sock.SetNoDelay(true)
setNoDelay(sock, true)
go p.linkLoop(linkIn)
defer func() {
// Put all of our cleanup here...
@ -239,7 +233,7 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
p.core.peers.mutex.Unlock()
close(linkIn)
}()
them := sock.RemoteAddr().(*net.TCPAddr)
them := sock.RemoteAddr()
themNodeID := getNodeID(&info.box)
themAddr := address_addrForNodeID(themNodeID)
themAddrString := net.IP(themAddr[:]).String()
@ -250,7 +244,7 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
return
}
func (iface *tcpInterface) reader(sock *net.TCPConn, in func([]byte)) {
func (iface *tcpInterface) reader(sock net.Conn, in func([]byte)) {
bs := make([]byte, 2*tcp_msgSize)
frag := bs[:0]
for {

View File

@ -21,31 +21,13 @@ import "runtime"
import "golang.org/x/net/ipv6"
import . "yggdrasil"
import "yggdrasil"
import "yggdrasil/config"
import "github.com/kardianos/minwinsvc"
/**
* This is a very crude wrapper around src/yggdrasil
* It can generate a new config (--genconf)
* It can read a config from stdin (--useconf)
* It can run with an automatic config (--autoconf)
*/
type nodeConfig struct {
Listen string
AdminListen string
Peers []string
BoxPub string
BoxPriv string
SigPub string
SigPriv string
Multicast bool
LinkLocal string
IfName string
IfTAPMode bool
IfMTU int
}
type nodeConfig = config.NodeConfig
type Core = yggdrasil.Core
type node struct {
core Core
@ -76,6 +58,9 @@ func (n *node) init(cfg *nodeConfig, logger *log.Logger) {
panic(err)
}
n.core.DEBUG_setIfceExpr(ifceExpr)
n.core.Dialer = yggdrasil.NewDialer(cfg.Net)
logger.Println("Starting interface...")
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
@ -126,6 +111,10 @@ func generateConfig(isAutoconf bool) *nodeConfig {
cfg.IfName = core.DEBUG_GetTUNDefaultIfName()
cfg.IfMTU = core.DEBUG_GetTUNDefaultIfMTU()
cfg.IfTAPMode = core.DEBUG_GetTUNDefaultIfTAPMode()
cfg.Net.Tor.SocksAddr = "127.0.0.1:9050"
cfg.Net.Tor.UseForAll = false
cfg.Net.Tor.Enabled = true
return &cfg
}