xtaci / kcptun

A Quantum-Safe Secure Tunnel based on QPP, KCP, FEC, and N:M multiplexing.
MIT License
13.88k stars 2.54k forks source link

Kcp用着用着偶尔就会断开{伪解决方案} #228

Closed feizhenzhuang closed 7 years ago

feizhenzhuang commented 7 years ago

VPS:搬瓦工 OS :Debian 7.0 x86_64 客户端版本=服务器版本 :0922 ssr版本:3.7.4.1 问题描述:最近这几天当我打开KCP和SS配合翻墙观看youtube视频时,开始没有什么问题,网速也很快,但是过了大概十分钟左右后,突然就不能翻墙了,此时我切换ss直连vps, 经测试连接没有问题。在这种无法使用kcp的情况下,经过大概半小时 我再测试使用kcp配合翻墙,发现又可以使用了。请问这是为什么呢? PS: 我在网上查询相关问题时 有不少人遇到和我类似的问题,有人说是isp封锁了UDP端口 (不知道对错)

谢谢您的帮助,感激不尽 (客户端参数未调整,只是用的ssr版本的shadowsocks,把UDP over TCP 勾选后(见楼下图),经过我接近三个小时的youtube视频播放测试,之前的视频播放一段时间就断开现象没有遇到,之后的几天,该问题也没有遇到。所以我认为这应该算是一个解决方案吧。逃) update:最近我的ssr即使打开 UDP over TCP 也是会看一会视频就断开 过几天试试降低MTU值

xtaci commented 7 years ago

参数也不贴

loveproe commented 7 years ago

和参数没关系,我测试过半年多的时间并且不管是移动和电信网络都试过。。这个问题在所有使用kcp都出现是udp大流量被运营商自动封这个ip的udp连接。这个时间你们技术宅可能没有耐心测试,我因为一天24小时开youtube看skynews,他的断流时间也不固定可能一个小时也可能几十分钟,可能你和附近udp的国外带宽有关,如果断流了你只要等待十几分钟到半个小时就正常。解决这个问题只有finalspeed采用的将udp封装成tcp来发包。就从来不断线,我测试了大概一周都不断流。当然用finalspeed的udp模式和kcptun一样出现这个问题,v2ray 所使用的mkcp也同样有这个问题。只要用udp大量发包的必定被自动断流一段时间。

至于用搬瓦工的openvz的兄弟你们是无解的。。。速度换kvm的vps吧

可惜我每个版本都测试了,这个问题无解,只有等作者把udp封装成tcp的功能出现再使用了。。。

feizhenzhuang commented 7 years ago

很抱歉,现在才看到作者的回复 我现在把参数贴一下 。 version: 20160922 listening on: [::]:8989 encryption: aes nodelay parameters: 0 20 2 1 remote address: 45.78.27.211:29900 sndwnd: 128 rcvwnd: 1024 compression: true mtu: 1350 datashard: 10 parityshard: 3 acknodelay: false dscp: 0 sockbuf: 4194304 keepalive: 10 conn: 1 autoexpire: 0 谢谢作者的帮助,

feizhenzhuang commented 7 years ago

看到楼上“loveproe”所说的:“ 至于用搬瓦工的openvz的兄弟你们是无解的。。。速度换kvm的vps吧.” 我之前看到 搬瓦工应该也可以安装finalspeed吧。 default

PS: 我所使用的shadowsocksR有一个功能是UDP over TCP 不知道将这个选上 配合kcp 能不能实现绕过UDP封锁.

gatalon commented 7 years ago

搬瓦工用finalspeed只能UDP。 我遇到的情况跟你差不多,UDP似乎都是被封了,玩warframe跟朋友联机提示让我打开端口,我防火墙都是关闭的。

shutup commented 7 years ago

我当时测试发现,公司的网络出国的UDP数据绝对被干扰了。也可能和时间有关?我在家使用没什么问题。

xtaci commented 7 years ago

尝试降低MTU=512

CuminLo commented 7 years ago

@xtaci 服务端和客户端都需要降低么?

xtaci commented 7 years ago

是的,参考 https://github.com/xtaci/kcptun/issues/218

