From dc4d42007b5998f927c0295b069651abadbeddab Mon Sep 17 00:00:00 2001 From: xtaci Date: Mon, 23 Jan 2017 22:30:54 +0800 Subject: [PATCH] init --- .github/ISSUE_TEMPLATE | 27 +++ .gitignore | 26 +++ .travis.yml | 16 ++ Dockerfile | 8 + LICENSE.md | 21 ++ README.md | 245 +++++++++++++++++++++ build-release.sh | 54 +++++ client/config.go | 44 ++++ client/main.go | 487 +++++++++++++++++++++++++++++++++++++++++ client/signal.go | 28 +++ fast.png | Bin 0 -> 25395 bytes kcptun.png | Bin 0 -> 20098 bytes layeredparams.png | Bin 0 -> 60800 bytes logo-small.png | Bin 0 -> 6929 bytes logo.png | Bin 0 -> 4639 bytes rs.png | Bin 0 -> 25544 bytes server/config.go | 42 ++++ server/main.go | 405 ++++++++++++++++++++++++++++++++++ server/signal.go | 28 +++ 19 files changed, 1431 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 Dockerfile create mode 100644 LICENSE.md create mode 100644 README.md create mode 100755 build-release.sh create mode 100644 client/config.go create mode 100644 client/main.go create mode 100644 client/signal.go create mode 100644 fast.png create mode 100644 kcptun.png create mode 100644 layeredparams.png create mode 100644 logo-small.png create mode 100644 logo.png create mode 100644 rs.png create mode 100644 server/config.go create mode 100644 server/main.go create mode 100644 server/signal.go diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE new file mode 100644 index 0000000..b45d668 --- /dev/null +++ b/.github/ISSUE_TEMPLATE @@ -0,0 +1,27 @@ +问问题前先搜索ISSUE,并搞清楚下面的问题: + +1. 检查 ```-key xxx``` 至少三遍, ***保证***两边一致。 +2. 保证```-nocomp, -datashard, -parityshard, -key, -crypt```两边一致。 +3. 是否在服务器端,正确设定了转发的目标服务器地址 ***--target***。 +4. 如果第3条不确定,尝试在服务器上telnet target port试试。 +5. 防火墙是否关闭了UDP通信。 +6. 两端的版本是否一致? +7. 是不是最新版本? +8. 两端分别是什么操作系统? +9. 两端的输出日志是什么? + +Before firing issue, make sure you figured out the following common questions. + +PLEASE DO SEARCH FIRST. + +1. Check your ```-key xxx``` for at least 3 times, ***MAKE SURE*** both sides share the same secret. +2. ```-nocomp, -datashard, -parityshard, -key, -crypt``` ***must be the same*** on both side. +3. Did you correctly set the ***-target*** on the server side? +4. ***MAKE SURE*** ```telnet target port``` on your server successful(don't ask me why couldn't). +5. Does your ***firewall allows UDP*** communications? (including your ISP Cable-Modem) +6. Are you using the **same version** for both client & server +7. Are you using the **latest release**? +8. Which **OS** do you use? +9. Which end for this issue related to, **client or server**? + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..389256f --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof +client/client +server/server diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3961fc3 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: go +go: + - 1.6 +before_install: + - go get github.com/mattn/goveralls + - go get golang.org/x/tools/cmd/cover +install: + - go get github.com/xtaci/kcptun/client + - go get github.com/xtaci/kcptun/server +before_script: +script: + - cd $HOME/gopath/src/github.com/xtaci/kcptun/client + - $HOME/gopath/bin/goveralls -service=travis-ci + - cd $HOME/gopath/src/github.com/xtaci/kcptun/server + - $HOME/gopath/bin/goveralls -service=travis-ci + - exit 0 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..42a3d1f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,8 @@ +FROM golang:alpine +MAINTAINER xtaci +RUN apk update && \ + apk upgrade && \ + apk add git +RUN go get github.com/xtaci/kcptun/client && go get github.com/xtaci/kcptun/server +EXPOSE 29900/udp +EXPOSE 12948 diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..88a8eea --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Daniel Fu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..98d23b9 --- /dev/null +++ b/README.md @@ -0,0 +1,245 @@ +# kcptun +[![Release][1]][2] [![Powered][7]][8] [![Build Status][3]][4] [![Go Report Card][5]][6] +[1]: https://img.shields.io/github/release/xtaci/kcptun.svg +[2]: https://github.com/xtaci/kcptun/releases/latest +[3]: https://travis-ci.org/xtaci/kcptun.svg?branch=master +[4]: https://travis-ci.org/xtaci/kcptun +[5]: https://goreportcard.com/badge/github.com/xtaci/kcptun +[6]: https://goreportcard.com/report/github.com/xtaci/kcptun +[7]: https://img.shields.io/badge/KCP-Powered-blue.svg +[8]: https://github.com/skywind3000/kcp + +A tool for converting tcp stream into kcp+udp stream, :zap: ***[download address](https://github.com/xtaci/kcptun/releases/latest)***:zap: + +![kcptun](kcptun.png) + +***kcptun is based on [kcp-go](https://github.com/xtaci/kcp-go)*** + +### *QuickStart* :lollipop: +Client, server, respectively, download the corresponding platform binary compression package, and extract, through the following command to start port forwarding. +``` +Server: ./server_linux_amd64 -t "SERVER_IP:8388" -l ":4000" -mode fast2 +Client: ./client_darwin_amd64 -r "SERVER_IP:4000" -l ":8388" -mode fast2 +``` +The above command can establish 8388/tcp port forwarding (through 4000/udp port). + + +### *Performance* :lollipop: +fast.com +* Speed tested with: https://fast.com +* WAN Link Speed: 100M ADSL +* WIFI: 5GHz TL-WDR3320 + + +### *Usage* :lollipop: +Help output under MacOS X: +``` +$ ./client_darwin_amd64 -h +NAME: + kcptun - client(with SMUX) + +USAGE: + client_darwin_amd64 [global options] command [command options] [arguments...] + +VERSION: + 20170120 + +COMMANDS: + help, h Shows a list of commands or help for one command + +GLOBAL OPTIONS: + --localaddr value, -l value local listen address (default: ":12948") + --remoteaddr value, -r value kcp server address (default: "vps:29900") + --key value pre-shared secret between client and server (default: "it's a secrect") [$KCPTUN_KEY] + --crypt value aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none (default: "aes") + --mode value profiles: fast3, fast2, fast, normal (default: "fast") + --conn value set num of UDP connections to server (default: 1) + --autoexpire value set auto expiration time(in seconds) for a single UDP connection, 0 to disable (default: 0) + --mtu value set maximum transmission unit for UDP packets (default: 1350) + --sndwnd value set send window size(num of packets) (default: 128) + --rcvwnd value set receive window size(num of packets) (default: 512) + --datashard value, --ds value set reed-solomon erasure coding - datashard (default: 10) + --parityshard value, --ps value set reed-solomon erasure coding - parityshard (default: 3) + --dscp value set DSCP(6bit) (default: 0) + --nocomp disable compression + --snmplog value collect snmp to file, aware of timeformat in golang, like: ./snmp-20060102.log + --snmpperiod value snmp collect period, in seconds (default: 60) + --log value specify a log file to output, default goes to stderr + -c value config from json file, which will override the command from shell + --help, -h show help + --version, -v print the version + +$ ./server_darwin_amd64 -h +NAME: + kcptun - server(with SMUX) + +USAGE: + server_darwin_amd64 [global options] command [command options] [arguments...] + +VERSION: + 20170120 + +COMMANDS: + help, h Shows a list of commands or help for one command + +GLOBAL OPTIONS: + --listen value, -l value kcp server listen address (default: ":29900") + --target value, -t value target server address (default: "127.0.0.1:12948") + --key value pre-shared secret between client and server (default: "it's a secrect") [$KCPTUN_KEY] + --crypt value aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none (default: "aes") + --mode value profiles: fast3, fast2, fast, normal (default: "fast") + --mtu value set maximum transmission unit for UDP packets (default: 1350) + --sndwnd value set send window size(num of packets) (default: 1024) + --rcvwnd value set receive window size(num of packets) (default: 1024) + --datashard value, --ds value set reed-solomon erasure coding - datashard (default: 10) + --parityshard value, --ps value set reed-solomon erasure coding - parityshard (default: 3) + --dscp value set DSCP(6bit) (default: 0) + --nocomp disable compression + --snmplog value collect snmp to file, aware of timeformat in golang, like: ./snmp-20060102.log + --snmpperiod value snmp collect period, in seconds (default: 60) + --log value specify a log file to output, default goes to stderr + -c value config from json file, which will override the command from shell + --help, -h show help + --version, -v print the version +``` + +#### *Parameters by Layers* :lollipop: + +

