Compare commits

..
218 Commits
Author SHA1 Message Date
xtaciandGitHub aed33d45ae Update README.md 2017-01-12 11:33:08 +08:00
xtaciandGitHub 53328dce08 Update README.md 2017-01-11 13:12:29 +08:00
xtaci 17be438477 switch back to golang offical snappy lib 2017-01-11 12:50:33 +08:00
xtaci c7db48ae11 upd 2017-01-03 12:51:21 +08:00
xtaci de389a8500 upd issue template 2017-01-03 11:01:15 +08:00
xtaci f7474faf19 adjust default rcvwnd from 1024 to 512 2016-12-27 13:34:46 +08:00
xtaci 61e69d9d5b add snmp reset 2016-12-21 10:52:12 +08:00
xtaci 11cdc2038c add unix timestamp to snmp records 2016-12-20 23:01:47 +08:00
xtaci 1908dc391e upd 2016-12-20 22:16:34 +08:00
xtaci 51e6b381bf upd 2016-12-20 22:16:10 +08:00
xtaci 3531726339 add -snmplog & -snmpperiod options to collect SNMP into file 2016-12-20 22:13:00 +08:00
xtaci 53f814ec9f handle AcceptTCP error 2016-12-17 13:13:59 +08:00
xtaci 375640d183 Merge branch 'master' of https://github.com/xtaci/kcptun 2016-12-07 20:14:34 +08:00
xtaci ae2ba18b08 async stream open 2016-12-07 20:14:09 +08:00
xtaciandGitHub 717df77668 Update README.md 2016-12-05 14:06:44 +08:00
xtaci b61a2c240c upd 2016-12-02 17:02:41 +08:00
xtaci bfe3524d74 Merge branch 'master' of https://github.com/xtaci/kcptun 2016-12-02 16:24:44 +08:00
xtaci 8b3b38eeef add compile target mipsle 2016-12-02 16:23:53 +08:00
xtaciandGitHub 754b4a7186 Update README.md 2016-11-18 13:50:09 +08:00
xtaci 229a4a8783 Merge branch 'master' of https://github.com/xtaci/kcptun 2016-11-10 20:36:39 +08:00
xtaci 052f0a5397 optimized xor doesn't need -B flag for bce 2016-11-10 20:35:33 +08:00
xtaciandGitHub 8e74cf410c Update README.en.md 2016-11-04 10:56:03 +08:00
xtaciandGitHub 206df4b69f Update README.md 2016-11-04 10:55:36 +08:00
xtaciandGitHub 4ccc922059 Update README.md 2016-11-01 13:47:57 +08:00
xtaciandGitHub 1e88951c54 Update README.md 2016-11-01 13:41:49 +08:00
xtaciandGitHub 6540e3e90a Update README.en.md 2016-11-01 13:38:47 +08:00
xtaciandGitHub 9ac03a973b Update README.md 2016-11-01 13:34:51 +08:00
xtaciandGitHub f911127426 Add files via upload 2016-11-01 13:31:48 +08:00
xtaciandGitHub c601a18b3c Update README.md 2016-10-29 21:42:49 +08:00
xtaciandGitHub 7eb8d3ce41 Update README.md 2016-10-28 17:56:18 +08:00
xtaciandGitHub d425d472eb Update README.md 2016-10-28 16:44:04 +08:00
xtaciandGitHub bb9574e700 Update README.md 2016-10-28 13:02:58 +08:00
xtaciandGitHub 4670fa3a92 Update README.md 2016-10-28 12:55:03 +08:00
xtaciandGitHub b84a293eda simplify 2016-10-28 11:34:01 +08:00
xtaciandGitHub 7e1acb4a0f Update README.md 2016-10-28 11:32:58 +08:00
xtaciandGitHub 829694fb75 Update README.md 2016-10-26 21:05:48 +08:00
xtaciandGitHub c0c7d56f47 Update README.md 2016-10-26 14:51:04 +08:00
xtaciandGitHub 79d69e76bc Update README.md 2016-10-26 14:43:49 +08:00
xtaciandGitHub 2378dc7dfe Update README.md 2016-10-26 14:43:02 +08:00
xtaciandGitHub 4e4882741a Update README.md 2016-10-26 14:32:08 +08:00
xtaciandGitHub af39e7edf0 Update README.md 2016-10-26 14:28:58 +08:00
xtaciandGitHub e12977a031 Update README.md 2016-10-26 14:27:33 +08:00
xtaciandGitHub 5ba941f654 Update README.md 2016-10-26 11:08:25 +08:00
xtaciandGitHub 5dbc2d25c8 Update README.md 2016-10-26 11:06:09 +08:00
xtaciandGitHub 0bcf57c444 Update README.md 2016-10-26 11:00:41 +08:00
xtaciandGitHub a8b5c0677e Update README.en.md 2016-10-26 10:59:49 +08:00
xtaciandGitHub 27b67c1a5a Update README.md 2016-10-26 10:58:38 +08:00
xtaciandGitHub 45a802a137 Update README.en.md 2016-10-25 22:19:52 +08:00
xtaciandGitHub c8cc2fe95e Update README.md 2016-10-25 21:56:20 +08:00
xtaciandGitHub 2addfa670d Update README.md 2016-10-25 17:59:16 +08:00
xtaciandGitHub 4001e1b23d Update README.md 2016-10-24 22:59:48 +08:00
xtaciandGitHub 40590417a9 Update README.md 2016-10-24 17:28:45 +08:00
xtaciandGitHub 67db1f276b Update README.md 2016-10-24 13:15:54 +08:00
xtaciandGitHub 16b4b6a9a0 Update README.md 2016-10-24 13:15:07 +08:00
xtaciandGitHub c4d07f13f1 Update README.md 2016-10-22 23:02:55 +08:00
xtaciandGitHub 5945a2490c Update README.md 2016-10-22 11:00:33 +08:00
xtaciandGitHub 532b2c89d5 Update README.md 2016-10-19 13:41:01 +08:00
xtaciandGitHub b2b4f8cdf6 Update README.md 2016-10-19 11:38:56 +08:00
xtaciandGitHub f7655b79e0 Update README.md 2016-10-19 11:35:27 +08:00
xtaciandGitHub 91980543ee Update README.md 2016-10-19 11:29:56 +08:00
xtaciandGitHub 02cda02f9a Update README.md 2016-10-19 11:28:55 +08:00
xtaciandGitHub 6016302e8a Update README.md 2016-10-19 10:29:00 +08:00
xtaciandGitHub dfdd4c8c24 Update README.md 2016-10-18 23:16:48 +08:00
xtaciandGitHub 2195981b01 Update README.md 2016-10-18 11:25:15 +08:00
xtaciandGitHub 485572857e Update README.md 2016-10-18 10:27:16 +08:00
xtaci 4b2d0e567d replace "github.com/golang/snappy" with "github.com/klauspost/compress/snappy" 2016-10-18 10:14:23 +08:00
xtaciandGitHub 68b36fbf74 Update README.md 2016-10-01 09:49:36 +08:00
xtaci 9b08423b3e upd README 2016-09-27 12:36:23 +08:00
xtaci 35522d30cb upd README 2016-09-23 12:42:14 +08:00
xtaci e8e3e5a894 add -log option to redirect log , see issue #199 2016-09-22 15:20:42 +08:00
xtaci 9c95df026b lint 2016-09-20 16:16:36 +08:00
xtaci 09aea3056a block-waiting for a connection after the client has been started 2016-09-19 10:40:59 +08:00
xtaci 0788aa8260 Revert "Revert "do not panic when network is temporarily unavailable""
This reverts commit 2f479b788c.
2016-09-19 10:31:21 +08:00
xtaci 2f479b788c Revert "do not panic when network is temporarily unavailable"
This reverts commit f3f78460a4.
2016-09-18 21:00:28 +08:00
xtaci f3f78460a4 do not panic when network is temporarily unavailable 2016-09-18 20:51:35 +08:00
xtaci 3127b2d19f lint 2016-09-06 16:29:36 +08:00
xtaci 3db63cdff6 add a max ttl for session in scavenger 2016-09-03 14:32:35 +08:00
xtaci 5154cf81de api change of smux 2016-09-02 23:18:29 +08:00
xtaci cc80029b1e adjust params 2016-09-02 17:29:55 +08:00
xtaci 23d6624745 upd 2016-09-02 17:05:44 +08:00
xtaci f38f7a8ac5 scavenge only 2016-09-02 10:55:22 +08:00
xtaci e913f96f7e Merge branch 'smux' 2016-09-02 10:54:00 +08:00
xtaci 5d0d8bd74d upd 2016-09-02 10:42:23 +08:00
xtaci 4010c83e8f upd 2016-09-01 15:02:21 +08:00
xtaci 76351dff2b upd 2016-09-01 12:59:08 +08:00
xtaci 7a5807cbf5 Revert "explict close session"
This reverts commit cb0f299263.
2016-08-31 23:24:30 +08:00
xtaci 6b26c75ea5 upd 2016-08-31 21:48:43 +08:00
xtaci 0873f349c3 upd 2016-08-31 21:46:14 +08:00
xtaci 281f8675a3 upd 2016-08-31 21:33:52 +08:00
xtaci 65512e9296 upd 2016-08-31 21:31:05 +08:00
xtaci 3ea858ed90 upd 2016-08-31 21:29:27 +08:00
xtaci 5f23781fc0 scavenger 2016-08-31 21:27:19 +08:00
xtaci 2b3573f4ea Merge branch 'master' into smux 2016-08-31 18:10:48 +08:00
xtaci cb0f299263 explict close session 2016-08-31 18:07:24 +08:00
xtaci f64bc908ee upd 2016-08-31 16:30:51 +08:00
xtaci 43c6a674ef upd 2016-08-31 15:28:43 +08:00
xtaci 1a48680a55 upd 2016-08-31 15:23:31 +08:00
xtaci dbdb5293b4 branch smux 2016-08-31 11:39:56 +08:00
xtaci 94070bfcbe should continue 2016-08-30 15:34:19 +08:00
xtaciandGitHub 398a0bf9fc Merge pull request #166 from jannson/master
add support for json configuration
2016-08-30 14:56:33 +08:00
janson ff54a2dc92 better for parseJsonConfig 2016-08-30 14:44:55 +08:00
janson 747eba0ee1 add usage and check error for json config 2016-08-30 14:24:08 +08:00
janson f057cbc7f4 add support for json configuration (server side) 2016-08-30 13:50:37 +08:00
janson a83ae4bf15 add support for json configuration 2016-08-30 13:39:08 +08:00
xtaci 4d062090a7 bugfix 2016-08-30 11:17:15 +08:00
xtaci 27f76582e1 structured configuration 2016-08-29 16:06:38 +08:00
xtaci b023b542e8 handle errors gracefully 2016-08-28 10:37:09 +08:00
xtaci 9a3be067bf upd 2016-08-27 21:52:42 +08:00
xtaci 8705bd7670 upd 2016-08-27 09:17:16 +08:00
xtaci b4e5181a2f optimize retry strategy 2016-08-27 09:00:35 +08:00
xtaci 94f61b5945 upd param 2016-08-26 13:04:38 +08:00
xtaci efc0b99d21 Revert "replace yamux with muxado"
This reverts commit 3803993529.
2016-08-26 11:35:13 +08:00
xtaci 3803993529 replace yamux with muxado 2016-08-26 10:58:43 +08:00
xtaci d23ff7c351 upd 2016-08-25 20:34:33 +08:00
xtaci f383ee31a5 add autoexpire option 2016-08-25 20:33:04 +08:00
xtaci d399f220f0 remove a line 2016-08-25 20:04:34 +08:00
xtaci 59a1bbc7b8 SetFinalizer to session 2016-08-25 18:22:20 +08:00
xtaci 3b656e101f better api 2016-08-25 11:46:17 +08:00
xtaci aec364eb72 set tcp socket buffer 2016-08-24 12:27:33 +08:00
xtaci e26ab6729f spelling 2016-08-22 14:46:57 +08:00
xtaci 583fe3ba24 simple layer 2016-08-21 19:09:08 +08:00
xtaci 7fd6442284 refer to my fork 2016-08-20 21:15:05 +08:00
xtaci 81f4643830 Revert "refer to fork"
This reverts commit 744a6407e7.
2016-08-20 20:49:44 +08:00
xtaci 744a6407e7 refer to fork 2016-08-20 20:23:04 +08:00
xtaci 2cf5292ac1 revert yamux config 2016-08-20 18:37:52 +08:00
xtaci b3a8b631b4 upd README 2016-08-20 16:48:10 +08:00
xtaci 1167419210 add salsa20, xtea crypto 2016-08-20 15:02:25 +08:00
xtaci 56f9f0d01a Merge branch 'master' of https://github.com/xtaci/kcptun 2016-08-20 13:39:01 +08:00
xtaci 96888f1cac pisces 2016-08-20 13:35:27 +08:00
xtaciandGitHub e752d70c79 Update README.en.md 2016-08-20 10:47:59 +08:00
xtaciandGitHub a882b94e5b Update README.md 2016-08-20 10:46:34 +08:00
xtaciandGitHub 790a6d5352 Update README.en.md 2016-08-19 21:21:03 +08:00
xtaciandGitHub 603c2db5ab Update README.md 2016-08-19 21:20:15 +08:00
xtaci 581df3a34d update README.md 2016-08-19 15:00:25 +08:00
xtaci 6113d2b497 update README.md 2016-08-19 14:27:13 +08:00
xtaci d3b8a4d71d keep compatiability 2016-08-19 13:17:02 +08:00
xtaci 1f0a4a2c2f change default settings 2016-08-19 12:31:51 +08:00
xtaci 75923fb08f adjust -help 2016-08-19 12:22:36 +08:00
xtaci 0243422885 add supports for blowfish, cast5, 3des 2016-08-19 11:15:13 +08:00
xtaci 6374cb0d36 Merge branch 'master' of https://github.com/xtaci/kcptun 2016-08-18 23:44:25 +08:00
xtaci 0aedc21c50 Revert "change default resend from 2 -> 3"
This reverts commit 003617186b.
2016-08-18 23:40:51 +08:00
xtaciandGitHub 727887517f Update README.en.md 2016-08-18 10:56:46 +08:00
xtaciandGitHub 7b81b24e8d Update README.md 2016-08-18 10:55:55 +08:00
xtaci ba22434379 experimental Bounds Checking Elimination 2016-08-18 09:51:17 +08:00
xtaci 003617186b change default resend from 2 -> 3 2016-08-17 21:07:27 +08:00
xtaciandGitHub b9ce27cb3e Update README.en.md 2016-08-17 11:33:53 +08:00
xtaciandGitHub c93a199823 Update README.md 2016-08-17 11:32:58 +08:00
xtaci bb34894947 upd issue 2016-08-17 11:26:35 +08:00
xtaci f743a075c5 upd 2016-08-17 11:22:09 +08:00
xtaci a04c959c9c add aes-128 aes-192 cipher 2016-08-16 16:46:27 +08:00
xtaci 4a79d26d35 upd README.md 2016-08-16 10:31:37 +08:00
xtaci 8104d18959 Revert "add manual GC support"
This reverts commit ae699f498c.
2016-08-15 21:34:43 +08:00
xtaci ae699f498c add manual GC support 2016-08-15 20:28:15 +08:00
xtaci dbdd79f1d6 upd 2016-08-15 14:04:45 +08:00
xtaciandGitHub 51bdedb1b3 Update README.md 2016-08-15 14:03:48 +08:00
xtaci 8ea071fa03 upd README 2016-08-15 10:23:47 +08:00
xtaciandGitHub f74201a410 Update ISSUE_TEMPLATE 2016-08-14 18:34:32 +08:00
xtaci 96622bcfc0 add issue template 2016-08-12 10:27:17 +08:00
xtaciandGitHub 29328b375a Update README.md 2016-08-11 21:02:21 +08:00
xtaciandGitHub db7f1def1b Update README.en.md 2016-08-11 20:50:48 +08:00
xtaciandGitHub 628e723167 Update README.md 2016-08-11 20:48:48 +08:00
xtaci ff393ccacb revert part of the PR 2016-08-11 14:47:43 +08:00
xtaciandGitHub 1bb61dbcfc Merge pull request #113 from buaazp/yamux-optimize
*: some optimizes for yamux cache and config
2016-08-11 14:38:05 +08:00
招牌疯子 0b1598d09f *: yamux optimizes for cache and config
and debug log flags when selfbuild.
2016-08-11 14:23:44 +08:00
xtaci 0552bebe46 upd 2016-08-11 13:29:01 +08:00
xtaci d158e6df3f set stream max windows size to sockbuff 2016-08-11 13:20:03 +08:00
xtaciandGitHub cf7bca5cb7 Update README.md 2016-08-11 10:05:05 +08:00
xtaciandGitHub 99a2b60c7d Update README.md 2016-08-11 10:04:25 +08:00
xtaciandGitHub 4a5024b361 Update README.md 2016-08-11 10:04:02 +08:00
xtaciandGitHub 12bd3853d5 Update README.en.md 2016-08-10 10:31:05 +08:00
xtaciandGitHub 7992b87889 Update README.md 2016-08-10 10:30:17 +08:00
xtaciandGitHub cfcc2e0676 Update README.en.md 2016-08-09 15:52:45 +08:00
xtaciandGitHub 1e870f02af Update README.md 2016-08-09 14:08:22 +08:00
xtaci bf2abf14e7 change default socket buffer to 4MB(macOS default limit) 2016-08-08 10:50:46 +08:00
xtaci 2df3e6c438 optimize API 2016-08-08 10:41:42 +08:00
xtaciandGitHub ba4c93c3f5 Update README.md 2016-08-07 21:00:52 +08:00
xtaciandGitHub bc22f46065 Merge pull request #97 from buaazp/master
optmize cli flags for accept callback
2016-08-07 19:45:01 +08:00
招牌疯子 3fc15de95d optmize cli flags for accept callback
And use custom kcp package name for godef.
2016-08-07 14:09:58 +08:00
xtaci 6f9449bb10 rename api 2016-08-06 11:21:20 +08:00
xtaci c6cbfd307e change ping -> keepalive for nat keep-alive 2016-08-06 10:19:13 +08:00
xtaci d68792cb1a add hidden parameters -- ping 2016-08-05 22:46:11 +08:00
xtaci 117edce137 upd kcp-go api 2016-08-05 17:06:57 +08:00
xtaciandGitHub 990a5f7f87 Update README.md 2016-08-02 14:24:42 +08:00
xtaciandGitHub 19d7d74d59 Add files via upload 2016-08-01 12:44:41 +08:00
xtaci 31afe325ad Merge branch 'master' of https://github.com/xtaci/kcptun 2016-07-29 10:17:33 +08:00
xtaci ab7519c2d6 remove one unnecessary line 2016-07-29 10:17:14 +08:00
xtaciandGitHub d6da2e1ead Update README.en.md 2016-07-27 13:51:13 +08:00
xtaciandGitHub 4d5a3dd791 Update README.md 2016-07-27 13:49:01 +08:00
xtaciandGitHub 4a46d696b6 Update README.md 2016-07-27 13:41:31 +08:00
xtaciandGitHub 33d50dcd45 Update README.en.md 2016-07-26 23:26:23 +08:00
xtaciandGitHub 2b3f6dbabe Update README.md 2016-07-26 23:25:15 +08:00
xtaciandGitHub 448717fa1c Update README.md 2016-07-26 21:40:17 +08:00
xtaciandGitHub 887fba3381 Update README.md 2016-07-26 21:33:52 +08:00
xtaciandGitHub fb62d45df8 Update README.en.md 2016-07-26 16:10:29 +08:00
xtaciandGitHub cd1e2b4ff7 Update README.md 2016-07-26 16:09:08 +08:00
xtaci 5ee659dd41 improve network latency by introducing stream mode 2016-07-25 20:14:12 +08:00
xtaciandGitHub 1a596f55f4 Update README.en.md 2016-07-24 16:18:28 +08:00
xtaciandGitHub 889a904dca Update README.md 2016-07-24 16:18:09 +08:00
xtaciandGitHub 172dcf6481 Update README.en.md 2016-07-24 16:16:34 +08:00
xtaciandGitHub ff92c70b40 Add files via upload 2016-07-24 16:15:22 +08:00
xtaciandGitHub af1d28ae5a Update README.md 2016-07-24 16:09:06 +08:00
xtaciandGitHub 4a7d143c69 Update README.en.md 2016-07-24 16:04:58 +08:00
xtaciandGitHub 7ff69f16d5 Update README.md 2016-07-24 16:03:48 +08:00
xtaciandGitHub 7eb037c4dd Update README.md 2016-07-24 16:00:53 +08:00
xtaciandGitHub a87f6af812 Add files via upload 2016-07-24 15:58:35 +08:00
xtaciandGitHub 7574f9bfd3 Update README.md 2016-07-24 09:23:47 +08:00
xtaci d5b5cf683b update Dockerfile 2016-07-23 11:30:37 +08:00
xtaci fded353b68 update Dockerfile 2016-07-23 11:23:18 +08:00
xtaci 832dbed064 Merge branch 'master' of https://github.com/xtaci/kcptun 2016-07-23 11:18:48 +08:00
xtaci 4b660fa02c update 2016-07-23 11:18:29 +08:00
xtaciandGitHub 59e6ebee05 Update README.md 2016-07-23 11:10:55 +08:00
xtaciandGitHub c1a895426d Update README.md 2016-07-23 10:49:21 +08:00
xtaci ebdcc9ae8a Merge branch 'master' of https://github.com/xtaci/kcptun 2016-07-22 21:41:24 +08:00
xtaci 2c076f7a34 update Dockerfile to alpine 2016-07-22 21:25:29 +08:00
Daniel FuandGitHub a1a0fbd060 Update README.md 2016-07-21 20:25:43 +08:00
Daniel FuandGitHub bc4214e4a8 Update README.md 2016-07-21 12:27:00 +08:00
Daniel FuandGitHub 61e6dfe87b Update README.md 2016-07-21 12:26:00 +08:00
Daniel FuandGitHub 4448a2658d Add files via upload 2016-07-20 14:53:01 +08:00
16 changed files with 1034 additions and 335 deletions
+27
View File
@@ -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**?
+5 -3
View File
@@ -1,6 +1,8 @@
FROM golang:latest
FROM golang:alpine
MAINTAINER xtaci <daniel820313@gmail.com>
RUN go get github.com/xtaci/kcptun/client
RUN go get github.com/xtaci/kcptun/server
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
+114 -34
View File
@@ -1,7 +1,7 @@
# <img src="logo.png" alt="kcptun" height="60px" />
[![GoDoc][1]][2] [![Release][13]][14] [![Powered][17]][18] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Downloads][15]][16]
[1]: https://godoc.org/github.com/xtaci/kcptun?status.svg
[2]: https://godoc.org/github.com/xtaci/kcptun
[![Release][13]][14] [![Powered][17]][18] [![MIT licensed][11]][12] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Downloads][15]][16] [![Gitter][19]][20] [![Docker][1]][2]
[1]: https://images.microbadger.com/badges/image/xtaci/kcptun.svg
[2]: https://microbadger.com/images/xtaci/kcptun
[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
@@ -10,16 +10,16 @@
[8]: https://raw.githubusercontent.com/xtaci/kcptun/master/LICENSE.md
[9]: https://img.shields.io/github/stars/xtaci/kcptun.svg
[10]: https://github.com/xtaci/kcptun/stargazers
[11]: https://img.shields.io/github/forks/xtaci/kcptun.svg
[12]: https://github.com/xtaci/kcptun/network
[11]: https://img.shields.io/badge/license-MIT-blue.svg
[12]: LICENSE.md
[13]: https://img.shields.io/github/release/xtaci/kcptun.svg
[14]: https://github.com/xtaci/kcptun/releases/latest
[15]: https://img.shields.io/github/downloads/xtaci/kcptun/total.svg?maxAge=2592000
[15]: https://img.shields.io/github/downloads/xtaci/kcptun/total.svg?maxAge=1800
[16]: https://github.com/xtaci/kcptun/releases
[17]: https://img.shields.io/badge/KCP-Powered-blue.svg
[18]: https://github.com/skywind3000/kcp
[19]: https://img.shields.io/docker/pulls/xtaci/kcptun.svg?maxAge=2592000
[20]: https://hub.docker.com/r/xtaci/kcptun/
[19]: https://badges.gitter.im/xtaci/kcptun.svg
[20]: https://gitter.im/xtaci/kcptun?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
A tool for converting tcp stream into kcp+udp stream, :zap: ***[download address](https://github.com/xtaci/kcptun/releases/latest)***:zap:
@@ -28,31 +28,122 @@ A tool for converting tcp stream into kcp+udp stream, :zap: ***[download address
***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 Side: ./server_linux_amd64 -t "127.0.0.1:1080" -l ":554" -mode fast2 // forwarding to local port 1080
Client Side: ./client_darwin_amd64 -r "SERVERIP:554" -l ":1080" -mode fast2 // listening on port 1080
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:
<img src="fast.png" alt="fast.com" height="256px" />
* Speed tested with: https://fast.com
* WAN Link Speed: 100M ADSL
* WIFI: 5GHz TL-WDR3320
### *Usage* :lollipop:
![client](client.png)
![server](server.png)
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:
20160922
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: 1024)
--datashard value set reed-solomon erasure coding - datashard (default: 10)
--parityshard value set reed-solomon erasure coding - parityshard (default: 3)
--dscp value set DSCP(6bit) (default: 0)
--nocomp disable compression
--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:
20160922
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 set reed-solomon erasure coding - datashard (default: 10)
--parityshard value set reed-solomon erasure coding - parityshard (default: 3)
--dscp value set DSCP(6bit) (default: 0)
--nocomp disable compression
--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:
<p align="left"><img src="layeredparams.png" alt="params" height="450px"/></p>
### *Applications* :lollipop:
1. Real-time gaming.
2. Cross-ISP data exchange in PRC.
3. Other lossy network.
### *Parameters Recommended* :lollipop:
```
Test Environment: China Telecom 100M ADSL(100mbps up/8mbps down)
SERVER: -mtu 1400 -sndwnd 2048 -rcvwnd 2048 -mode fast2
CLIENT: -mtu 1400 -sndwnd 256 -rcvwnd 2048 -mode fast2 -dscp 46
```
### *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 1Increase client rcvwnd & server sndwnd simultaneously & gradually。
> Step 2Try 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***
### *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.***
@@ -84,6 +175,7 @@ Manual control is supported with hidden parameters, you must understand KCP prot
```
-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 ReedSolomon code belongs to the class of non-binary cyclic error-correcting codes. The ReedSolomon code is based on univariate polynomials over finite fields.
@@ -92,7 +184,7 @@ It is able to detect and correct multiple symbol errors. By adding t check symbo
![reed-solomon](rs.png)
Setting parameters of RS-Code with ```-datashard 10 -parityshard 3```
Setting parameters of RS-Code with ```-datashard m -parityshard n```
### *Snappy Stream Compression* :lollipop:
> Snappy is a compression/decompression library. It does not aim for maximum
@@ -106,6 +198,8 @@ Setting parameters of RS-Code with ```-datashard 10 -parityshard 3```
disable compression by setting ```-nocomp``` on both side.
> Tips: Turning off compression may reduce latency.
### *SNMP* :lollipop:
```go
// Snmp defines network statistics indicator
@@ -135,24 +229,10 @@ type Snmp struct {
Sending a signal by ```kill -SIGUSR1 pid``` will give SNMP information for KCPuseful for fine-grained adjustment.
Of which ```RetransSegs,FastRetransSegs,LostSegs,OutSegs``` is the most useful.
### *Performance* :lollipop:
```
root@vultr:~# iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 4.00 MByte (default)
------------------------------------------------------------
[ 4] local 172.7.7.1 port 5001 connected with 172.7.7.2 port 55453
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-18.0 sec 5.50 MBytes 2.56 Mbits/sec <-- connection via kcptun
[ 5] local 45.32.xxx.xxx port 5001 connected with 218.88.xxx.xxx port 17220
[ 5] 0.0-17.9 sec 2.12 MBytes 997 Kbits/sec <-- direct connnection via tcp
```
### *Donations* :dollar:
![donate](donate.png)
All donations to this project will be used on the R&D of [gonet/2](http://gonet2.github.io/).
Best wishes to you all.
### *References* :paperclip:
1. https://github.com/skywind3000/kcp -- KCP - A Fast and Reliable ARQ Protocol.
+266 -113
View File
@@ -1,82 +1,238 @@
# <img src="logo.png" alt="kcptun" height="60px" />
[![GoDoc][1]][2] [![Release][13]][14] [![Powered][17]][18] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Downloads][15]][16]
[1]: https://godoc.org/github.com/xtaci/kcptun?status.svg
[2]: https://godoc.org/github.com/xtaci/kcptun
<p align="center"><img src="logo.png" alt="kcptun" height="60px" /></p>
<p align="center"><em>A Simple UDP Tunnel Based On KCP</em></p>
-
[![Release][13]][14] [![Powered][17]][18] [![MIT licensed][11]][12] [![Build Status][3]][4] [![Go Report Card][5]][6] [![Downloads][15]][16] [![Gitter][19]][20] [![Docker][1]][2]
[1]: https://images.microbadger.com/badges/image/xtaci/kcptun.svg
[2]: https://microbadger.com/images/xtaci/kcptun
[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/license-MIT-blue.svg
[8]: https://raw.githubusercontent.com/xtaci/kcptun/master/LICENSE.md
[9]: https://img.shields.io/github/stars/xtaci/kcptun.svg
[10]: https://github.com/xtaci/kcptun/stargazers
[11]: https://img.shields.io/github/forks/xtaci/kcptun.svg
[12]: https://github.com/xtaci/kcptun/network
[11]: https://img.shields.io/badge/license-MIT-blue.svg
[12]: LICENSE.md
[13]: https://img.shields.io/github/release/xtaci/kcptun.svg
[14]: https://github.com/xtaci/kcptun/releases/latest
[15]: https://img.shields.io/github/downloads/xtaci/kcptun/total.svg?maxAge=1800
[16]: https://github.com/xtaci/kcptun/releases
[17]: https://img.shields.io/badge/KCP-Powered-blue.svg
[18]: https://github.com/skywind3000/kcp
[19]: https://img.shields.io/docker/pulls/xtaci/kcptun.svg?maxAge=2592000
[20]: https://hub.docker.com/r/xtaci/kcptun/
***TCP端口加速器 :zap: [官方下载地址](https://github.com/xtaci/kcptun/releases/latest):zap:***
[19]: https://badges.gitter.im/xtaci/kcptun.svg
[20]: https://gitter.im/xtaci/kcptun?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
![kcptun](kcptun.png)
[English Readme](README.en.md)
### *快速设定* :lollipop:
<p align="center"><img src="kcptun.png" alt="kcptun" height="200px"/></p>
<p align="center"><a href="https://github.com/xtaci/kcptun/releases/latest">立即安装</a></p>
<p align="center"><em>支持macOS/Linux/Windows/FreeBSD/ARM/Raspberry Pi/OpenWrt</em></p>
<p align="right"><a href="https://github.com/xtaci/kcptun/blob/master/README.en.md">ENG</a></p>
-
### 手动编译
```
服务器: ./server_linux_amd64 -t "127.0.0.1:1080" -l ":554" -mode fast2 // 转发到本地1080端口
客户端: ./client_darwin_amd64 -r "服务器IP地址:554" -l ":1080" -mode fast2 // 监听本地1080端口
$go get -u github.com/xtaci/kcptun/client
$go get -u github.com/xtaci/kcptun/server
```
注意: 如果出现错误提示,请确保依赖库能正确访问到。
Release中的所有二进制版本,是通过 `build-release.sh` 脚本生成并优化。
### 快速设定
客户端、服务器分别**下载**对应平台的二进制压缩包,并**解压**,通过下面的命令**启动**端口转发。
```
服务器: ./server_linux_amd64 -t "服务器IP地址:8388" -l ":4000" -mode fast2
客户端: ./client_darwin_amd64 -r "服务器IP地址:4000" -l ":8388" -mode fast2
```
以上命令可以实现8388/tcp端口的转发(通过4000/udp端口)。
### 速度对比
<img src="fast.png" alt="fast.com" height="256px" />
* 测速网站: https://fast.com
* 接入速度: 100Mbps
* WIFI: 5GHz TL-WDR3320
### 使用方法
在Mac OS X El Capitan下的帮助输出,注意默认值:
```
$ ./client_darwin_amd64 -h
NAME:
kcptun - client(with SMUX)
USAGE:
client_darwin_amd64 [global options] command [command options] [arguments...]
VERSION:
20161025
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: 1024)
--datashard value set reed-solomon erasure coding - datashard (default: 10)
--parityshard value set reed-solomon erasure coding - parityshard (default: 3)
--dscp value set DSCP(6bit) (default: 0)
--nocomp disable compression
--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:
20161025
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 set reed-solomon erasure coding - datashard (default: 10)
--parityshard value set reed-solomon erasure coding - parityshard (default: 3)
--dscp value set DSCP(6bit) (default: 0)
--nocomp disable compression
--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
```
#### 分层参数图
<p align="left"><img src="layeredparams.png" alt="params" height="450px"/></p>
**两端参数必须一致的有**:
* datashard --前向纠错
* parityshard --前向纠错
* nocomp --压缩
* key --密钥
* crypt --加密算法
其余为两边可独立设定的参数
### 内置模式
响应速度:
*fast3 > fast2 >* **[fast]** *> normal > default*
有效载荷比:
*default > normal >* **[fast]** *> fast2 > fast3*
中间-mode参数比较均衡,总之就是越快,包重传越激进。
更高级的 **手动档** 需要理解KCP协议,并通过 **隐藏参数** 调整,例如:
```
-mode manual -nodelay 1 -resend 2 -nc 1 -interval 20
```
### *使用方法* :lollipop:
在Mac OS X El Capitan下的帮助输出:
* 搭配1. fast + FEC(5,5)
* 搭配2. fast2 + FEC(10,3)
* 搭配3. fast2 + FEC(0,0)
![client](client.png)
![server](server.png)
默认profile参考: https://github.com/xtaci/kcptun/blob/master/client/main.go#L248
### *推荐参数* :lollipop:
```
适用大部分ADSL接入(非对称上下行)的参数(实验环境电信100M ADSL)
其它带宽请按比例调整,比如 50M ADSL,把 CLIENT 的 -sndwnd -rcvwnd 减掉一半,SERVER 不变
### 前向纠错
SERVER: -mtu 1400 -sndwnd 2048 -rcvwnd 2048 -mode fast2
CLIENT: -mtu 1400 -sndwnd 256 -rcvwnd 2048 -mode fast2 -dscp 46
*巭孬嫑乱动*
```
前向纠错采用Reed Solomon纠删码, 它的基本原理如下: 给定n个数据块d1, d2,…, dn,n和一个正整数m, RS根据n个数据块生成m个校验块, c1, c2,…, cm。 对于任意的n和m, 从n个原始数据块和m 个校验块中任取n块就能解码出原始数据, 即RS最多**容忍m个数据块或者校验块同时丢失**。
![reed-solomon](rs.png)
通过参数```-datashard n -parityshard m``` 在两端同时设定。
数据包发送顺序严格遵循: n个datashard紧接m个parityshard,重复。
注意:为了发挥FEC最佳效果,设置 parityshard/(parity+datashard) > packet loss,比如5/(5+5) > 30%
### 窗口调整
**简易窗口自我调优方法**
*简易自我调优方法*
> 第一步:同时在两端逐步增大client rcvwnd和server sndwnd;
> 第二步:尝试下载,观察如果带宽利用率(服务器+客户端两端都要观察)接近物理带宽则停止,否则跳转到第一步。
> 第二步:尝试下载,观察如果带宽利用率(服务器+客户端两端都要观察)到达预期则停止,否则跳转到第一步。
**注意:产生大量重传时,一定是窗口偏大了**
### 安全
无论你上层如何加密,如果```-crypt none```,那么**协议头部**都是**明文**的,建议至少采用```-crypt aes-128```加密,并修改密码。
密码可以通过`-key`指定,也可以通过环境变量`KCPTUN_KEY`指定。
注意: ```-crypt xor``` 也是不安全的,除非你知道你在做什么。
附加密速度Benchmark
*带宽计算公式*
```
在不丢包的情况下,有最大-rcvwnd 个数据包在网络上正在向你传输,以平均数据包大小avgsize计算,在任意时刻,有:
network_cap = rcvwnd*avgsize
数据流向你,这个值再除以ping值(rtt),等于最大带宽使用量。
max_bandwidth = network_cap/rtt = rcvwnd*avgsize/rtt
举例,设rcvwnd = 1024, avgsize = 1KB, rtt = 400ms,则:
max_bandwidth = 1024 * 1KB / 400ms = 2.5MB/s ~= 25Mbps
(注:以上计算不包括前向纠错的数据量)
前向纠错是最大带宽量的一个固定比例增加:
max_bandwidth_fec = max_bandwidth*(datashard+parityshard)/datashard
举例,设datashard = 10 , partiyshard = 3,则:
max_bandwidth_fec = max_bandwidth * (10 + 3) /10 = 1.3*max_bandwidth 1.3 * 25Mbps = 32.5Mbps
BenchmarkAES128-4 200000 11182 ns/op
BenchmarkAES192-4 200000 12699 ns/op
BenchmarkAES256-4 100000 13757 ns/op
BenchmarkTEA-4 50000 26441 ns/op
BenchmarkSimpleXOR-4 3000000 441 ns/op
BenchmarkBlowfish-4 30000 48036 ns/op
BenchmarkNone-4 20000000 106 ns/op
BenchmarkCast5-4 20000 60222 ns/op
BenchmarkTripleDES-4 2000 878759 ns/op
BenchmarkTwofish-4 20000 68501 ns/op
BenchmarkXTEA-4 20000 77417 ns/op
BenchmarkSalsa20-4 300000 4998 ns/op
```
### *流量控制* :lollipop:
***必要性: 针对流量敏感的服务器,做双保险。***
### 内存控制
路由器,手机等嵌入式设备通常对**内存用量敏感**,通过调节环境变量GOGC(例如GOGC=20)后启动client,可以降低内存使用。
参考:https://blog.golang.org/go15gc
### DSCP
DSCP差分服务代码点(Differentiated Services Code Point),IETF于1998年12月发布了Diff-ServDifferentiated Service)的QoS分类标准。它在每个数据包IP头部的服务类别TOS标识字节中,利用已使用的**6比特**和未使用的2比特,通过编码值来区分优先级。
常用DSCP值可以参考[Wikipedia DSCP](https://en.wikipedia.org/wiki/Differentiated_services#Commonly_used_DSCP_values),至于有没有用,完全取决于数据包经过的设备。
通过 ```-dscp ``` 参数指定dscp值,两端可分别设定。
注意:设置dscp不一定会更好,需要尝试。
### Snappy数据流压缩
> 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/
压缩对于非加密,非压缩的数据能降低传输数据量,比如点对点的HTTP数据转发。
通过参数 ```-nocomp``` 在两端同时设定以关闭压缩。
> 提示: 关闭压缩可能会降低延迟。
### 流量控制
**必要性: 针对流量敏感的服务器,做双保险。**
> 基本原则: SERVER的发送速率不能超过ADSL下行带宽,否则只会浪费您的服务器带宽。
@@ -93,44 +249,8 @@ root@kcptun:~#
```
其中eth0为网卡,有些服务器为ens3,有些为p2p1,通过ifconfig查询修改。
### SNMP
### *DSCP* :lollipop:
DSCP差分服务代码点(Differentiated Services Code Point),IETF于1998年12月发布了Diff-ServDifferentiated Service)的QoS分类标准。它在每个数据包IP头部的服务类别TOS标识字节中,利用已使用的6比特和未使用的2比特,通过编码值来区分优先级。
常用DSCP值可以参考[Wikipedia DSCP](https://en.wikipedia.org/wiki/Differentiated_services#Commonly_used_DSCP_values),至于有没有用,完全取决于数据包经过的设备。
通过 ```-dscp ``` 参数指定dscp值,两端可分别设定。
### *前向纠错* :lollipop:
前向纠错采用Reed Solomon纠删码, 它的基本原理如下: 给定n个数据块d1, d2,…, dn,n和一个正整数m, RS根据n个数据块生成m个校验块, c1, c2,…, cm。 对于任意的n和m, 从n个原始数据块和m 个校验块中任取n块就能解码出原始数据, 即RS最多容忍m个数据块或者校验块同时丢失。
![reed-solomon](rs.png)
通过参数```-datashard 10 -parityshard 3``` 在两端同时设定。
### *Snappy数据流压缩* :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/
通过参数 ```-nocomp``` 在两端同时设定以关闭压缩。
### *内置模式* :lollipop:
响应速度:
*fast3 >* ***[fast2]*** *> fast > normal > default*
有效载荷比:
*default > normal > fast >* ***[fast2]*** *> fast3*
中间mode参数比较均衡,总之就是越快越浪费带宽,推荐模式 ***fast2***
更高级的 ***手动档*** 需要理解KCP协议,并通过 ***隐藏参数*** 调整,例如:
```
-mode manual -nodelay 1 -resend 2 -nc 1 -interval 20
```
### *SNMP* :lollipop:
```go
// Snmp defines network statistics indicator
type Snmp struct {
@@ -156,44 +276,76 @@ type Snmp struct {
}
```
使用```kill -SIGUSR1 pid``` 可以在控制台打印出SNMP信息,通常用于精细调整***当前链路的有效载荷比***
观察```RetransSegs,FastRetransSegs,LostSegs,OutSegs```这几者的数值比例,用于参考调整```-mode manual,fec```的参数。
使用```kill -SIGUSR1 pid``` 可以在控制台打印出SNMP信息,通常用于精细调整**当前链路的有效载荷比**。
观察```RetransSegs,FastRetransSegs,LostSegs,OutSegs```这几者的数值比例,用于参考调整```-mode manual,fec```的参数。
#### 带宽计算公式
### *性能对比* :lollipop:
```
root@vultr:~# iperf -s
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 4.00 MByte (default)
------------------------------------------------------------
[ 4] local 172.7.7.1 port 5001 connected with 172.7.7.2 port 55453
[ ID] Interval Transfer Bandwidth
[ 4] 0.0-18.0 sec 5.50 MBytes 2.56 Mbits/sec <-- connection via kcptun
[ 5] local 45.32.xxx.xxx port 5001 connected with 218.88.xxx.xxx port 17220
[ 5] 0.0-17.9 sec 2.12 MBytes 997 Kbits/sec <-- direct connnection via tcp
在不丢包的情况下,有最大-rcvwnd 个数据包在网络上正在向你传输,以平均数据包大小avgsize计算,在任意时刻,有:
network_cap = rcvwnd*avgsize
数据流向你,这个值再除以ping值(rtt),等于最大带宽使用量。
max_bandwidth = network_cap/rtt = rcvwnd*avgsize/rtt
举例,设rcvwnd = 1024, avgsize = 1KB, rtt = 400ms,则:
max_bandwidth = 1024 * 1KB / 400ms = 2.5MB/s ~= 25Mbps
(注:以上计算不包括前向纠错的数据量)
前向纠错是最大带宽量的一个固定比例增加:
max_bandwidth_fec = max_bandwidth*(datashard+parityshard)/datashard
举例,设datashard = 10 , partiyshard = 3,则:
max_bandwidth_fec = max_bandwidth * (10 + 3) /10 = 1.3*max_bandwidth 1.3 * 25Mbps = 32.5Mbps
```
### *故障排除* :lollipop:
> Q: 客户端和服务器端***皆无*** ```stream opened```信息。
### 故障排除
> Q: 客户端和服务器端**皆无** ```stream opened```信息。
> A: 连接客户端程序的端口设置错误。
> Q: 客户端有 ```stream opened```信息,服务器端没有。
> A: 连接服务器的端口设置错误,或者被防火墙拦截。
> Q: 客户端服务器***皆有*** ```stream opened```信息,但无法通信。
> Q: 客户端服务器**皆有** ```stream opened```信息,但无法通信。
> A: 上层软件的设定错误。
### *免责申明* :warning:
用户以各种方式使用本软件(包括但不限于修改使用、直接使用、通过第三方使用)的过程中,不得以任何方式利用本软件直接或间接从事违反中国法律、以及社会公德的行为。软件的使用者需对自身行为负责,因使用软件引发的一切纠纷,由使用者承担全部法律及连带责任。作者不承担任何法律及连带责任。
### 免责申明
对免责声明的解释、修改及更新权均属于作者本人所有。
**用户以各种方式使用本软件(包括但不限于修改使用、直接使用、通过第三方使用)的过程中,不得以任何方式利用本软件直接或间接从事违反中国法律、以及社会公德的行为。软件的使用者需对自身行为负责,因使用软件引发的一切纠纷,由使用者承担全部法律及连带责任。作者不承担任何法律及连带责任。**
**对免责声明的解释、修改及更新权均属于作者本人所有。**
### 捐赠
### *捐赠* :dollar:
![donate](donate.png)
对该项目的捐款将用于[gonet/2](http://gonet2.github.io/)游戏服务器框架的研发。
### 特别鸣谢
> 郑H立, 南东风, Li, 七七, 凌君, 昶,LesMiserables, KyOn, 噼里啪啦, 继斌, 小苍辛苦, **Ken**,
> 乔槁, 佳晨, 猪肉佬, lcx, 昊文, 冰峰, 凡, alex, **海豹叔叔**, 奥姐, 张冰, 司成,
> 武子, **慎**Alex43211**Coxxs**,荣,NeroNg,吴骁,定一,我不是林JPatrick, 超, 陈,windfarer, 宇,
> 今晶,斌,晓东,最后一缕阳光,亮,Ethan,一心不乱,allenm,冬卯,GELATO,用户1Butterfly,光子曲面,
> 丞佳,捉鱼,TalonBiny,李勇,***阿彪***
好人一生平安!
### 相关软件
1. https://github.com/bettermanbao/openwrt-kcptun
2. https://github.com/EasyPi/openwrt-kcptun
3. https://github.com/kuoruan/luci-app-kcptun
4. https://github.com/dfdragon/kcptun_gclient
5. https://github.com/dfdragon/kcptun_xclient
### 参考资料
### *参考资料* :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.
@@ -207,3 +359,4 @@ TCP window size: 4.00 MByte (default)
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/LARTC-zh_CN.GB2312.pdf -- Linux Advanced Routing & Traffic Control
14. https://en.wikipedia.org/wiki/Noisy-channel_coding_theorem -- Noisy channel coding theorem
+17 -4
View File
@@ -12,6 +12,7 @@ fi
VERSION=`date -u +%Y%m%d`
LDFLAGS="-X main.VERSION=$VERSION -s -w"
GCFLAGS=""
OSES=(linux darwin windows freebsd)
ARCHS=(amd64 386)
@@ -22,8 +23,8 @@ for os in ${OSES[@]}; do
then
suffix=".exe"
fi
env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -o client_${os}_${arch}${suffix} github.com/xtaci/kcptun/client
env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -o server_${os}_${arch}${suffix} github.com/xtaci/kcptun/server
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
@@ -33,9 +34,21 @@ 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" -o client_linux_arm$v github.com/xtaci/kcptun/client
env CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=$v go build -ldflags "$LDFLAGS" -o server_linux_arm$v github.com/xtaci/kcptun/server
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
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

+44
View File
@@ -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)
}
+303 -100
View File
@@ -2,6 +2,8 @@ package main
import (
"crypto/sha1"
"encoding/csv"
"fmt"
"io"
"log"
"math/rand"
@@ -12,9 +14,10 @@ import (
"golang.org/x/crypto/pbkdf2"
"github.com/golang/snappy"
"github.com/hashicorp/yamux"
"github.com/pkg/errors"
"github.com/urfave/cli"
"github.com/xtaci/kcp-go"
kcp "github.com/xtaci/kcp-go"
"github.com/xtaci/smux"
)
var (
@@ -52,7 +55,12 @@ func newCompStream(conn net.Conn) *compStream {
return c
}
func handleClient(p1, p2 io.ReadWriteCloser) {
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()
@@ -60,16 +68,10 @@ func handleClient(p1, p2 io.ReadWriteCloser) {
// start tunnel
p1die := make(chan struct{})
go func() {
io.Copy(p1, p2)
close(p1die)
}()
go func() { io.Copy(p1, p2); close(p1die) }()
p2die := make(chan struct{})
go func() {
io.Copy(p2, p1)
close(p2die)
}()
go func() { io.Copy(p2, p1); close(p2die) }()
// wait for tunnel termination
select {
@@ -80,16 +82,20 @@ func handleClient(p1, p2 io.ReadWriteCloser) {
func checkError(err error) {
if err != nil {
log.Println(err)
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 = "kcptun client"
myApp.Usage = "client(with SMUX)"
myApp.Version = VERSION
myApp.Flags = []cli.Flag{
cli.StringFlag{
@@ -105,28 +111,33 @@ func main() {
cli.StringFlag{
Name: "key",
Value: "it's a secrect",
Usage: "key for communcation, must be the same as kcptun server",
Usage: "pre-shared secret between client and server",
EnvVar: "KCPTUN_KEY",
},
cli.StringFlag{
Name: "crypt",
Value: "aes",
Usage: "methods for encryption: aes, tea, xor, none",
Usage: "aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none",
},
cli.StringFlag{
Name: "mode",
Value: "fast",
Usage: "mode for communication: fast3, fast2, fast, normal",
Usage: "profiles: fast3, fast2, fast, normal",
},
cli.IntFlag{
Name: "conn",
Value: 1,
Usage: "establish N physical connections as specified by 'conn' to server",
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 MTU of UDP packets, suggest 'tracepath' to discover path mtu",
Usage: "set maximum transmission unit for UDP packets",
},
cli.IntFlag{
Name: "sndwnd",
@@ -135,13 +146,9 @@ func main() {
},
cli.IntFlag{
Name: "rcvwnd",
Value: 1024,
Value: 512,
Usage: "set receive window size(num of packets)",
},
cli.BoolFlag{
Name: "nocomp",
Usage: "disable compression",
},
cli.IntFlag{
Name: "datashard",
Value: 10,
@@ -152,16 +159,20 @@ func main() {
Value: 3,
Usage: "set reed-solomon erasure coding - parityshard",
},
cli.BoolFlag{
Name: "acknodelay",
Usage: "flush ack immediately when a packet is received",
Hidden: true,
},
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,
@@ -182,103 +193,295 @@ func main() {
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", c.String("localaddr"))
addr, err := net.ResolveTCPAddr("tcp", config.LocalAddr)
checkError(err)
listener, err := net.ListenTCP("tcp", addr)
checkError(err)
pass := pbkdf2.Key([]byte(c.String("key")), []byte(SALT), 4096, 32, sha1.New)
// kcp server
nodelay, interval, resend, nc := c.Int("nodelay"), c.Int("interval"), c.Int("resend"), c.Int("nc")
switch c.String("mode") {
case "normal":
nodelay, interval, resend, nc = 0, 30, 2, 1
case "fast":
nodelay, interval, resend, nc = 0, 20, 2, 1
case "fast2":
nodelay, interval, resend, nc = 1, 20, 2, 1
case "fast3":
nodelay, interval, resend, nc = 1, 10, 2, 1
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:", c.String("crypt"))
log.Println("nodelay parameters:", nodelay, interval, resend, nc)
log.Println("remote address:", c.String("remoteaddr"))
log.Println("sndwnd:", c.Int("sndwnd"), "rcvwnd:", c.Int("rcvwnd"))
log.Println("compression:", !c.Bool("nocomp"))
log.Println("mtu:", c.Int("mtu"))
log.Println("datashard:", c.Int("datashard"), "parityshard:", c.Int("parityshard"))
log.Println("acknodelay:", c.Bool("acknodelay"))
log.Println("dscp:", c.Int("dscp"))
log.Println("conn:", c.Int("conn"))
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)
createConn := func() *yamux.Session {
var block kcp.BlockCrypt
switch c.String("crypt") {
case "tea":
block, _ = kcp.NewTEABlockCrypt(pass[:16])
case "xor":
block, _ = kcp.NewSimpleXORBlockCrypt(pass)
case "none":
block, _ = kcp.NewNoneBlockCrypt(pass)
default:
block, _ = kcp.NewAESBlockCrypt(pass)
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)
}
kcpconn, err := kcp.DialWithOptions(c.String("remoteaddr"), block, c.Int("datashard"), c.Int("parityshard"))
checkError(err)
kcpconn.SetNoDelay(nodelay, interval, resend, nc)
kcpconn.SetWindowSize(c.Int("sndwnd"), c.Int("rcvwnd"))
kcpconn.SetMtu(c.Int("mtu"))
kcpconn.SetACKNoDelay(c.Bool("acknodelay"))
kcpconn.SetDSCP(c.Int("dscp"))
// stream multiplex
config := &yamux.Config{
AcceptBacklog: 256,
EnableKeepAlive: true,
KeepAliveInterval: 30 * time.Second,
ConnectionWriteTimeout: 30 * time.Second,
MaxStreamWindowSize: 16777216,
LogOutput: os.Stderr,
}
var session *yamux.Session
if c.Bool("nocomp") {
session, err = yamux.Client(kcpconn, config)
var session *smux.Session
if config.NoComp {
session, err = smux.Client(kcpconn, smuxConfig)
} else {
session, err = yamux.Client(newCompStream(kcpconn), config)
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)
return session
}
numconn := uint16(c.Int("conn"))
var muxes []*yamux.Session
for i := uint16(0); i < numconn; i++ {
muxes = append(muxes, createConn())
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()
checkError(err)
mux := muxes[rr%numconn]
p2, err := mux.Open()
if err != nil { // yamux failure
log.Println(err)
p1.Close()
mux.Close()
muxes[rr%numconn] = createConn()
continue
if err != nil {
log.Fatalln(err)
}
go handleClient(p1, p2)
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++
}
return nil
}
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()
}
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"os/signal"
"syscall"
"github.com/xtaci/kcp-go"
kcp "github.com/xtaci/kcp-go"
)
func init() {
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

+42
View File
@@ -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)
}
+214 -79
View File
@@ -2,6 +2,8 @@ package main
import (
"crypto/sha1"
"encoding/csv"
"fmt"
"io"
"log"
"math/rand"
@@ -12,9 +14,9 @@ import (
"golang.org/x/crypto/pbkdf2"
"github.com/golang/snappy"
"github.com/hashicorp/yamux"
"github.com/urfave/cli"
"github.com/xtaci/kcp-go"
kcp "github.com/xtaci/kcp-go"
"github.com/xtaci/smux"
)
var (
@@ -53,35 +55,33 @@ func newCompStream(conn net.Conn) *compStream {
}
// handle multiplex-ed connection
func handleMux(conn io.ReadWriteCloser, target string) {
func handleMux(conn io.ReadWriteCloser, config *Config) {
// stream multiplex
var mux *yamux.Session
config := &yamux.Config{
AcceptBacklog: 256,
EnableKeepAlive: true,
KeepAliveInterval: 30 * time.Second,
ConnectionWriteTimeout: 30 * time.Second,
MaxStreamWindowSize: 16777216,
LogOutput: os.Stderr,
}
m, err := yamux.Server(conn, config)
smuxConfig := smux.DefaultConfig()
smuxConfig.MaxReceiveBuffer = config.SockBuf
mux, err := smux.Server(conn, smuxConfig)
if err != nil {
log.Println(err)
return
}
mux = m
defer mux.Close()
for {
p1, err := mux.Accept()
p1, err := mux.AcceptStream()
if err != nil {
log.Println(err)
return
}
p2, err := net.DialTimeout("tcp", target, 5*time.Second)
p2, err := net.DialTimeout("tcp", config.Target, 5*time.Second)
if err != nil {
p1.Close()
log.Println(err)
return
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)
}
@@ -95,16 +95,10 @@ func handleClient(p1, p2 io.ReadWriteCloser) {
// start tunnel
p1die := make(chan struct{})
go func() {
io.Copy(p1, p2)
close(p1die)
}()
go func() { io.Copy(p1, p2); close(p1die) }()
p2die := make(chan struct{})
go func() {
io.Copy(p2, p1)
close(p2die)
}()
go func() { io.Copy(p2, p1); close(p2die) }()
// wait for tunnel termination
select {
@@ -113,11 +107,22 @@ func handleClient(p1, p2 io.ReadWriteCloser) {
}
}
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 = "kcptun server"
myApp.Usage = "server(with SMUX)"
myApp.Version = VERSION
myApp.Flags = []cli.Flag{
cli.StringFlag{
@@ -133,23 +138,23 @@ func main() {
cli.StringFlag{
Name: "key",
Value: "it's a secrect",
Usage: "key for communcation, must be the same as kcptun client",
Usage: "pre-shared secret between client and server",
EnvVar: "KCPTUN_KEY",
},
cli.StringFlag{
Name: "crypt",
Value: "aes",
Usage: "methods for encryption: aes, tea, xor, none",
Usage: "aes, aes-128, aes-192, salsa20, blowfish, twofish, cast5, 3des, tea, xtea, xor, none",
},
cli.StringFlag{
Name: "mode",
Value: "fast",
Usage: "mode for communication: fast3, fast2, fast, normal",
Usage: "profiles: fast3, fast2, fast, normal",
},
cli.IntFlag{
Name: "mtu",
Value: 1350,
Usage: "set MTU of UDP packets, suggest 'tracepath' to discover path mtu",
Usage: "set maximum transmission unit for UDP packets",
},
cli.IntFlag{
Name: "sndwnd",
@@ -161,10 +166,6 @@ func main() {
Value: 1024,
Usage: "set receive window size(num of packets)",
},
cli.BoolFlag{
Name: "nocomp",
Usage: "disable compression",
},
cli.IntFlag{
Name: "datashard",
Value: 10,
@@ -175,16 +176,20 @@ func main() {
Value: 3,
Usage: "set reed-solomon erasure coding - parityshard",
},
cli.BoolFlag{
Name: "acknodelay",
Usage: "flush ack immediately when a packet is received",
Hidden: true,
},
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,
@@ -205,66 +210,196 @@ func main() {
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 {
log.Println("version:", VERSION)
nodelay, interval, resend, nc := c.Int("nodelay"), c.Int("interval"), c.Int("resend"), c.Int("nc")
switch c.String("mode") {
case "normal":
nodelay, interval, resend, nc = 0, 30, 2, 1
case "fast":
nodelay, interval, resend, nc = 0, 20, 2, 1
case "fast2":
nodelay, interval, resend, nc = 1, 20, 2, 1
case "fast3":
nodelay, interval, resend, nc = 1, 10, 2, 1
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)
}
pass := pbkdf2.Key([]byte(c.String("key")), []byte(SALT), 4096, 32, sha1.New)
// 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 c.String("crypt") {
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(c.String("listen"), block, c.Int("datashard"), c.Int("parityshard"))
if err != nil {
log.Fatal(err)
}
log.Println("listening on ", lis.Addr())
log.Println("encryption:", c.String("crypt"))
log.Println("nodelay parameters:", nodelay, interval, resend, nc)
log.Println("sndwnd:", c.Int("sndwnd"), "rcvwnd:", c.Int("rcvwnd"))
log.Println("compression:", !c.Bool("nocomp"))
log.Println("mtu:", c.Int("mtu"))
log.Println("datashard:", c.Int("datashard"), "parityshard:", c.Int("parityshard"))
log.Println("acknodelay:", c.Bool("acknodelay"))
log.Println("dscp:", c.Int("dscp"))
for {
if conn, err := lis.Accept(); err == nil {
log.Println("remote address:", conn.RemoteAddr())
conn.SetNoDelay(nodelay, interval, resend, nc)
conn.SetMtu(c.Int("mtu"))
conn.SetWindowSize(c.Int("sndwnd"), c.Int("rcvwnd"))
conn.SetACKNoDelay(c.Bool("acknodelay"))
conn.SetDSCP(c.Int("dscp"))
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 c.Bool("nocomp") {
go handleMux(conn, c.String("target"))
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), c.String("target"))
go handleMux(newCompStream(conn), &config)
}
} else {
log.Println(err)
log.Printf("%+v", err)
}
}
return nil
}
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()
}
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ import (
"os/signal"
"syscall"
"github.com/xtaci/kcp-go"
kcp "github.com/xtaci/kcp-go"
)
func init() {