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

Merge pull request #11 from Arceliar/bigmtu

Enable TCP support, switch to it by default, and increase MTU to 65535
This commit is contained in:
Arceliar 2018-02-11 13:34:10 -06:00 committed by GitHub
commit ec6d749b59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 21 additions and 293 deletions

View File

@ -43,6 +43,9 @@ In practice, you probably want to run this instead:
This keeps a persistent set of keys (and by extension, IP address) and gives you the option of editing the configuration file. This keeps a persistent set of keys (and by extension, IP address) and gives you the option of editing the configuration file.
If you want to use it as an overlay network on top of e.g. the internet, then you can do so by adding the remote devices domain/address and port (as a string, e.g. `"1.2.3.4:5678"`) to the list of `Peers` in the configuration file. If you want to use it as an overlay network on top of e.g. the internet, then you can do so by adding the remote devices domain/address and port (as a string, e.g. `"1.2.3.4:5678"`) to the list of `Peers` in the configuration file.
You can control whether or not it peers over TCP or UDP by adding `tcp:` or `udp:` to the start of the string, i.e. `"udp:1.2.3.4:5678"`.
It is currently configured to accept incoming TCP and UDP connections.
In the interest of testing the TCP machinery, it's set to create TCP connections for auto-peering (over link-local IPv6), and to use TCP by default if no transport is specified for a manually configured peer.
### Platforms ### Platforms

View File

