mirror of
				https://gogs.blitter.com/RLabs/xs
				synced 2024-08-14 10:26:42 +00:00 
			
		
		
		
	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
							
								
									6b3154eeb6
								
							
						
					
					
						commit
						1a2e97706c
					
				
					 4 changed files with 144 additions and 25 deletions
				
			
		|  | @ -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 | ||||||
|  |  | ||||||
							
								
								
									
										129
									
								
								hkexnet/kcp.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								hkexnet/kcp.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue