Kcptun: Enhancement Request: Recreate UDP socket regularly to circumvent QoS

Created on 25 Aug 2016  ·  11Comments  ·  Source: xtaci/kcptun

首先感谢作者,使用两天,看起来这个软件很实用。

似乎很多地区的 ISP 对长时间的udp连接有限速,每次启动 kcptun(或其他udp隧道),
起初速度很快, 一段时间后速度明显下降,虽然延迟仍然平稳,但可用带宽大大缩小。

其QoS的依据很可能是按照 源 和/或 目的端口 相同 判断属于同一个会话 / 同一种应用。

如果能不定时重建 UDP “连接”,(udp确实没有连接一说,但是一个udp会话的源和目的端口是固定的)
或许对提升速度会有帮助。

目的端口有种办法可以这样搞,例如两侧都是linux,
这样设置可以把端口号变成3000-5000之间的一个范围:
客户端:
iptables -t nat -I OUTPUT 1 -d [VPS公网IP] -p udp --dport [SERVER端口] -j DNAT --to-destination [VPS公网IP]:3000-5000 --random
服务端:
iptables -t nat -A PREROUTING -p udp -m multiport --dport 3000:5000 -j REDIRECT --to-ports [kcptun监听端口]

然而除非结束kcptun进程再起一个,否则目前的 kcptun 启动期间无法更换源和目的端口。
如果结束kcptun进程再起一个,那么kcptun承载的tcp必然会断,还要等一段时间的自动重连。
暂时想不到简单易行的办法,所以提出此建议。

All 11 comments

这个方法挺好的,可以定期重连,不影响现有连接,是可行的。

感谢快速的回复!

测试发现 --autoexpire 60 似乎并未起到预期的作用。

测试方法:
客户端增加 --autoexpire 60 参数, 使用iftop观察;
客户端出口路由器使用 show ip nat translations | i [客户端ip] 观察。

预期的结果:
每分钟 udp session 的源端口和目的端口改变一次。 前一个udp session对应nat条目几分钟后老化掉。

实际结果:
5分钟后,从iftop的输出和路由器nat表看到 源和目的端口并无变化。


如下设置, ovpn(static key) over kcptun 可以达到20~30Mbps, 若干小时后将掉到大约 100Kbps

./client_linux_amd64 -l :1949 -r 1.2.3.4:23333 -key XTREMENBL000Gkey! -mtu 1300 -sndwnd 256 -rcvwnd 2048 -mode normal -dscp 46 -conn 2 --autoexpire 60
2016/08/26 15:18:33 version: 20160825
2016/08/26 15:18:33 listening on: [::]:1949
2016/08/26 15:18:33 encryption: aes
2016/08/26 15:18:33 nodelay parameters: 0 30 2 1
2016/08/26 15:18:33 remote address: 1.2.3.4:23333
2016/08/26 15:18:33 sndwnd: 256 rcvwnd: 2048
2016/08/26 15:18:33 compression: true
2016/08/26 15:18:33 mtu: 1300
2016/08/26 15:18:33 datashard: 10 parityshard: 3
2016/08/26 15:18:33 acknodelay: false
2016/08/26 15:18:33 dscp: 46
2016/08/26 15:18:33 sockbuf: 4194304
2016/08/26 15:18:33 keepalive: 10
2016/08/26 15:18:33 conn: 2
2016/08/26 15:18:33 autoexpire: 60
2016/08/26 15:18:36 stream opened
2016/08/26 15:18:37 [ERR] yamux: Failed to read header: snappy: unsupported input
2016/08/26 15:18:37 stream closed
2016/08/26 15:18:42 stream opened
2016/08/26 15:18:45 [ERR] yamux: Failed to read header: snappy: unsupported input
2016/08/26 15:18:45 stream closed
2016/08/26 15:18:50 session shutdown
2016/08/26 15:18:56 stream opened

@siril233 用0826版本,另外,貌似你参数两端对-nocomp配置的不同,他不会中止已经建立好的连接,但对于新的连接,会替换。

@siril233 ovpn长链接是没用的,必须让其定时重启。

两侧都没有-nocomp,但是刚才服务端忘了换新版,可能 [ERR] 因版本不匹配产生。
如果 -nocomp 不匹配,服务端会有很多 “[ERR] yamux: Invalid protocol version: 255”


换了0826版本重新测试,效果符合对新建tcp连接产生新的udp session的预期。
测试方法:
持续连接至少10分钟后,结束其承载的ovpn,
重连,客户端可见日志中出现 autoexpired,源和目的端口均发生变化。


明白了, 就是对于shadowsocks、cow 这类会有明显效果,
但是对类似ovpn的长连接, 可能因为

  1. 实现难度大一些,
  2. 或者需求较少,
  3. 难以避免tun在未使用时由于其承载的tcp长连接的keepalive (一直有少量流量)
    不断替换udp session 而产生(不必要的)行为特征

而没有计划实现它呢。


建议 autoexpired 搞成随机的比较大时间范围而非固定时间。
例如允许如此配置使expire时间在1-30分钟之间。
--autoexpire 60:1800
如果可以启发式地根据丢包率变大而自动调整那就更好了。。。 可能会过于复杂了就。


另外,
ss、cow因为随时发起新的tcp连接,(ss待确认,我以前只搭过一次现在也未在使用所以不确定)
具备强加密和混淆,也未被严厉封锁,
并且tcp受QoS影响较udp小很多,
所以直接使用前述的随机端口方案即可在一定程度上绕过qos。


或许应该新开issue提问。。。
有没有计划 / 有没有可能 实现支持多个 internet连接 上的 failover/aggregation
例如
有 1条电信线路,1条移动线路,1个香港vps,1个新加坡vps
电信线路到香港vps 50ms, 到新加坡vps 300ms+ ;
移动线路到香港vps 300ms+,到新加坡vps 60ms ;
两个vps之间 40ms。

那么玩一套花样:
电信出口 -> 香港vps -> 新加坡vps = 90ms;
移动出口 -> 新加坡vps = 60ms。
(香港vps上直接iptables转发)
有没有可能同时使用这两个连接,国外线路以新加坡vps为出口,
以浪费带宽为代价,规避这两条线路不同程度的
易断流、带宽不稳定、丢包率不稳定、 延迟不稳定等缺陷,
从而实现更大的带宽和更低的丢包率呢?

是可能的,多路复用到一个kcp对象即可, 但偏离了kcp-go的本意了(游戏服务器用), 你可以自己实现。 PS. 这个 --random确实是一个很酷的办法。

@siril233

这是个很有趣的问题,多路复用的平衡,流控,failover,聚合。

以前弄一个项目也观察到这个问题。当时的方案是:
先建立一个 UDPConn,用5分钟,发送与接收都有效,此时端口随机;
暂时不关闭原来的 UDPConn,再加一个 UDPConn。两个 UDPConn都同时接收有效,但第二个发送有效;(原先的UDPConn不再发送,但是对端会有数据继续发送,所以必须接收)
再过5分钟,关闭旧的。(可以认为,对端得到新的 UDPConn 的连接,此时不会给旧的 UDPConn发送消息,可以关闭)
此时再建立一个新的 UDPConn,再循环上述操作。

产生的效果是:
ovpn 这样的长连接,也会动态的改变端口!
每个会话需要两个 UDP 端口。

之前为了简单,用的固定 5 分钟。但固定值可能就是特征。这个是问题。

那么玩一套花样:

这个花样我现在的中间方案是,策略路由。国外ip 走移动到 VPS。

how to configure multi-port acceleration of shadowsocks.

Was this page helpful?
0 / 5 - 0 ratings