linhua55 commented 7 years ago

鹏博士的网,搬瓦工的VPS,也是频繁断开,10分钟-半小时左右会恢复。

经测试,断开后,除了80和443端口以外的所有TCP端口都被封,而且是Server --> Client的下行流量被封,上行没有影响

UDP端口似乎都被封了(也只是下行 被封),还没有找到简便的测试方法,不确定,留待测试。

而ICMP ping命令始终能通,这使人不禁寄希望于 ICMPTunnel ,不过据说速度很慢。

应该是 端口封锁/Qos,不含端口的VPN协议流量应该可以通过,但是又会碰上GFW的封锁。

如果只是 对UDP端口单独进行统计流量,流量过大就触发封锁规则的话,那么 在Server端 用iptables工具,实现随机化端口发送数据(Server --> Client),应该可以解决

测试方法,对于TCP,使用netcat或nmap(可选:可辅助用tcpdump,wireshark进行确认)

测试单个端口:

$ nc -zv <your-server-ip>  <your-tcp-port>

这里的端口可以是没有监听的, 如果可以连通,出来的警告是connection refused。如果是被封了,出来的警告是connection time out。(这个可以使用tcpdump/wireshark进行确认)

$ sudo tcpdump -nnq host  <your-server-ip> and not port 80

批量测试:

$ sudo nmap -sS  --top-ports 1000  <your-server-ip>

对于UDP,不能使用nmap进行批量测试,因为UDP没有三次握手,从而没有返回包(Server--> Client)。 只能使用 echo server 对单一端口进行手动测试

linhua55 commented 7 years ago

@feizhenzhuang 可以试试 随机化端口方案 https://gist.github.com/suikatomoki/89b1221dab19f64ba2b3

例如

Client ➜   sudo iptables -t nat -I OUTPUT -d <your_vps_ip> -p udp --dport <your_kcp_server_port> -j DNAT --to-destination <your_vps_ip>:4000-5000 --random
Server root@default:~# iptables -t nat -A PREROUTING -p udp -m multiport --dport 4000:5000 -j REDIRECT --to-ports <your_kcp_server_port>

同时要调大connection参数(其实不知connection参数具体影响什么!!!)

不过这个 不是针对 每个 packet 随机化端口,而是针对 每一个connection 随机化端口。 https://serverfault.com/questions/716346/randomize-destination-port-for-every-packet-with-iptables

下面这个好像是针对 packet的 https://www.haiyun.me/archives/1024.html/comment-page-1 上条链接的命令有点问题,是针对老版本的iptables的,现在的可参考 https://serverfault.com/questions/490854/rotating-outgoing-ips-using-iptables/491517#491517

如何控制 kcptun 每个connection的流量大小?

CuminLo commented 7 years ago

@linhua55 我也是鹏博士的网,那有什么好的解决办法么?

linhua55 commented 7 years ago

好奇怪,这两天没断了,也没用上面提到过的随机化端口方案,也没改小mtu。只是前几天,把ssh服务端端口改为了80端口。 你可以试一下把ssh端口改为80443端口试试。 可能如果 80443端口没开,就会把你加入黑名单,进行特殊照顾

今天中午又开始断了,看来不是这个原因

cjjdaq commented 7 years ago

一直断,所以用了上面的随机端口方案,但发现,封的时候不是封服务器的udp,而且是对宽带本身的udp进出进行封堵,重新拨号换ip后就能连上了。。这就无解了。。。

linhua55 commented 7 years ago

@cjjdaq 应该不会封宽带本身的, 有好多的宽带都是分的内网的ip,如果封宽带本身的,就会牵连其他用户。你如果有另外的vps服务器,可以尝试一下看看能否连通。 你重新拨号可以,还可以有另外的解释:就是换出口ip后,这个 新的 出口ip或中间路由ip中对应的服务器中的Qos服务 没有把你的服务器ip记录在黑名单里

我在客户端用nc,服务端用tcpdump测试: 客户端用nc访问一个udp端口,在服务端的tcpdump可以看到收到了从客户端访问这个udp端口的包。 从此看来是,客户端到服务端的udp上行流量不受影响

