mirror of https://gogs.blitter.com/RLabs/xs
				
				
				
			Uncoupled kcp-go UDP support by moving into hkexnet/kcp.go
TODO: cmdline param to set KCP symmetric key & salt at launch (consider also from a file to avoid putting inline in invocations, eg., init scripts) Signed-off-by: Russ Magee <rmagee@gmail.com>
This commit is contained in:
		
							parent
							
								
									d7dbcd8fdf
								
							
						
					
					
						commit
						c95794da1f
					
				| 
						 | 
					@ -25,7 +25,6 @@ package hkexnet
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"crypto/cipher"
 | 
						"crypto/cipher"
 | 
				
			||||||
	"crypto/sha1"
 | 
					 | 
				
			||||||
	"encoding/binary"
 | 
						"encoding/binary"
 | 
				
			||||||
	"encoding/hex"
 | 
						"encoding/hex"
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
| 
						 | 
					@ -41,9 +40,6 @@ import (
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kcp "github.com/xtaci/kcp-go"
 | 
					 | 
				
			||||||
	"golang.org/x/crypto/pbkdf2"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	hkex "blitter.com/go/herradurakex"
 | 
						hkex "blitter.com/go/herradurakex"
 | 
				
			||||||
	"blitter.com/go/hkexsh/logger"
 | 
						"blitter.com/go/hkexsh/logger"
 | 
				
			||||||
	kyber "git.schwanenlied.me/yawning/kyber.git"
 | 
						kyber "git.schwanenlied.me/yawning/kyber.git"
 | 
				
			||||||
| 
						 | 
					@ -699,9 +695,7 @@ func Dial(protocol string, ipport string, extensions ...string) (hc Conn, err er
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var c net.Conn
 | 
						var c net.Conn
 | 
				
			||||||
	if protocol == "kcp" {
 | 
						if protocol == "kcp" {
 | 
				
			||||||
		kcpKey := pbkdf2.Key([]byte("demo pass"), []byte("demo salt"), 1024, 32, sha1.New)
 | 
							c, err = kcpDial(ipport, extensions)
 | 
				
			||||||
		block, _ := kcp.NewNoneBlockCrypt(kcpKey)
 | 
					 | 
				
			||||||
		c, err = kcp.DialWithOptions(ipport, block, 10, 3)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return Conn{}, err
 | 
								return Conn{}, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -839,19 +833,16 @@ type HKExListener struct {
 | 
				
			||||||
// Listen for a connection
 | 
					// Listen for a connection
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// See go doc net.Listen
 | 
					// See go doc net.Listen
 | 
				
			||||||
func Listen(proto string, ipport string) (hl HKExListener, e error) {
 | 
					func Listen(proto string, ipport string, extensions ...string) (hl HKExListener, e error) {
 | 
				
			||||||
	if Log == nil {
 | 
						if Log == nil {
 | 
				
			||||||
		Init(false, "server", logger.LOG_DAEMON|logger.LOG_DEBUG)
 | 
							Init(false, "server", logger.LOG_DAEMON|logger.LOG_DEBUG)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kcpKey := pbkdf2.Key([]byte("demo pass"), []byte("demo salt"), 1024, 32, sha1.New)
 | 
					 | 
				
			||||||
	//var block kcp.BlockCrypt
 | 
					 | 
				
			||||||
	var lErr error
 | 
						var lErr error
 | 
				
			||||||
	var l net.Listener
 | 
						var l net.Listener
 | 
				
			||||||
	
 | 
					
 | 
				
			||||||
	if proto == "kcp" {
 | 
						if proto == "kcp" {
 | 
				
			||||||
		block, _ := kcp.NewNoneBlockCrypt(kcpKey)
 | 
							l, lErr = kcpListen(ipport, extensions)
 | 
				
			||||||
		l, lErr = kcp.ListenWithOptions(ipport, block, 10, 3)
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		l, lErr = net.Listen(proto, ipport)
 | 
							l, lErr = net.Listen(proto, ipport)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -886,11 +877,10 @@ func (hl HKExListener) Addr() net.Addr {
 | 
				
			||||||
func (hl *HKExListener) Accept() (hc Conn, err error) {
 | 
					func (hl *HKExListener) Accept() (hc Conn, err error) {
 | 
				
			||||||
	var c net.Conn
 | 
						var c net.Conn
 | 
				
			||||||
	if hl.proto == "kcp" {
 | 
						if hl.proto == "kcp" {
 | 
				
			||||||
		c, err = hl.l.(*kcp.Listener).AcceptKCP()
 | 
							c, err = hl.AcceptKCP()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return Conn{}, err
 | 
								return Conn{}, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		logger.LogDebug(fmt.Sprintln("[kcp.Listener Accepted]"))
 | 
							logger.LogDebug(fmt.Sprintln("[kcp.Listener Accepted]"))
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// Open raw Conn c
 | 
							// Open raw Conn c
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,129 @@
 | 
				
			||||||
 | 
					package hkexnet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/sha1"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"net"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"blitter.com/go/hkexsh/logger"
 | 
				
			||||||
 | 
						kcp "github.com/xtaci/kcp-go"
 | 
				
			||||||
 | 
						"golang.org/x/crypto/pbkdf2"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						KCP_NONE = iota
 | 
				
			||||||
 | 
						KCP_AES
 | 
				
			||||||
 | 
						KCP_BLOWFISH
 | 
				
			||||||
 | 
						KCP_CAST5
 | 
				
			||||||
 | 
						KCP_SM4
 | 
				
			||||||
 | 
						KCP_SALSA20
 | 
				
			||||||
 | 
						KCP_SIMPLEXOR
 | 
				
			||||||
 | 
						KCP_TEA
 | 
				
			||||||
 | 
						KCP_3DES
 | 
				
			||||||
 | 
						KCP_TWOFISH
 | 
				
			||||||
 | 
						KCP_XTEA
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// for github.com/xtaci/kcp-go BlockCrypt alg selection
 | 
				
			||||||
 | 
					type KCPAlg uint8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						kcpKeyBytes  []byte = []byte("SET THIS") // symmetric crypto key for KCP (github.com/xtaci/kcp-go) if used
 | 
				
			||||||
 | 
						kcpSaltBytes []byte = []byte("ALSO SET THIS")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getKCPalgnum(extensions []string) (k KCPAlg) {
 | 
				
			||||||
 | 
						k = KCP_AES // default
 | 
				
			||||||
 | 
						var s string
 | 
				
			||||||
 | 
						for _, s = range extensions {
 | 
				
			||||||
 | 
							switch s {
 | 
				
			||||||
 | 
							case "KCP_NONE":
 | 
				
			||||||
 | 
								k = KCP_NONE
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							case "KCP_AES":
 | 
				
			||||||
 | 
								k = KCP_AES
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							case "KCP_BLOWFISH":
 | 
				
			||||||
 | 
								k = KCP_BLOWFISH
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							case "KCP_CAST5":
 | 
				
			||||||
 | 
								k = KCP_CAST5
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							case "KCP_SM4":
 | 
				
			||||||
 | 
								k = KCP_SM4
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							case "KCP_SALSA20":
 | 
				
			||||||
 | 
								k = KCP_SALSA20
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							case "KCP_SIMPLEXOR":
 | 
				
			||||||
 | 
								k = KCP_SIMPLEXOR
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							case "KCP_TEA":
 | 
				
			||||||
 | 
								k = KCP_TEA
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							case "KCP_3DES":
 | 
				
			||||||
 | 
								k = KCP_3DES
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							case "KCP_TWOFISH":
 | 
				
			||||||
 | 
								k = KCP_TWOFISH
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							case "KCP_XTEA":
 | 
				
			||||||
 | 
								k = KCP_XTEA
 | 
				
			||||||
 | 
								break //out of for
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						logger.LogDebug(fmt.Sprintf("[KCP BlockCrypt '%s' activated]", s))
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SetKCPKeyAndSalt(key []byte, salt []byte) {
 | 
				
			||||||
 | 
						kcpKeyBytes = key
 | 
				
			||||||
 | 
						kcpSaltBytes = salt
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func _newKCPBlockCrypt(key []byte, extensions []string) (b kcp.BlockCrypt, e error) {
 | 
				
			||||||
 | 
						switch getKCPalgnum(extensions) {
 | 
				
			||||||
 | 
						case KCP_NONE:
 | 
				
			||||||
 | 
							return kcp.NewNoneBlockCrypt(key)
 | 
				
			||||||
 | 
						case KCP_AES:
 | 
				
			||||||
 | 
							return kcp.NewAESBlockCrypt(key)
 | 
				
			||||||
 | 
						case KCP_BLOWFISH:
 | 
				
			||||||
 | 
							return kcp.NewBlowfishBlockCrypt(key)
 | 
				
			||||||
 | 
						case KCP_CAST5:
 | 
				
			||||||
 | 
							return kcp.NewCast5BlockCrypt(key)
 | 
				
			||||||
 | 
						case KCP_SM4:
 | 
				
			||||||
 | 
							return kcp.NewSM4BlockCrypt(key)
 | 
				
			||||||
 | 
						case KCP_SALSA20:
 | 
				
			||||||
 | 
							return kcp.NewSalsa20BlockCrypt(key)
 | 
				
			||||||
 | 
						case KCP_SIMPLEXOR:
 | 
				
			||||||
 | 
							return kcp.NewSimpleXORBlockCrypt(key)
 | 
				
			||||||
 | 
						case KCP_TEA:
 | 
				
			||||||
 | 
							return kcp.NewTEABlockCrypt(key)
 | 
				
			||||||
 | 
						case KCP_3DES:
 | 
				
			||||||
 | 
							return kcp.NewTripleDESBlockCrypt(key)
 | 
				
			||||||
 | 
						case KCP_TWOFISH:
 | 
				
			||||||
 | 
							return kcp.NewTwofishBlockCrypt(key)
 | 
				
			||||||
 | 
						case KCP_XTEA:
 | 
				
			||||||
 | 
							return kcp.NewXTEABlockCrypt(key)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil, errors.New("Invalid KCP BlockCrypto specified")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func kcpDial(ipport string, extensions []string) (c net.Conn, err error) {
 | 
				
			||||||
 | 
						kcpKey := pbkdf2.Key(kcpKeyBytes, kcpSaltBytes, 1024, 32, sha1.New)
 | 
				
			||||||
 | 
						block, be := _newKCPBlockCrypt([]byte(kcpKey), extensions)
 | 
				
			||||||
 | 
						_ = be
 | 
				
			||||||
 | 
						return kcp.DialWithOptions(ipport, block, 10, 3)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func kcpListen(ipport string, extensions []string) (l net.Listener, err error) {
 | 
				
			||||||
 | 
						kcpKey := pbkdf2.Key(kcpKeyBytes, kcpSaltBytes, 1024, 32, sha1.New)
 | 
				
			||||||
 | 
						block, be := _newKCPBlockCrypt([]byte(kcpKey), extensions)
 | 
				
			||||||
 | 
						_ = be
 | 
				
			||||||
 | 
						return kcp.ListenWithOptions(ipport, block, 10, 3)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (hl *HKExListener) AcceptKCP() (c net.Conn, e error) {
 | 
				
			||||||
 | 
						return hl.l.(*kcp.Listener).AcceptKCP()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ var (
 | 
				
			||||||
	// wg controls when the goroutines handling client I/O complete
 | 
						// wg controls when the goroutines handling client I/O complete
 | 
				
			||||||
	wg sync.WaitGroup
 | 
						wg sync.WaitGroup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	kopt bool // set to use kcp (encrypted reliable UDP) instead of TCP
 | 
						kcpMode string // set to a valid KCP BlockCrypt alg tag to use rather than TCP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Log defaults to regular syslog output (no -d)
 | 
						// Log defaults to regular syslog output (no -d)
 | 
				
			||||||
	Log *logger.Writer
 | 
						Log *logger.Writer
 | 
				
			||||||
| 
						 | 
					@ -627,7 +627,7 @@ func main() {
 | 
				
			||||||
	flag.StringVar(&cipherAlg, "c", "C_AES_256", "`cipher` [\"C_AES_256\" | \"C_TWOFISH_128\" | \"C_BLOWFISH_64\" | \"C_CRYPTMT1\"]")
 | 
						flag.StringVar(&cipherAlg, "c", "C_AES_256", "`cipher` [\"C_AES_256\" | \"C_TWOFISH_128\" | \"C_BLOWFISH_64\" | \"C_CRYPTMT1\"]")
 | 
				
			||||||
	flag.StringVar(&hmacAlg, "m", "H_SHA256", "`hmac` [\"H_SHA256\" | \"H_SHA512\"]")
 | 
						flag.StringVar(&hmacAlg, "m", "H_SHA256", "`hmac` [\"H_SHA256\" | \"H_SHA512\"]")
 | 
				
			||||||
	flag.StringVar(&kexAlg, "k", "KEX_HERRADURA512", "`kex` [\"KEX_HERRADURA{256/512/1024/2048}\" | \"KEX_KYBER{512/768/1024}\" | \"KEX_NEWHOPE\" | \"KEX_NEWHOPE_SIMPLE\"]")
 | 
						flag.StringVar(&kexAlg, "k", "KEX_HERRADURA512", "`kex` [\"KEX_HERRADURA{256/512/1024/2048}\" | \"KEX_KYBER{512/768/1024}\" | \"KEX_NEWHOPE\" | \"KEX_NEWHOPE_SIMPLE\"]")
 | 
				
			||||||
	flag.BoolVar(&kopt, "K", false, "set true to use KCP (github.com/xtaci/kcp-go) reliable UDP instead of TCP")
 | 
						flag.StringVar(&kcpMode, "K", "unused", `set to one of ["KCP_NONE","KCP_AES", "KCP_BLOWFISH", "KCP_CAST5", "KCP_SM4", "KCP_SALSA20", "KCP_SIMPLEXOR", "KCP_TEA", "KCP_3DES", "KCP_TWOFISH", "KCP_XTEA"] to use KCP (github.com/xtaci/kcp-go) reliable UDP instead of TCP`)
 | 
				
			||||||
	flag.UintVar(&port, "p", 2000, "`port`")
 | 
						flag.UintVar(&port, "p", 2000, "`port`")
 | 
				
			||||||
	//flag.StringVar(&authCookie, "a", "", "auth cookie")
 | 
						//flag.StringVar(&authCookie, "a", "", "auth cookie")
 | 
				
			||||||
	flag.BoolVar(&chaffEnabled, "e", true, "enable chaff pkts")
 | 
						flag.BoolVar(&chaffEnabled, "e", true, "enable chaff pkts")
 | 
				
			||||||
| 
						 | 
					@ -821,12 +821,12 @@ func main() {
 | 
				
			||||||
			cmdStr = string(copySrc)
 | 
								cmdStr = string(copySrc)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
	proto := "tcp"
 | 
						proto := "tcp"
 | 
				
			||||||
	if kopt {
 | 
						if kcpMode != "unused" {
 | 
				
			||||||
		proto = "kcp"
 | 
								proto = "kcp"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	conn, err := hkexnet.Dial(proto, server, cipherAlg, hmacAlg, kexAlg)
 | 
						conn, err := hkexnet.Dial(proto, server, cipherAlg, hmacAlg, kexAlg, kcpMode)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		fmt.Println(err)
 | 
							fmt.Println(err)
 | 
				
			||||||
		exitWithStatus(3)
 | 
							exitWithStatus(3)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ var (
 | 
				
			||||||
	gitCommit   string // set in -ldflags by build
 | 
						gitCommit   string // set in -ldflags by build
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	useSysLogin bool
 | 
						useSysLogin bool
 | 
				
			||||||
	kopt bool // set to use kcp (encrypted reliable UDP) instead of TCP
 | 
						kcpMode string // set to a valid KCP BlockCrypt alg tag to use rather than TCP
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Log - syslog output (with no -d)
 | 
						// Log - syslog output (with no -d)
 | 
				
			||||||
	Log *logger.Writer
 | 
						Log *logger.Writer
 | 
				
			||||||
| 
						 | 
					@ -444,7 +444,7 @@ func main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	flag.BoolVar(&vopt, "v", false, "show version")
 | 
						flag.BoolVar(&vopt, "v", false, "show version")
 | 
				
			||||||
	flag.StringVar(&laddr, "l", ":2000", "interface[:port] to listen")
 | 
						flag.StringVar(&laddr, "l", ":2000", "interface[:port] to listen")
 | 
				
			||||||
	flag.BoolVar(&kopt, "K", false, "set true to use KCP (github.com/xtaci/kcp-go) reliable UDP instead of TCP")
 | 
						flag.StringVar(&kcpMode, "K", "unused", `set to one of ["KCP_NONE","KCP_AES", "KCP_BLOWFISH", "KCP_CAST5", "KCP_SM4", "KCP_SALSA20", "KCP_SIMPLEXOR", "KCP_TEA", "KCP_3DES", "KCP_TWOFISH", "KCP_XTEA"] to use KCP (github.com/xtaci/kcp-go) reliable UDP instead of TCP`)
 | 
				
			||||||
	flag.BoolVar(&useSysLogin, "L", false, "use system login")
 | 
						flag.BoolVar(&useSysLogin, "L", false, "use system login")
 | 
				
			||||||
	flag.BoolVar(&chaffEnabled, "e", true, "enable chaff pkts")
 | 
						flag.BoolVar(&chaffEnabled, "e", true, "enable chaff pkts")
 | 
				
			||||||
	flag.UintVar(&chaffFreqMin, "f", 100, "chaff pkt freq min (msecs)")
 | 
						flag.UintVar(&chaffFreqMin, "f", 100, "chaff pkt freq min (msecs)")
 | 
				
			||||||
| 
						 | 
					@ -508,10 +508,10 @@ func main() {
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	proto := "tcp"
 | 
						proto := "tcp"
 | 
				
			||||||
	if kopt {
 | 
						if kcpMode != "unused" {
 | 
				
			||||||
		proto = "kcp"
 | 
							proto = "kcp"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	l, err := hkexnet.Listen(proto, laddr)
 | 
						l, err := hkexnet.Listen(proto, laddr, kcpMode)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatal(err)
 | 
							log.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue