menu Chancel's blog
rss_feed
Chancel's blog
我就是这样的人

Kcptun - 如何降低VPS网络延迟

作者:Chancel, 更新:2022 Dec 14, 字数:8111, 已阅:1569

1. 背景

作为正常用途的VPS,如果不想备案的话,香港VPS是非常不错的选择,但香港VPS的性价比不太高,宽带小水管。

如果需要大宽带,则可以选择其他国外地区的VPS,但相对来说延迟就会高不少,对于没有CN2路线的VPS来讲,那VPS的延迟几乎等于残废。

有什么办法可以降低网络延迟呢?答案是有的,那就是Kcptun

2. Kcptun

2.1. 介绍

Kcptun早期是作为go语言版本实现kcp协议的建议测试工具,作为端口转发工具出现,目前是一个开源的加速软件

我的理解是Kcptun本质上是将TCP包转换为UDP来实现TCP流加速,但会提高带宽的消耗量

KCP的架设需要一个客户端一个服务端,如图所示(图来自Github项目介绍)

掌握Kcptun实现的理论知识复杂,如有兴趣,可以参考官方的仓库xtaci/Kcptun下的References

2.2. 部署准备

Kcptun现已支持众多系统,包括Linux/Windows/Solaris等等,也支持ARM架构的系统

xtaci/Kcptun - Release选择适合自己操作系统的包下载即可

下面我假设我需要使用Kcptun来加速SSH服务(SSH延迟高用起来操作就很离谱)

假设本地机器为127.0.0.1 目标服务器IP为172.172.172.72

2.3. 使用

虽然官方仓库README.me巨长,但其实使用方式十分粗暴简单,下载后,解压缩会得到两个文件

  • server_linux_amd64
  • client_linux_amd64

顾名思义就是两个客户端,所有参数官方仓库也列出来了,看起来很长不用怕,看看就好

➜  ~ ./client_linux_amd64 -h
NAME:
   Kcptun - client(with SMUX)

USAGE:
   client_linux_amd64 [global options] command [command options] [arguments...]

VERSION:
   20190924

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, sm4, none (default: "aes")
   --mode value                     profiles: fast3, fast2, fast, normal, manual (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)
   --scavengettl value              set how long an expired connection can live (in seconds) (default: 600)
   --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
   --sockbuf value                  per-socket buffer in bytes (default: 4194304)
   --smuxver value                  specify smux version, available 1,2 (default: 1)
   --smuxbuf value                  the overall de-mux buffer in bytes (default: 4194304)
   --streambuf value                per stream receive buffer in bytes, smux v2+ (default: 2097152)
   --keepalive value                seconds between heartbeats (default: 10)
   --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
   --quiet                          to suppress the 'stream open/close' messages
   --tcp                            to emulate a TCP connection(linux)
   -c value                         config from json file, which will override the command from shell
   --help, -h                       show help
   --version, -v                    print the version

➜  ~ ./server_linux_amd64 -h
NAME:
   Kcptun - server(with SMUX)

USAGE:
   server_linux_amd64 [global options] command [command options] [arguments...]