params

+ +### *Parameters* :lollipop: + +***Both sides must agree on the following parameters:*** +* datashard +* parityshard +* nocomp +* key +* crypt + +other parameters can be set independently. + +*How to optimize*: +> Step 1:Increase client rcvwnd & server sndwnd simultaneously & gradually。 +> Step 2:Try download something and observer, if the bandwidth usage is close the limit then stop, otherwise goto step 1. + +***NOTICE: if too much retranmission happens, it's quite possible the windows are too large*** + +### *Embeded Mode* :lollipop: + +Latency: +*fast3 >* ***[fast2]*** *> fast > normal > default* +Payload Ratio: +*default > normal > fast >* ***[fast2]*** *> fast3* +Parameters in middle is balanced for latency & payload ratio, the faster you get the more wasteful you are. +Manual control is supported with hidden parameters, you must understand KCP protocol before doing this. +``` + -mode manual -nodelay 1 -resend 2 -nc 1 -interval 20 +``` +I suggest fast2 for high-loss network, normal for low-loss network. + +### *Forward Error Correction* :lollipop: + +In coding theory, the Reed–Solomon code belongs to the class of non-binary cyclic error-correcting codes. The Reed–Solomon code is based on univariate polynomials over finite fields. + +It is able to detect and correct multiple symbol errors. By adding t check symbols to the data, a Reed–Solomon code can detect any combination of up to t erroneous symbols, or correct up to ⌊t/2⌋ symbols. As an erasure code, it can correct up to t known erasures, or it can detect and correct combinations of errors and erasures. Furthermore, Reed–Solomon codes are suitable as multiple-burst bit-error correcting codes, since a sequence of b + 1 consecutive bit errors can affect at most two symbols of size b. The choice of t is up to the designer of the code, and may be selected within wide limits. + +![reed-solomon](rs.png) + +Setting parameters of RS-Code with ```-datashard m -parityshard n``` + +### *DSCP* :lollipop: + +Differentiated services or DiffServ is a computer networking architecture that specifies a simple, scalable and coarse-grained mechanism for classifying and managing network traffic and providing quality of service (QoS) on modern IP networks. DiffServ can, for example, be used to provide low-latency to critical network traffic such as voice or streaming media while providing simple best-effort service to non-critical services such as web traffic or file transfers. + +DiffServ uses a 6-bit differentiated services code point (DSCP) in the 8-bit differentiated services field (DS field) in the IP header for packet classification purposes. The DS field and ECN field replace the outdated IPv4 TOS field.[1] + +setting each side with ```-dscp value```. + + +### *Security* :lollipop: + +No matter what encryption you are using for application layer, if you specify ```-crypt none``` to kcptun, +the header will be ***PLAINTEXT*** to everyone; I suggest ```-crypt aes-128``` for encryption at least . + +NOTICE: ```-crypt xor``` is also insecure, do not use this unless you know what you are doing. + +### *Memory Control* :lollipop: + +Routers, mobile devices are sensitive to memory consumption; by setting GOGC environment(eg: GOGC=20) will lower memory consumption. +Reference: https://blog.golang.org/go15gc + +### *Traffic Control* :lollipop: + +***Intended audience : for those server's bandwidth is quite limited.*** + +Example: To limit outgoing bandwidth to 32mbit/s on server. +``` +root@kcptun:~# cat tc.sh +tc qdisc del dev eth0 root +tc qdisc add dev eth0 root handle 1: htb +tc class add dev eth0 parent 1: classid 1:1 htb rate 32mbit +tc filter add dev eth0 protocol ip parent 1:0 prio 1 handle 10 fw flowid 1:1 +iptables -t mangle -A POSTROUTING -o eth0 -j MARK --set-mark 10 +root@kcptun:~# +``` + +### *Snappy Stream Compression* :lollipop: + +> Snappy is a compression/decompression library. It does not aim for maximum +> compression, or compatibility with any other compression library; instead, +> it aims for very high speeds and reasonable compression. For instance, +> compared to the fastest mode of zlib, Snappy is an order of magnitude faster +> for most inputs, but the resulting compressed files are anywhere from 20% to +> 100% bigger. + +> Reference: http://google.github.io/snappy/ + +disable compression by setting ```-nocomp``` on both side. + +> Tips: Turning off compression may reduce latency. + +### *SNMP* :lollipop: + +```go +// Snmp defines network statistics indicator +type Snmp struct { + BytesSent uint64 // payload bytes sent + BytesReceived uint64 + MaxConn uint64 + ActiveOpens uint64 + PassiveOpens uint64 + CurrEstab uint64 + InErrs uint64 + InCsumErrors uint64 // checksum errors + InSegs uint64 + OutSegs uint64 + OutBytes uint64 // udp bytes sent + RetransSegs uint64 + FastRetransSegs uint64 + EarlyRetransSegs uint64 + LostSegs uint64 + RepeatSegs uint64 + FECRecovered uint64 + FECErrs uint64 + FECSegs uint64 // fec segments received +} +``` + +Sending a signal by ```kill -SIGUSR1 pid``` will give SNMP information for KCP,useful for fine-grained adjustment. +Of which ```RetransSegs,FastRetransSegs,LostSegs,OutSegs``` is the most useful. + +### *References* :paperclip: + +1. https://github.com/skywind3000/kcp -- KCP - A Fast and Reliable ARQ Protocol. +2. https://github.com/klauspost/reedsolomon -- Reed-Solomon Erasure Coding in Go. +3. https://en.wikipedia.org/wiki/Differentiated_services -- DSCP. +4. http://google.github.io/snappy/ -- A fast compressor/decompressor. +5. https://www.backblaze.com/blog/reed-solomon/ -- Reed-Solomon Explained. +6. http://www.qualcomm.cn/products/raptorq -- RaptorQ Forward Error Correction Scheme for Object Delivery. +7. https://en.wikipedia.org/wiki/PBKDF2 -- Key stretching. +8. http://blog.appcanary.com/2016/encrypt-or-compress.html -- Should you encrypt or compress first? +9. https://github.com/hashicorp/yamux -- Connection multiplexing library. +10. https://tools.ietf.org/html/rfc6937 -- Proportional Rate Reduction for TCP. +11. https://tools.ietf.org/html/rfc5827 -- Early Retransmit for TCP and Stream Control Transmission Protocol (SCTP). +12. http://http2.github.io/ -- What is HTTP/2? +13. http://www.lartc.org/ -- Linux Advanced Routing & Traffic Control diff --git a/build-release.sh b/build-release.sh new file mode 100755 index 0000000..4a935b9 --- /dev/null +++ b/build-release.sh @@ -0,0 +1,54 @@ +#!/bin/bash +MD5='md5sum' +unamestr=`uname` +if [[ "$unamestr" == 'Darwin' ]]; then + MD5='md5' +fi + +UPX=false +if hash upx 2>/dev/null; then + UPX=true +fi + +VERSION=`date -u +%Y%m%d` +LDFLAGS="-X main.VERSION=$VERSION -s -w" +GCFLAGS="" + +OSES=(linux darwin windows freebsd) +ARCHS=(amd64 386) +for os in ${OSES[@]}; do + for arch in ${ARCHS[@]}; do + suffix="" + if [ "$os" == "windows" ] + then + suffix=".exe" + fi + env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o client_${os}_${arch}${suffix} github.com/xtaci/kcptun/client + env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o server_${os}_${arch}${suffix} github.com/xtaci/kcptun/server + if $UPX; then upx -9 client_${os}_${arch}${suffix} server_${os}_${arch}${suffix};fi + tar -zcf kcptun-${os}-${arch}-$VERSION.tar.gz client_${os}_${arch}${suffix} server_${os}_${arch}${suffix} + $MD5 kcptun-${os}-${arch}-$VERSION.tar.gz + done +done + +# ARM +ARMS=(5 6 7) +for v in ${ARMS[@]}; do + env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=$v go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o client_linux_arm$v github.com/xtaci/kcptun/client + env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=$v go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o server_linux_arm$v github.com/xtaci/kcptun/server +done +if $UPX; then upx -9 client_linux_arm* server_linux_arm*;fi +tar -zcf kcptun-linux-arm-$VERSION.tar.gz client_linux_arm* server_linux_arm* +$MD5 kcptun-linux-arm-$VERSION.tar.gz + +#MIPS32LE +env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o client_linux_mipsle github.com/xtaci/kcptun/client +env CGO_ENABLED=0 GOOS=linux GOARCH=mipsle go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o server_linux_mipsle github.com/xtaci/kcptun/server +env CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o client_linux_mips github.com/xtaci/kcptun/client +env CGO_ENABLED=0 GOOS=linux GOARCH=mips go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o server_linux_mips github.com/xtaci/kcptun/server + +if $UPX; then upx -9 client_linux_mips* server_linux_mips*;fi +tar -zcf kcptun-linux-mipsle-$VERSION.tar.gz client_linux_mipsle server_linux_mipsle +tar -zcf kcptun-linux-mips-$VERSION.tar.gz client_linux_mips server_linux_mips +$MD5 kcptun-linux-mipsle-$VERSION.tar.gz +$MD5 kcptun-linux-mips-$VERSION.tar.gz diff --git a/client/config.go b/client/config.go new file mode 100644 index 0000000..faad77c --- /dev/null +++ b/client/config.go @@ -0,0 +1,44 @@ +package main + +import ( + "encoding/json" + "os" +) + +// Config for client +type Config struct { + LocalAddr string `json:"localaddr"` + RemoteAddr string `json:"remoteaddr"` + Key string `json:"key"` + Crypt string `json:"crypt"` + Mode string `json:"mode"` + Conn int `json:"conn"` + AutoExpire int `json:"autoexpire"` + MTU int `json:"mtu"` + SndWnd int `json:"sndwnd"` + RcvWnd int `json:"rcvwnd"` + DataShard int `json:"datashard"` + ParityShard int `json:"parityshard"` + DSCP int `json:"dscp"` + NoComp bool `json:"nocomp"` + AckNodelay bool `json:"acknodelay"` + NoDelay int `json:"nodelay"` + Interval int `json:"interval"` + Resend int `json:"resend"` + NoCongestion int `json:"nc"` + SockBuf int `json:"sockbuf"` + KeepAlive int `json:"keepalive"` + Log string `json:"log"` + SnmpLog string `json:"snmplog"` + SnmpPeriod int `json:"snmpperiod"` +} + +func parseJSONConfig(config *Config, path string) error { + file, err := os.Open(path) // For read access. + if err != nil { + return err + } + defer file.Close() + + return json.NewDecoder(file).Decode(config) +} diff --git a/client/main.go b/client/main.go new file mode 100644 index 0000000..dfc4d76 --- /dev/null +++ b/client/main.go @@ -0,0 +1,487 @@ +package main + +import ( + "crypto/sha1" + "encoding/csv" + "fmt" + "io" + "log" + "math/rand" + "net" + "os" + "time" + + "golang.org/x/crypto/pbkdf2" + + "github.com/golang/snappy" + "github.com/pkg/errors" + "github.com/urfave/cli" + kcp "github.com/xtaci/kcp-go" + "github.com/xtaci/smux" +) + +var ( + // VERSION is injected by buildflags + VERSION = "SELFBUILD" + // SALT is use for pbkdf2 key expansion + SALT = "kcp-go" +) + +type compStream struct { + conn net.Conn + w *snappy.Writer + r *snappy.Reader +} + +func (c *compStream) Read(p []byte) (n int, err error) { + return c.r.Read(p) +} + +func (c *compStream) Write(p []byte) (n int, err error) { + n, err = c.w.Write(p) + err = c.w.Flush() + return n, err +} + +func (c *compStream) Close() error { + return c.conn.Close() +} + +func newCompStream(conn net.Conn) *compStream { + c := new(compStream) + c.conn = conn + c.w = snappy.NewBufferedWriter(conn) + c.r = snappy.NewReader(conn) + return c +} + +func handleClient(sess *smux.Session, p1 io.ReadWriteCloser) { + p2, err := sess.OpenStream() + if err != nil { + return + } + + log.Println("stream opened") + defer log.Println("stream closed") + defer p1.Close() + defer p2.Close() + + // start tunnel + p1die := make(chan struct{}) + go func() { io.Copy(p1, p2); close(p1die) }() + + p2die := make(chan struct{}) + go func() { io.Copy(p2, p1); close(p2die) }() + + // wait for tunnel termination + select { + case <-p1die: + case <-p2die: + } +} + +func checkError(err error) { + if err != nil { + log.Printf("%+v\n", err) + os.Exit(-1) + } +} + +func main() { + rand.Seed(int64(time.Now().Nanosecond())) + if VERSION == "SELFBUILD" { + // add more log flags for debugging + log.SetFlags(log.LstdFlags | log.Lshortfile) + } + myApp := cli.NewApp() + myApp.Name = "kcptun" + myApp.Usage = "client(with SMUX)" + myApp.Version = VERSION + myApp.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "localaddr,l", + Value: ":12948", + Usage: "local listen address", + }, + cli.StringFlag{ + Name: "remoteaddr, r", + Value: "vps:29900", + Usage: "kcp server address", + }, + cli.StringFlag{ + Name: "key", + Value: "it's a secrect", + Usage: "pre-shared secret between client and server", + EnvVar: "KCPTUN_KEY", + }, + cli.StringFlag{ + Name: "crypt", + Value: "aes", + Usage: "aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none", + }, + cli.StringFlag{ + Name: "mode", + Value: "fast", + Usage: "profiles: fast3, fast2, fast, normal", + }, + cli.IntFlag{ + Name: "conn", + Value: 1, + Usage: "set num of UDP connections to server", + }, + cli.IntFlag{ + Name: "autoexpire", + Value: 0, + Usage: "set auto expiration time(in seconds) for a single UDP connection, 0 to disable", + }, + cli.IntFlag{ + Name: "mtu", + Value: 1350, + Usage: "set maximum transmission unit for UDP packets", + }, + cli.IntFlag{ + Name: "sndwnd", + Value: 128, + Usage: "set send window size(num of packets)", + }, + cli.IntFlag{ + Name: "rcvwnd", + Value: 512, + Usage: "set receive window size(num of packets)", + }, + cli.IntFlag{ + Name: "datashard,ds", + Value: 10, + Usage: "set reed-solomon erasure coding - datashard", + }, + cli.IntFlag{ + Name: "parityshard,ps", + Value: 3, + Usage: "set reed-solomon erasure coding - parityshard", + }, + cli.IntFlag{ + Name: "dscp", + Value: 0, + Usage: "set DSCP(6bit)", + }, + cli.BoolFlag{ + Name: "nocomp", + Usage: "disable compression", + }, + cli.BoolFlag{ + Name: "acknodelay", + Usage: "flush ack immediately when a packet is received", + Hidden: true, + }, + cli.IntFlag{ + Name: "nodelay", + Value: 0, + Hidden: true, + }, + cli.IntFlag{ + Name: "interval", + Value: 40, + Hidden: true, + }, + cli.IntFlag{ + Name: "resend", + Value: 0, + Hidden: true, + }, + cli.IntFlag{ + Name: "nc", + Value: 0, + Hidden: true, + }, + cli.IntFlag{ + Name: "sockbuf", + Value: 4194304, // socket buffer size in bytes + Hidden: true, + }, + cli.IntFlag{ + Name: "keepalive", + Value: 10, // nat keepalive interval in seconds + Hidden: true, + }, + cli.StringFlag{ + Name: "snmplog", + Value: "", + Usage: "collect snmp to file, aware of timeformat in golang, like: ./snmp-20060102.log", + }, + cli.IntFlag{ + Name: "snmpperiod", + Value: 60, + Usage: "snmp collect period, in seconds", + }, + cli.StringFlag{ + Name: "log", + Value: "", + Usage: "specify a log file to output, default goes to stderr", + }, + cli.StringFlag{ + Name: "c", + Value: "", // when the value is not empty, the config path must exists + Usage: "config from json file, which will override the command from shell", + }, + } + myApp.Action = func(c *cli.Context) error { + config := Config{} + config.LocalAddr = c.String("localaddr") + config.RemoteAddr = c.String("remoteaddr") + config.Key = c.String("key") + config.Crypt = c.String("crypt") + config.Mode = c.String("mode") + config.Conn = c.Int("conn") + config.AutoExpire = c.Int("autoexpire") + config.MTU = c.Int("mtu") + config.SndWnd = c.Int("sndwnd") + config.RcvWnd = c.Int("rcvwnd") + config.DataShard = c.Int("datashard") + config.ParityShard = c.Int("parityshard") + config.DSCP = c.Int("dscp") + config.NoComp = c.Bool("nocomp") + config.AckNodelay = c.Bool("acknodelay") + config.NoDelay = c.Int("nodelay") + config.Interval = c.Int("interval") + config.Resend = c.Int("resend") + config.NoCongestion = c.Int("nc") + config.SockBuf = c.Int("sockbuf") + config.KeepAlive = c.Int("keepalive") + config.Log = c.String("log") + config.SnmpLog = c.String("snmplog") + config.SnmpPeriod = c.Int("snmpperiod") + + if c.String("c") != "" { + err := parseJSONConfig(&config, c.String("c")) + checkError(err) + } + + // log redirect + if config.Log != "" { + f, err := os.OpenFile(config.Log, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + checkError(err) + defer f.Close() + log.SetOutput(f) + } + + switch config.Mode { + case "normal": + config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 30, 2, 1 + case "fast": + config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 20, 2, 1 + case "fast2": + config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 20, 2, 1 + case "fast3": + config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 10, 2, 1 + } + + log.Println("version:", VERSION) + addr, err := net.ResolveTCPAddr("tcp", config.LocalAddr) + checkError(err) + listener, err := net.ListenTCP("tcp", addr) + checkError(err) + + pass := pbkdf2.Key([]byte(config.Key), []byte(SALT), 4096, 32, sha1.New) + var block kcp.BlockCrypt + switch config.Crypt { + case "tea": + block, _ = kcp.NewTEABlockCrypt(pass[:16]) + case "xor": + block, _ = kcp.NewSimpleXORBlockCrypt(pass) + case "none": + block, _ = kcp.NewNoneBlockCrypt(pass) + case "aes-128": + block, _ = kcp.NewAESBlockCrypt(pass[:16]) + case "aes-192": + block, _ = kcp.NewAESBlockCrypt(pass[:24]) + case "blowfish": + block, _ = kcp.NewBlowfishBlockCrypt(pass) + case "twofish": + block, _ = kcp.NewTwofishBlockCrypt(pass) + case "cast5": + block, _ = kcp.NewCast5BlockCrypt(pass[:16]) + case "3des": + block, _ = kcp.NewTripleDESBlockCrypt(pass[:24]) + case "xtea": + block, _ = kcp.NewXTEABlockCrypt(pass[:16]) + case "salsa20": + block, _ = kcp.NewSalsa20BlockCrypt(pass) + default: + config.Crypt = "aes" + block, _ = kcp.NewAESBlockCrypt(pass) + } + + log.Println("listening on:", listener.Addr()) + log.Println("encryption:", config.Crypt) + log.Println("nodelay parameters:", config.NoDelay, config.Interval, config.Resend, config.NoCongestion) + log.Println("remote address:", config.RemoteAddr) + log.Println("sndwnd:", config.SndWnd, "rcvwnd:", config.RcvWnd) + log.Println("compression:", !config.NoComp) + log.Println("mtu:", config.MTU) + log.Println("datashard:", config.DataShard, "parityshard:", config.ParityShard) + log.Println("acknodelay:", config.AckNodelay) + log.Println("dscp:", config.DSCP) + log.Println("sockbuf:", config.SockBuf) + log.Println("keepalive:", config.KeepAlive) + log.Println("conn:", config.Conn) + log.Println("autoexpire:", config.AutoExpire) + log.Println("snmplog:", config.SnmpLog) + log.Println("snmpperiod:", config.SnmpPeriod) + + smuxConfig := smux.DefaultConfig() + smuxConfig.MaxReceiveBuffer = config.SockBuf + + createConn := func() (*smux.Session, error) { + kcpconn, err := kcp.DialWithOptions(config.RemoteAddr, block, config.DataShard, config.ParityShard) + if err != nil { + return nil, errors.Wrap(err, "createConn()") + } + kcpconn.SetStreamMode(true) + kcpconn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion) + kcpconn.SetWindowSize(config.SndWnd, config.RcvWnd) + kcpconn.SetMtu(config.MTU) + kcpconn.SetACKNoDelay(config.AckNodelay) + kcpconn.SetKeepAlive(config.KeepAlive) + + if err := kcpconn.SetDSCP(config.DSCP); err != nil { + log.Println("SetDSCP:", err) + } + if err := kcpconn.SetReadBuffer(config.SockBuf); err != nil { + log.Println("SetReadBuffer:", err) + } + if err := kcpconn.SetWriteBuffer(config.SockBuf); err != nil { + log.Println("SetWriteBuffer:", err) + } + + // stream multiplex + var session *smux.Session + if config.NoComp { + session, err = smux.Client(kcpconn, smuxConfig) + } else { + session, err = smux.Client(newCompStream(kcpconn), smuxConfig) + } + if err != nil { + return nil, errors.Wrap(err, "createConn()") + } + return session, nil + } + + // wait until a connection is ready + waitConn := func() *smux.Session { + for { + if session, err := createConn(); err == nil { + return session + } else { + time.Sleep(time.Second) + } + } + } + + numconn := uint16(config.Conn) + muxes := make([]struct { + session *smux.Session + ttl time.Time + }, numconn) + + for k := range muxes { + sess, err := createConn() + checkError(err) + muxes[k].session = sess + muxes[k].ttl = time.Now().Add(time.Duration(config.AutoExpire) * time.Second) + } + + chScavenger := make(chan *smux.Session, 128) + go scavenger(chScavenger) + go snmpLogger(config.SnmpLog, config.SnmpPeriod) + rr := uint16(0) + for { + p1, err := listener.AcceptTCP() + if err != nil { + log.Fatalln(err) + } + if err := p1.SetReadBuffer(config.SockBuf); err != nil { + log.Println("TCP SetReadBuffer:", err) + } + if err := p1.SetWriteBuffer(config.SockBuf); err != nil { + log.Println("TCP SetWriteBuffer:", err) + } + checkError(err) + idx := rr % numconn + + // do auto expiration && reconnection + if muxes[idx].session.IsClosed() || (config.AutoExpire > 0 && time.Now().After(muxes[idx].ttl)) { + chScavenger <- muxes[idx].session + muxes[idx].session = waitConn() + muxes[idx].ttl = time.Now().Add(time.Duration(config.AutoExpire) * time.Second) + } + + go handleClient(muxes[idx].session, p1) + rr++ + } + } + myApp.Run(os.Args) +} + +type scavengeSession struct { + session *smux.Session + ttl time.Time +} + +const ( + maxScavengeTTL = 10 * time.Minute +) + +func scavenger(ch chan *smux.Session) { + ticker := time.NewTicker(30 * time.Second) + defer ticker.Stop() + var sessionList []scavengeSession + for { + select { + case sess := <-ch: + sessionList = append(sessionList, scavengeSession{sess, time.Now()}) + case <-ticker.C: + var newList []scavengeSession + for k := range sessionList { + s := sessionList[k] + if s.session.NumStreams() == 0 || s.session.IsClosed() || time.Since(s.ttl) > maxScavengeTTL { + log.Println("session scavenged") + s.session.Close() + } else { + newList = append(newList, sessionList[k]) + } + } + sessionList = newList + } + } +} + +func snmpLogger(path string, interval int) { + if path == "" || interval == 0 { + return + } + ticker := time.NewTicker(time.Duration(interval) * time.Second) + defer ticker.Stop() + for { + select { + case <-ticker.C: + f, err := os.OpenFile(time.Now().Format(path), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + log.Println(err) + return + } + w := csv.NewWriter(f) + // write header in empty file + if stat, err := f.Stat(); err == nil && stat.Size() == 0 { + if err := w.Write(append([]string{"Unix"}, kcp.DefaultSnmp.Header()...)); err != nil { + log.Println(err) + } + } + if err := w.Write(append([]string{fmt.Sprint(time.Now().Unix())}, kcp.DefaultSnmp.ToSlice()...)); err != nil { + log.Println(err) + } + kcp.DefaultSnmp.Reset() + w.Flush() + f.Close() + } + } +} diff --git a/client/signal.go b/client/signal.go new file mode 100644 index 0000000..c7b1063 --- /dev/null +++ b/client/signal.go @@ -0,0 +1,28 @@ +// +build linux darwin freebsd + +package main + +import ( + "log" + "os" + "os/signal" + "syscall" + + kcp "github.com/xtaci/kcp-go" +) + +func init() { + go sigHandler() +} + +func sigHandler() { + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGUSR1) + + for { + switch <-ch { + case syscall.SIGUSR1: + log.Printf("KCP SNMP:%+v", kcp.DefaultSnmp.Copy()) + } + } +} diff --git a/fast.png b/fast.png new file mode 100644 index 0000000000000000000000000000000000000000..d5ed3c7bbc9abf0630f370351d0a5ad826927ccd GIT binary patch literal 25395 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 XVeIEo&l!Q7tK~C;!i=j7-Q)fMDXseJ literal 0 HcmV?d00001 diff --git a/layeredparams.png b/layeredparams.png new file mode 100644 index 0000000000000000000000000000000000000000..d6a350ce6246c9aa70f0dd9f5ba8b63acfab1bc4 GIT binary patch literal 60800 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 literal 0 HcmV?d00001 diff --git a/logo-small.png b/logo-small.png new file mode 100644 index 0000000000000000000000000000000000000000..3f8736a32232b3434929c59029e39d75590479d3 GIT binary patch literal 6929 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 lJ=e|`48N{nyP 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 V@eux8pf~^k002ovPDHLkV1k;{9JK%d literal 0 HcmV?d00001 diff --git a/rs.png b/rs.png new file mode 100644 index 0000000000000000000000000000000000000000..3d228c084827c65a70f56dcaa8137bb32cafbec3 GIT binary patch literal 25544 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 z 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 cOV literal 0 HcmV?d00001 diff --git a/server/config.go b/server/config.go new file mode 100644 index 0000000..0972498 --- /dev/null +++ b/server/config.go @@ -0,0 +1,42 @@ +package main + +import ( + "encoding/json" + "os" +) + +// Config for server +type Config struct { + Listen string `json:"listen"` + Target string `json:"target"` + Key string `json:"key"` + Crypt string `json:"crypt"` + Mode string `json:"mode"` + MTU int `json:"mtu"` + SndWnd int `json:"sndwnd"` + RcvWnd int `json:"rcvwnd"` + DataShard int `json:"datashard"` + ParityShard int `json:"parityshard"` + DSCP int `json:"dscp"` + NoComp bool `json:"nocomp"` + AckNodelay bool `json:"acknodelay"` + NoDelay int `json:"nodelay"` + Interval int `json:"interval"` + Resend int `json:"resend"` + NoCongestion int `json:"nc"` + SockBuf int `json:"sockbuf"` + KeepAlive int `json:"keepalive"` + Log string `json:"log"` + SnmpLog string `json:"snmplog"` + SnmpPeriod int `json:"snmpperiod"` +} + +func parseJSONConfig(config *Config, path string) error { + file, err := os.Open(path) // For read access. + if err != nil { + return err + } + defer file.Close() + + return json.NewDecoder(file).Decode(config) +} diff --git a/server/main.go b/server/main.go new file mode 100644 index 0000000..55d33cb --- /dev/null +++ b/server/main.go @@ -0,0 +1,405 @@ +package main + +import ( + "crypto/sha1" + "encoding/csv" + "fmt" + "io" + "log" + "math/rand" + "net" + "os" + "time" + + "golang.org/x/crypto/pbkdf2" + + "github.com/golang/snappy" + "github.com/urfave/cli" + kcp "github.com/xtaci/kcp-go" + "github.com/xtaci/smux" +) + +var ( + // VERSION is injected by buildflags + VERSION = "SELFBUILD" + // SALT is use for pbkdf2 key expansion + SALT = "kcp-go" +) + +type compStream struct { + conn net.Conn + w *snappy.Writer + r *snappy.Reader +} + +func (c *compStream) Read(p []byte) (n int, err error) { + return c.r.Read(p) +} + +func (c *compStream) Write(p []byte) (n int, err error) { + n, err = c.w.Write(p) + err = c.w.Flush() + return n, err +} + +func (c *compStream) Close() error { + return c.conn.Close() +} + +func newCompStream(conn net.Conn) *compStream { + c := new(compStream) + c.conn = conn + c.w = snappy.NewBufferedWriter(conn) + c.r = snappy.NewReader(conn) + return c +} + +// handle multiplex-ed connection +func handleMux(conn io.ReadWriteCloser, config *Config) { + // stream multiplex + smuxConfig := smux.DefaultConfig() + smuxConfig.MaxReceiveBuffer = config.SockBuf + mux, err := smux.Server(conn, smuxConfig) + if err != nil { + log.Println(err) + return + } + defer mux.Close() + for { + p1, err := mux.AcceptStream() + if err != nil { + log.Println(err) + return + } + p2, err := net.DialTimeout("tcp", config.Target, 5*time.Second) + if err != nil { + p1.Close() + log.Println(err) + continue + } + if err := p2.(*net.TCPConn).SetReadBuffer(config.SockBuf); err != nil { + log.Println("TCP SetReadBuffer:", err) + } + if err := p2.(*net.TCPConn).SetWriteBuffer(config.SockBuf); err != nil { + log.Println("TCP SetWriteBuffer:", err) + } + go handleClient(p1, p2) + } +} + +func handleClient(p1, p2 io.ReadWriteCloser) { + log.Println("stream opened") + defer log.Println("stream closed") + defer p1.Close() + defer p2.Close() + + // start tunnel + p1die := make(chan struct{}) + go func() { io.Copy(p1, p2); close(p1die) }() + + p2die := make(chan struct{}) + go func() { io.Copy(p2, p1); close(p2die) }() + + // wait for tunnel termination + select { + case <-p1die: + case <-p2die: + } +} + +func checkError(err error) { + if err != nil { + log.Printf("%+v\n", err) + os.Exit(-1) + } +} + +func main() { + rand.Seed(int64(time.Now().Nanosecond())) + if VERSION == "SELFBUILD" { + // add more log flags for debugging + log.SetFlags(log.LstdFlags | log.Lshortfile) + } + myApp := cli.NewApp() + myApp.Name = "kcptun" + myApp.Usage = "server(with SMUX)" + myApp.Version = VERSION + myApp.Flags = []cli.Flag{ + cli.StringFlag{ + Name: "listen,l", + Value: ":29900", + Usage: "kcp server listen address", + }, + cli.StringFlag{ + Name: "target, t", + Value: "127.0.0.1:12948", + Usage: "target server address", + }, + cli.StringFlag{ + Name: "key", + Value: "it's a secrect", + Usage: "pre-shared secret between client and server", + EnvVar: "KCPTUN_KEY", + }, + cli.StringFlag{ + Name: "crypt", + Value: "aes", + Usage: "aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none", + }, + cli.StringFlag{ + Name: "mode", + Value: "fast", + Usage: "profiles: fast3, fast2, fast, normal", + }, + cli.IntFlag{ + Name: "mtu", + Value: 1350, + Usage: "set maximum transmission unit for UDP packets", + }, + cli.IntFlag{ + Name: "sndwnd", + Value: 1024, + Usage: "set send window size(num of packets)", + }, + cli.IntFlag{ + Name: "rcvwnd", + Value: 1024, + Usage: "set receive window size(num of packets)", + }, + cli.IntFlag{ + Name: "datashard,ds", + Value: 10, + Usage: "set reed-solomon erasure coding - datashard", + }, + cli.IntFlag{ + Name: "parityshard,ps", + Value: 3, + Usage: "set reed-solomon erasure coding - parityshard", + }, + cli.IntFlag{ + Name: "dscp", + Value: 0, + Usage: "set DSCP(6bit)", + }, + cli.BoolFlag{ + Name: "nocomp", + Usage: "disable compression", + }, + cli.BoolFlag{ + Name: "acknodelay", + Usage: "flush ack immediately when a packet is received", + Hidden: true, + }, + cli.IntFlag{ + Name: "nodelay", + Value: 0, + Hidden: true, + }, + cli.IntFlag{ + Name: "interval", + Value: 40, + Hidden: true, + }, + cli.IntFlag{ + Name: "resend", + Value: 0, + Hidden: true, + }, + cli.IntFlag{ + Name: "nc", + Value: 0, + Hidden: true, + }, + cli.IntFlag{ + Name: "sockbuf", + Value: 4194304, // socket buffer size in bytes + Hidden: true, + }, + cli.IntFlag{ + Name: "keepalive", + Value: 10, // nat keepalive interval in seconds + Hidden: true, + }, + cli.StringFlag{ + Name: "snmplog", + Value: "", + Usage: "collect snmp to file, aware of timeformat in golang, like: ./snmp-20060102.log", + }, + cli.IntFlag{ + Name: "snmpperiod", + Value: 60, + Usage: "snmp collect period, in seconds", + }, + cli.StringFlag{ + Name: "log", + Value: "", + Usage: "specify a log file to output, default goes to stderr", + }, + cli.StringFlag{ + Name: "c", + Value: "", // when the value is not empty, the config path must exists + Usage: "config from json file, which will override the command from shell", + }, + } + myApp.Action = func(c *cli.Context) error { + config := Config{} + config.Listen = c.String("listen") + config.Target = c.String("target") + config.Key = c.String("key") + config.Crypt = c.String("crypt") + config.Mode = c.String("mode") + config.MTU = c.Int("mtu") + config.SndWnd = c.Int("sndwnd") + config.RcvWnd = c.Int("rcvwnd") + config.DataShard = c.Int("datashard") + config.ParityShard = c.Int("parityshard") + config.DSCP = c.Int("dscp") + config.NoComp = c.Bool("nocomp") + config.AckNodelay = c.Bool("acknodelay") + config.NoDelay = c.Int("nodelay") + config.Interval = c.Int("interval") + config.Resend = c.Int("resend") + config.NoCongestion = c.Int("nc") + config.SockBuf = c.Int("sockbuf") + config.KeepAlive = c.Int("keepalive") + config.Log = c.String("log") + config.SnmpLog = c.String("snmplog") + config.SnmpPeriod = c.Int("snmpperiod") + + if c.String("c") != "" { + //Now only support json config file + err := parseJSONConfig(&config, c.String("c")) + checkError(err) + } + + // log redirect + if config.Log != "" { + f, err := os.OpenFile(config.Log, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + checkError(err) + defer f.Close() + log.SetOutput(f) + } + + switch config.Mode { + case "normal": + config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 30, 2, 1 + case "fast": + config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 0, 20, 2, 1 + case "fast2": + config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 20, 2, 1 + case "fast3": + config.NoDelay, config.Interval, config.Resend, config.NoCongestion = 1, 10, 2, 1 + } + + log.Println("version:", VERSION) + pass := pbkdf2.Key([]byte(config.Key), []byte(SALT), 4096, 32, sha1.New) + var block kcp.BlockCrypt + switch config.Crypt { + case "tea": + block, _ = kcp.NewTEABlockCrypt(pass[:16]) + case "xor": + block, _ = kcp.NewSimpleXORBlockCrypt(pass) + case "none": + block, _ = kcp.NewNoneBlockCrypt(pass) + case "aes-128": + block, _ = kcp.NewAESBlockCrypt(pass[:16]) + case "aes-192": + block, _ = kcp.NewAESBlockCrypt(pass[:24]) + case "blowfish": + block, _ = kcp.NewBlowfishBlockCrypt(pass) + case "twofish": + block, _ = kcp.NewTwofishBlockCrypt(pass) + case "cast5": + block, _ = kcp.NewCast5BlockCrypt(pass[:16]) + case "3des": + block, _ = kcp.NewTripleDESBlockCrypt(pass[:24]) + case "xtea": + block, _ = kcp.NewXTEABlockCrypt(pass[:16]) + case "salsa20": + block, _ = kcp.NewSalsa20BlockCrypt(pass) + default: + config.Crypt = "aes" + block, _ = kcp.NewAESBlockCrypt(pass) + } + + lis, err := kcp.ListenWithOptions(config.Listen, block, config.DataShard, config.ParityShard) + checkError(err) + log.Println("listening on:", lis.Addr()) + log.Println("target:", config.Target) + log.Println("encryption:", config.Crypt) + log.Println("nodelay parameters:", config.NoDelay, config.Interval, config.Resend, config.NoCongestion) + log.Println("sndwnd:", config.SndWnd, "rcvwnd:", config.RcvWnd) + log.Println("compression:", !config.NoComp) + log.Println("mtu:", config.MTU) + log.Println("datashard:", config.DataShard, "parityshard:", config.ParityShard) + log.Println("acknodelay:", config.AckNodelay) + log.Println("dscp:", config.DSCP) + log.Println("sockbuf:", config.SockBuf) + log.Println("keepalive:", config.KeepAlive) + log.Println("snmplog:", config.SnmpLog) + log.Println("snmpperiod:", config.SnmpPeriod) + + if err := lis.SetDSCP(config.DSCP); err != nil { + log.Println("SetDSCP:", err) + } + if err := lis.SetReadBuffer(config.SockBuf); err != nil { + log.Println("SetReadBuffer:", err) + } + if err := lis.SetWriteBuffer(config.SockBuf); err != nil { + log.Println("SetWriteBuffer:", err) + } + + go snmpLogger(config.SnmpLog, config.SnmpPeriod) + for { + if conn, err := lis.AcceptKCP(); err == nil { + log.Println("remote address:", conn.RemoteAddr()) + conn.SetStreamMode(true) + conn.SetNoDelay(config.NoDelay, config.Interval, config.Resend, config.NoCongestion) + conn.SetMtu(config.MTU) + conn.SetWindowSize(config.SndWnd, config.RcvWnd) + conn.SetACKNoDelay(config.AckNodelay) + conn.SetKeepAlive(config.KeepAlive) + + if config.NoComp { + go handleMux(conn, &config) + } else { + go handleMux(newCompStream(conn), &config) + } + } else { + log.Printf("%+v", err) + } + } + } + myApp.Run(os.Args) +} + +func snmpLogger(path string, interval int) { + if path == "" || interval == 0 { + return + } + ticker := time.NewTicker(time.Duration(interval) * time.Second) + defer ticker.Stop() + for { + select { + case <-ticker.C: + f, err := os.OpenFile(time.Now().Format(path), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + log.Println(err) + return + } + w := csv.NewWriter(f) + // write header in empty file + if stat, err := f.Stat(); err == nil && stat.Size() == 0 { + if err := w.Write(append([]string{"Unix"}, kcp.DefaultSnmp.Header()...)); err != nil { + log.Println(err) + } + } + if err := w.Write(append([]string{fmt.Sprint(time.Now().Unix())}, kcp.DefaultSnmp.ToSlice()...)); err != nil { + log.Println(err) + } + kcp.DefaultSnmp.Reset() + w.Flush() + f.Close() + } + } +} diff --git a/server/signal.go b/server/signal.go new file mode 100644 index 0000000..c7b1063 --- /dev/null +++ b/server/signal.go @@ -0,0 +1,28 @@ +// +build linux darwin freebsd + +package main + +import ( + "log" + "os" + "os/signal" + "syscall" + + kcp "github.com/xtaci/kcp-go" +) + +func init() { + go sigHandler() +} + +func sigHandler() { + ch := make(chan os.Signal, 1) + signal.Notify(ch, syscall.SIGUSR1) + + for { + switch <-ch { + case syscall.SIGUSR1: + log.Printf("KCP SNMP:%+v", kcp.DefaultSnmp.Copy()) + } + } +}