你试试 调大 connection 参数试试,那天,把connection参数调为了10

cjjdaq commented 7 years ago

我的宽带电信的,公网ip,断的时候,我宽带的udp出不去进不来(只有等待解封,要么重新拨号),但我用其它省的宽带(电信固定ip)连接到服务器的udp一切正常。

linhua55 commented 7 years ago

@cjjdaq 因为路由变了呀

cjjdaq commented 7 years ago

其它省的连接一直正常,就我这里的电信封,我日

wkingfly commented 7 years ago

上海的电信也会审查过滤

cjjdaq notifications@github.com于2016年12月9日周五 下午2:21写道:

其它省的连接一直正常,就我这里的电信封,我日

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/xtaci/kcptun/issues/228#issuecomment-265942774, or mute the thread https://github.com/notifications/unsubscribe-auth/ADMsUGAntY0Bjvxfy_jNIMxuB5eamecYks5rGPNugaJpZM4Kb6qi .

linhua55 commented 7 years ago

@cjjdaq https://github.com/xtaci/kcptun/issues/323#issuecomment-266441441 刚才测试了一下,发现封锁策略变了,现象和你的一样了。TCP端口 没被封,但UDP上行流量(Client--> Server)被封。因客户端处在内网中,故没法测试UDP下行流量是否通畅

~UDP通畅的时候,在服务端tcpdump中显示的 ip地址 和 用TCP时显示的本地ip 地址不一样。看来是TCP和UDP流量走了不同的路由,导致出口ip不一样。~

显示的出口ip是一样的

linhua55 commented 7 years ago

@cjjdaq 客户端分别用ncnmap测试UDP端口连通性,服务端用tcpdump查看流量。发现虽然用nc测试,没有日志,即UDP上行流量(Client--> Server)被封。但是用nmap测试可以看到UDP的日志,虽然UDP包的字节数为0。nmap用了UDP host discovery(UDP ping) 去测试UDP端口的连通性,需要等待ICMP应答。如果这样可以的话,上行流量可以伪装成 这个的 流量。或上行流量用TCP,下行流量用UDP。 具体命令:

Client $ nc -dv <your_server_ip> 5879 -u
Server $ tcpdump -nnq host  <your_server_ip>  and not port 80  and not port 443 and not tcp

Client $ sudo nmap -sU <your_server_ip>  -p5879 -Pn

http://thesprawl.org/research/host-discovery/#udp-ping https://bt3gl.github.io/black-hat-python-building-a-udp-scanner.html https://www.oschina.net/translate/building-a-udp-scanner-with-pythons-socket-module

用python程序测试了一下,确实是UDP上行流量 不通,UDP下行流量是通的。但是如果UDP上行流量只发送0字节也是可以通过 到达服务器的(就像用上条nmap命令的效果)(可以用此特性来维护NAT长连接,但不能传输上行流量)。 因此上行流量用TCP,下行流量用UDP这个方案,原理上是可以实现的

linhua55 commented 7 years ago

上行流量用TCP,下行流量用UDP方案原理图 kcptun

其中,python程序client/server需要实现的功能是:

  1. 发送0字节UDP数据,维护NAT长连接,确保下行流量可到达客户端
  2. 下行流量的UDP转发
  3. 将上行UDP流量转化为TCP流量(客户端),及将TCP流量还原为UDP流量(服务端)
xtaci commented 7 years ago

你是要搞扩频通信啊 ,两组 UDP亦可

linhua55 commented 7 years ago

@xtaci UDP上行流量(Client --> Server)不通,被ISP封锁了。 UDP下行流量经之前的测试是可以的。

@cjjdaq 这是测试UDP下行流量是否通的代码:

注意:这是python3的代码 服务端: udpServer.py

#!/usr/bin/env python
# -*- coding:utf8 -*- 

import socket