VERSION:
   20190924

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, or path/to/unix_socket (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, sm4, none (default: "aes")
   --mode value                     profiles: fast3, fast2, fast, normal, manual (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
   --sockbuf value                  per-socket buffer in bytes (default: 4194304)
   --smuxver value                  specify smux version, available 1,2 (default: 1)
   --smuxbuf value                  the overall de-mux buffer in bytes (default: 4194304)
   --streambuf value                per stream receive buffer in bytes, smux v2+ (default: 2097152)
   --keepalive value                seconds between heartbeats (default: 10)
   --snmplog value                  collect snmp to file, aware of timeformat in golang, like: ./snmp-20060102.log
   --snmpperiod value               snmp collect period, in seconds (default: 60)
   --pprof                          start profiling server on :6060
   --log value                      specify a log file to output, default goes to stderr
   --quiet                          to suppress the 'stream open/close' messages
   --tcp                            to emulate a TCP connection(linux)
   -c value                         config from json file, which will override the command from shell
   --help, -h                       show help
   --version, -v                    print the version

在上表中选择自己需要的参数,写成一个Json文件,使用 -c 这个参数就可以直接使用所有参数

下面列出我的SSH服务加速配置文件供参考

我的服务端Json文件

{
  "listen": "172.172.172.72:30022",
  "target":"127.0.0.1:22",
  "key": "keykeykey",
  "crypt": "aes-256-cfb",
  "mtu": 1350,
  "sndwnd": 1024,
  "rcvwnd": 1024,
  "datashard": 10,
  "parityshard": 3,
  "dscp": 0,
  "conn": 1,
  "autoexpire": 60,
  "nocomp": false
}

部分参数解释

  • listen 监听地址与端口
  • key 密钥,客户端服务端必须一致
  • target 目标端口(SSH服务默认就是22端口,即原本直接访问的端口)
  • crypt 加密方式,客户端服务端必须一致
  • mtu 数据包大小

我的客户端Json文件

{
 "mtu": 1400,
 "key": "keykeykey",
 "nocomp": false,
 "remoteaddr": "172.172.172.72:30022",
 "datashard": 10,
 "autoexpire": 60,
 "acknodelay": false,
 "sndwnd": 1024,
 "nc": 0,
 "rcvwnd": 1024,
 "crypt": "aes-256-cfb",
 "dscp": 0,
 "conn": 1,
 "localaddr": "127.0.0.1:40022",
 "nodelay": 0,
 "parityshard": 3
}

部分参数解释

  • remoteaddr 服务端Kcpun监听的地址与端口
  • key 密钥,服务端客户端必须一致
  • crypt 加密方式,客户端服务端必须一致
  • localaddr 本地访问地址(访问这个本地地址,相当于原来访问到的服务端地址,即服务端填写的target参数)

将配置文件保存为config_ssh.json(服务端客户端因不是同一台机器,所以文件名称一致即可,建议保持一定规律,方便区分多个Kcptun应用)

运行方式,

# 服务端运行
server_linux_amd64 -c config_ssh.json
# 客户端运行
client_linux_amd64 -c config_ssh.json

2.4. 测试

执行SSH测试Kcptun连接是否可用

ssh user@127.0.0.1 -p 40022

如有问题,可用查看客户端的Kcptun输出和服务端Kcptun输出(不过服务端如果有输出说明连接是成功的)

2.5. 总结

使用Kcptun可以加速非常多服务,例如SSH/SAMBA/FTP等基础服务,降低延迟效果明显

不过部署可能略显繁琐,运行方法可以考虑使用Supervisor进行部署

Supervisor配置文件参考

[program:Kcptun-ssh]
#directory=/opt/Kcptun/
command=/opt/Kcptun/client_linux_amd64 -c /opt/Kcptun/config_ssh.json
autostart=true
autorestart=true
startsecs=10
stdout_logfile=/var/log/supervisor/Kcptun_ssh_stdout.log
stdout_logfile_maxbytes=5MB
stdout_logfile_backups=5
stdout_capture_maxbytes=1MB
stderr_logfile=/var/log/supervisor/Kcptun_ssh_stderr.log
stderr_logfile_maxbytes=5MB
stderr_logfile_backups=5
stderr_capture_maxbytes=1MB
user = chancel
# environment = HOME="/home/git", USER="git"

[[replyMessage== null?"发表评论":"发表评论 @ " + replyMessage.m_author]]

account_circle
email
web_asset
textsms

评论列表([[messageResponse.total]])

还没有可以显示的留言...
[[messageItem.m_author]] [[messageItem.m_author]]
[[messageItem.create_time]]
[[getEnviron(messageItem.m_environ)]]
[[subMessage.m_author]] [[subMessage.m_author]] @ [[subMessage.parent_message.m_author]] [[subMessage.parent_message.m_author]]
[[subMessage.create_time]]
[[getEnviron(messageItem.m_environ)]]
目录