@ -1,283 +0,0 @@
package main
import "bytes"
import "encoding/hex"
import "encoding/json"
import "flag"
import "fmt"
import "io/ioutil"
import "net"
import "os"
import "os/signal"
import "time"
import "regexp"
import _ "net/http/pprof"
import "net/http"
import "log"
import "runtime"
import "golang.org/x/net/ipv6"
import . "yggdrasil"
/**
* 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
}
type node struct {
core Core
sock *ipv6.PacketConn
}
func (n *node) init(cfg *nodeConfig, logger *log.Logger) {
boxPub, err := hex.DecodeString(cfg.BoxPub)
if err != nil {
panic(err)
}
boxPriv, err := hex.DecodeString(cfg.BoxPriv)
if err != nil {
panic(err)
}
sigPub, err := hex.DecodeString(cfg.SigPub)
if err != nil {
panic(err)
}
sigPriv, err := hex.DecodeString(cfg.SigPriv)
if err != nil {
panic(err)
}
n.core.DEBUG_init(boxPub, boxPriv, sigPub, sigPriv)
n.core.DEBUG_setLogger(logger)
ifceExpr, err := regexp.Compile(cfg.LinkLocal)
if err != nil {
panic(err)
}
n.core.DEBUG_setIfceExpr(ifceExpr)
logger.Println("Starting interface...")
n.core.DEBUG_setupAndStartGlobalTCPInterface(cfg.Listen)
logger.Println("Started interface")
logger.Println("Starting admin socket...")
n.core.DEBUG_setupAndStartAdminInterface(cfg.AdminListen)
logger.Println("Started admin socket")
go func() {
if len(cfg.Peers) == 0 {
return
}
for {
for _, p := range cfg.Peers {
n.core.DEBUG_addTCPConn(p)
time.Sleep(time.Second)
}
time.Sleep(time.Minute)
}
}()
}
func generateConfig() *nodeConfig {
core := Core{}
bpub, bpriv := core.DEBUG_newBoxKeys()
spub, spriv := core.DEBUG_newSigKeys()
cfg := nodeConfig{}
cfg.Listen = "[::]:0"
cfg.AdminListen = "localhost:9001"
cfg.BoxPub = hex.EncodeToString(bpub[:])
cfg.BoxPriv = hex.EncodeToString(bpriv[:])
cfg.SigPub = hex.EncodeToString(spub[:])
cfg.SigPriv = hex.EncodeToString(spriv[:])
cfg.Peers = []string{}
cfg.Multicast = true
cfg.LinkLocal = ""
cfg.IfName = "auto"
return &cfg
}
func doGenconf() string {
cfg := generateConfig()
bs, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
panic(err)
}
return string(bs)
}
var multicastAddr = "[ff02::114]:9001"
func (n *node) listen() {
groupAddr, err := net.ResolveUDPAddr("udp6", multicastAddr)
if err != nil {
panic(err)
}
bs := make([]byte, 2048)
for {
nBytes, rcm, fromAddr, err := n.sock.ReadFrom(bs)
if err != nil {
panic(err)
}
//if rcm == nil { continue } // wat
//fmt.Println("DEBUG:", "packet from:", fromAddr.String())
if rcm != nil {
// Windows can't set the flag needed to return a non-nil value here
// So only make these checks if we get something useful back
// TODO? Skip them always, I'm not sure if they're really needed...
if !rcm.Dst.IsLinkLocalMulticast() {
continue
}
if !rcm.Dst.Equal(groupAddr.IP) {
continue
}
}
anAddr := string(bs[:nBytes])
addr, err := net.ResolveTCPAddr("tcp6", anAddr)
if err != nil {
panic(err)
continue
} // Panic for testing, remove later
from := fromAddr.(*net.UDPAddr)
//fmt.Println("DEBUG:", "heard:", addr.IP.String(), "from:", from.IP.String())
if addr.IP.String() != from.IP.String() {
continue
}
addr.Zone = from.Zone
saddr := addr.String()
//if _, isIn := n.peers[saddr]; isIn { continue }
//n.peers[saddr] = struct{}{}
n.core.DEBUG_addTCPConn(saddr)
//fmt.Println("DEBUG:", "added multicast peer:", saddr)
}
}
func (n *node) announce() {
groupAddr, err := net.ResolveUDPAddr("udp6", multicastAddr)
if err != nil {
panic(err)
}
var anAddr net.TCPAddr
tcpAddr := n.core.DEBUG_getGlobalTCPAddr()
anAddr.Port = tcpAddr.Port
destAddr, err := net.ResolveUDPAddr("udp6", multicastAddr)
if err != nil {
panic(err)
}
for {
ifaces, err := net.Interfaces()
if err != nil {
panic(err)
}
for _, iface := range ifaces {
n.sock.JoinGroup(&iface, groupAddr)
//err := n.sock.JoinGroup(&iface, groupAddr)
//if err != nil { panic(err) }
addrs, err := iface.Addrs()
if err != nil {
panic(err)
}
for _, addr := range addrs {
addrIP, _, _ := net.ParseCIDR(addr.String())
if addrIP.To4() != nil {
continue
} // IPv6 only
if !addrIP.IsLinkLocalUnicast() {
continue
}
anAddr.IP = addrIP
anAddr.Zone = iface.Name
destAddr.Zone = iface.Name
msg := []byte(anAddr.String())
n.sock.WriteTo(msg, nil, destAddr)
break
}
time.Sleep(time.Second)
}
time.Sleep(time.Second)
}
}
var pprof = flag.Bool("pprof", false, "Run pprof, see http://localhost:6060/debug/pprof/")
var genconf = flag.Bool("genconf", false, "print a new config to stdout")
var useconf = flag.Bool("useconf", false, "read config from stdin")
var autoconf = flag.Bool("autoconf", false, "automatic mode (dynamic IP, peer with IPv6 neighbors)")
func main() {
flag.Parse()
var cfg *nodeConfig
switch {
case *autoconf:
cfg = generateConfig()
case *useconf:
config, err := ioutil.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
decoder := json.NewDecoder(bytes.NewReader(config))
cfg = generateConfig()
err = decoder.Decode(cfg)
if err != nil {
panic(err)
}
case *genconf:
fmt.Println(doGenconf())
default:
flag.PrintDefaults()
}
if cfg == nil {
return
}
logger := log.New(os.Stdout, "", log.Flags())
if *pprof {
runtime.SetBlockProfileRate(1)
go func() { log.Println(http.ListenAndServe("localhost:6060", nil)) }()
}
// Setup
logger.Println("Initializing...")
n := node{}
n.init(cfg, logger)
logger.Println("Starting tun...")
//n.core.DEBUG_startTun(cfg.IfName) // 1280, the smallest supported MTU
n.core.DEBUG_startTunWithMTU(cfg.IfName, 65535) // Largest supported MTU
defer func() {
logger.Println("Closing...")
n.core.DEBUG_stopTun()
}()
logger.Println("Started...")
if cfg.Multicast {
addr, err := net.ResolveUDPAddr("udp", multicastAddr)
if err != nil {
panic(err)
}
listenString := fmt.Sprintf("[::]:%v", addr.Port)
conn, err := net.ListenPacket("udp6", listenString)
if err != nil {
panic(err)
}
//defer conn.Close() // Let it close on its own when the application exits
n.sock = ipv6.NewPacketConn(conn)
if err = n.sock.SetControlMessage(ipv6.FlagDst, true); err != nil {
// Windows can't set this flag, so we need to handle it in other ways
//panic(err)
}
go n.listen()
go n.announce()
}
// Catch interrupt to exit gracefully
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill)
<-c
logger.Println("Stopping...")
}

View File

@ -319,7 +319,7 @@ func (iface *udpInterface) reader() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
const udp_chunkSize = 65535 const udp_chunkSize = 508 // Apparently the maximum guaranteed safe IPv4 size
func udp_decode(bs []byte) (chunks, chunk, count uint8, payload []byte) { func udp_decode(bs []byte) (chunks, chunk, count uint8, payload []byte) {
if len(bs) >= 3 { if len(bs) >= 3 {

View File

@ -71,7 +71,8 @@ func (n *node) init(cfg *nodeConfig, logger *log.Logger) {
} }
n.core.DEBUG_setIfceExpr(ifceExpr) n.core.DEBUG_setIfceExpr(ifceExpr)
logger.Println("Starting interface...") logger.Println("Starting interface...")
n.core.DEBUG_setupAndStartGlobalUDPInterface(cfg.Listen) 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
logger.Println("Started interface") logger.Println("Started interface")
logger.Println("Starting admin socket...") logger.Println("Starting admin socket...")
n.core.DEBUG_setupAndStartAdminInterface(cfg.AdminListen) n.core.DEBUG_setupAndStartAdminInterface(cfg.AdminListen)
@ -82,7 +83,14 @@ func (n *node) init(cfg *nodeConfig, logger *log.Logger) {
} }
for { for {
for _, p := range cfg.Peers { for _, p := range cfg.Peers {
n.core.DEBUG_maybeSendUDPKeys(p) switch {
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)
@ -144,7 +152,7 @@ func (n *node) listen() {
} }
} }
anAddr := string(bs[:nBytes]) anAddr := string(bs[:nBytes])
addr, err := net.ResolveUDPAddr("udp6", anAddr) addr, err := net.ResolveTCPAddr("tcp6", anAddr)
if err != nil { if err != nil {
panic(err) panic(err)
continue continue
@ -158,7 +166,7 @@ func (n *node) listen() {
saddr := addr.String() saddr := addr.String()
//if _, isIn := n.peers[saddr]; isIn { continue } //if _, isIn := n.peers[saddr]; isIn { continue }
//n.peers[saddr] = struct{}{} //n.peers[saddr] = struct{}{}
n.core.DEBUG_maybeSendUDPKeys(saddr) n.core.DEBUG_addTCPConn(saddr) // FIXME? can result in 2 connections per peer
//fmt.Println("DEBUG:", "added multicast peer:", saddr) //fmt.Println("DEBUG:", "added multicast peer:", saddr)
} }
} }
@ -168,9 +176,9 @@ func (n *node) announce() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
var anAddr net.UDPAddr var anAddr net.TCPAddr
udpAddr := n.core.DEBUG_getGlobalUDPAddr() tcpAddr := n.core.DEBUG_getGlobalTCPAddr()
anAddr.Port = udpAddr.Port anAddr.Port = tcpAddr.Port
destAddr, err := net.ResolveUDPAddr("udp6", multicastAddr) destAddr, err := net.ResolveUDPAddr("udp6", multicastAddr)
if err != nil { if err != nil {
panic(err) panic(err)
@ -249,8 +257,8 @@ func main() {
n := node{} n := node{}
n.init(cfg, logger) n.init(cfg, logger)
logger.Println("Starting tun...") logger.Println("Starting tun...")
n.core.DEBUG_startTun(cfg.IfName) // 1280, the smallest supported MTU //n.core.DEBUG_startTun(cfg.IfName) // 1280, the smallest supported MTU
//n.core.DEBUG_startTunWithMTU(cfg.IfName, 65535) // Largest supported MTU n.core.DEBUG_startTunWithMTU(cfg.IfName, 65535) // Largest supported MTU
defer func() { defer func() {
logger.Println("Closing...") logger.Println("Closing...")
n.core.DEBUG_stopTun() n.core.DEBUG_stopTun()