class UdpServer(object):
    def tcpServer(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        sock.bind(('', 9527))

        while True:
            revcData, (remoteHost, remotePort) = sock.recvfrom(1024)
            print("[%s:%s] connect" % (remoteHost, remotePort))

            sendDataLen = sock.sendto(b"this is send  data from server", (remoteHost, remotePort))
            print("revcData: ", revcData)
            print("sendDataLen: ", sendDataLen)

        sock.close()

if __name__ == "__main__":
    udpServer = UdpServer()
    udpServer.tcpServer()

客户端:udpClient.py 需要将YOUR_SERVER_IP改为自己服务器的真实ip

#!/usr/bin/env python
# -*- coding:utf8 -*-   

import socket

# send empty byte
MESSAGE = b""  # b"a" 
class UdpClient(object):
    def tcpclient(self, MESSAGE):
        clientSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

        sendDataLen = clientSock.sendto(MESSAGE, ('YOUR_SERVER_IP', 9527))
        recvData = clientSock.recvfrom(1024)
        print("sendDataLen: ", sendDataLen)
        print("recvData: ", recvData)

        clientSock.close()

if __name__ == "__main__":
    udpClient = UdpClient()
    udpClient.tcpclient(MESSAGE)
moolex commented 7 years ago

@linhua55 我和你遇到了一样的问题,公司电信网络,VPS 是搬瓦工。UDP 上行流量间歇性被封,下行流量是通的。

linhua55 commented 7 years ago

@cjjdaq @moolex https://github.com/linhua55/some_kcptun_tools

可以测试一下,用了 @xtaci 提到的两组UDP来分别传输 上行流量和下行流量。测试了一天,还可以

cjjdaq commented 7 years ago

some_kcptun_tools给个具体使用方法

cjjdaq commented 7 years ago

@xtaci 希望能将此功能集成。

xtaci commented 7 years ago

kcptun只想做核心部分,保持简洁。

cjjdaq commented 7 years ago

@xtaci 目前已经很多地方会对udp上行进行封堵,希望能想想办法。

xtaci commented 7 years ago

@cjjdaq 觉得可能还是蛮简单的,很多方法能解决,icmp也可以通信

cjjdaq commented 7 years ago

@xtaci 方法可能有很多,但对于我们普通网名也是等于没有方法呀。

xtaci commented 7 years ago

@cjjdaq 让有心人做吧

linhua55 commented 7 years ago

@cjjdaq 更新了说明,欢迎测试

linhua55 commented 7 years ago

封锁策略又变为封UDP下行流量,UDP上行流量没被封

xtaci commented 7 years ago

@linhua55 会不会是路由器本身的问题,比如这个参数太小 @bettermanbao

net.core.rmem_max = 26214400

启动的时候,有没有出现setsocket buffer报错

bettermanbao commented 7 years ago

[root@5K-W20:/proc/sys/net/core]#cat rmem_default 163840 [root@5K-W20:/proc/sys/net/core]#cat rmem_max 163840

这是我的路由器上的值,确实比你小很多。会影响吗?

启动的时候,setsocket buffer不会报错。

xtaci commented 7 years ago

kcptun默认是设置4MB, 如果太小,udp包太快,kcp处理太慢,可能会内核丢包。

bettermanbao commented 7 years ago

这种丢包能通过什么数据看到吗?我最近开了FEC,流量一大以后路由器的CPU必定满载。

xtaci commented 7 years ago

/proc/net/snmp应该能看到

linhua55 commented 7 years ago

@xtaci 用的 https://github.com/xtaci/kcptun/issues/228#issuecomment-268216076 中的脚本测得的

路由器不受我控制。 服务端的话,用tcpdump查看了,有发出去的包,但在客户端用tcpdump查看只有发出去的包没有进来的包

baggiogogo commented 7 years ago

自家的话,我觉得排查下路由是有必要的,这个状况,要么ISP要么路由,必有其一要背这个锅。 复杂环境,比如公司或者长宽这种,只要路由上开着QOS,对KCPTUN就是麻烦,我在自家环境尝试QOS,只要一开,无论到不到设定的阈值,都会被丢包,多少而已。 我个人的使用情况,自从@xtaci换库以来,即便遇到抽风,卡是有的,但从未遇到过断流。 还有个情况,当遇到断流的时候,可以尝试用站长工具用全国同一运营商的不同地点IP去PING主机,如果多数都PING超时,那就VPS去背这个锅。

linhua55 commented 7 years ago

现在连TCP 443端口也限制了,使用原生的Shadowsocks没有速度, 必须使用带混淆功能的ShadowsocksR。 配合net-speeder (双倍发包),竟然也能达到自身带宽的一半速度。但是这种无脑双倍发包还是浪费带宽。 搜索了一下 单/双边加速方案, 发现似乎可以在openvz上实现 用户态的网络协议栈(user space network stack)。 然后看到了这一句话:

比如说,由于运营商一般会对UDP流量进行策略化监管或者限速,目前,有一种非常简单的UDP双边加速的方式就是,仅仅将协议号由UDP改成TCP即可!而UDP允许一定程度的丢包,所以说,路由器交换机的AQM对其而言,就是刑不上大夫!

http://blog.csdn.net/dog250/article/details/53730374

改协议号说不定可行!!! 当然,改协议号之后还得混淆(成http/https流量)

linhua55 commented 7 years ago

初步实现了 用TCP传输UDP(不进行三次握手),通过使用raw socket(/pcap)(需要以root运行) 伪造数据包类型,绕过正常的内核协议栈。 但还没进行混淆 https://github.com/linhua55/some_kcptun_tools/tree/master/relayRawSocket

不过测试一下,带宽利用率还没有net-speeder高(即不到一半带宽),可能是参数没调好,或该程序有bug

linhua55 commented 7 years ago

https://github.com/linhua55/some_kcptun_tools/tree/master/relayRawSocket 重复发包,导致带宽利用率不到一半的问题已解决

Chion82 commented 7 years ago

借鉴了 https://github.com/linhua55/some_kcptun_tools/tree/master/relayRawSocket ,使用raw socket和libev,远端通信为伪TCP报文,重新实现了kcptun的最基本功能(未实现加密和纠错等,仍在测试),只需一个程序即可,不需要再另外建立UDP over TCP隧道,不容易“卡住”,欢迎试用 https://github.com/Chion82/kcptun-raw

wangyu- commented 7 years ago

借鉴了楼上的relayRawSocket和kcptun-raw。 专门应对UDP 封锁和UDP QoS 的通用解决方案。用raw socket把udp协议包装成tcp,有模拟3次握手,模拟序号,模拟tcp option;还可以把流量包装成icmp。支持几乎任何udp应用。包括kcptun和finalspeed。支持openvz。支持NAT穿透。稳定。 https://github.com/wangyu-/udp2raw-tunnel ==updated== 还有个功能是心跳保活、自动重连,udp2raw重连可以恢复上次的连接,重连后上层连接继续有效,底层掉线上层不掉线。也可以有效解决连接断开的问题(就算你拔掉网线重插,或者重新拨号获得新ip,上层的kcp也不会断线)。(功能借鉴自kcptun-raw) image udp2raw+kcptun step by step教程: https://github.com/wangyu-/udp2raw-tunnel/blob/master/doc/kcptun_step_by_step.md

HongdaWang commented 7 years ago

wangyu你好,请问客户端支持Windows平台吗

在 2017-08-10 12:51:30,"wangyu-" notifications@github.com 写道:

借鉴了楼上的relayRawSocket和kcptun-raw。 专门应对UDP 封锁和UDP QoS 的通用解决方案。用raw socket把udp协议包装成tcp,有模拟3次握手,模拟序号,模拟tcp option;还可以把流量包装成icmp。支持几乎任何udp应用。包括kcptun和finalspeed。支持openvz。稳定。 https://github.com/wangyu-/udp2raw-tunnel

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

wangyu- commented 7 years ago

@HongdaWang 暂时没做windows客户端,但是windows配合vmware或者openwrt路由器可以稳定使用。

==updated== 只需要把udp2raw运行在vmware或路由器上,kcptun可以继续使用window的客户端,其他上层应用也仍然是运行在window上的(比如你的浏览器,ss客户端)。

HongdaWang commented 7 years ago

好的,谢谢你的贡献,后边会有各平台gui客户端的,交给社区吧

在 2017-08-10 13:32:24,"wangyu-" notifications@github.com 写道:

@HongdaWang 暂时没做windows客户端,但是windows配合vmware或者openwrt路由器可以稳定使用。

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or mute the thread.