mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
令所有proxy均支持fullcone配置.只有当listen和dial都为fullcone时,才真fullcone
This commit is contained in:
@@ -40,7 +40,7 @@ dns(udp/tls)/route(geoip/geosite,分流功能完全与v2ray等价)/fallback(path
|
||||
|
||||
tcp/udp(以及fullcone)/unix domain socket, tls(包括客户端证书验证), uTls,【tls lazy encrypt】, http伪装头,PROXY protocol v1/v2 监听,
|
||||
|
||||
cli(交互模式)/apiServer, Docker.
|
||||
cli(交互模式)/apiServer, Docker, docker-compose.
|
||||
|
||||
|
||||
为了不吓跑小白,本 README 把安装、使用方式 放在了前面,如果你要直接阅读本作的技术介绍部分,点击跳转 -> [创新点](#创新点)
|
||||
|
||||
@@ -113,11 +113,8 @@ func RelayUDP(rc, lc MsgConn, downloadByteCount, uploadByteCount *uint64) uint64
|
||||
|
||||
count += uint64(len(bs))
|
||||
}
|
||||
if !rc.Fullcone() {
|
||||
if !(rc.Fullcone() && lc.Fullcone()) {
|
||||
rc.Close()
|
||||
}
|
||||
|
||||
if !lc.Fullcone() {
|
||||
lc.Close()
|
||||
}
|
||||
|
||||
@@ -161,11 +158,8 @@ func relayUDP_rc_toLC(rc, lc MsgConn, downloadByteCount *uint64, mutex *sync.RWM
|
||||
}
|
||||
count += uint64(len(bs))
|
||||
}
|
||||
if !rc.Fullcone() {
|
||||
if !(rc.Fullcone() && lc.Fullcone()) {
|
||||
rc.Close()
|
||||
}
|
||||
|
||||
if !lc.Fullcone() {
|
||||
lc.Close()
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,8 @@ type Base struct {
|
||||
Sockopt *netLayer.Sockopt
|
||||
Xver int
|
||||
|
||||
IsFullcone bool
|
||||
|
||||
Tls_s *tlsLayer.Server
|
||||
Tls_c *tlsLayer.Client
|
||||
|
||||
@@ -302,6 +304,7 @@ func (b *Base) ConfigCommon(cc *CommonConf) {
|
||||
b.Xver = cc.Xver
|
||||
b.Tag = cc.Tag
|
||||
b.Sockopt = cc.Sockopt
|
||||
b.IsFullcone = cc.Fullcone
|
||||
|
||||
if cc.HttpHeader != nil {
|
||||
cc.HttpHeader.AssignDefaultValue()
|
||||
|
||||
@@ -20,23 +20,16 @@ type DirectCreator struct{}
|
||||
func (DirectCreator) NewClientFromURL(url *url.URL) (Client, error) {
|
||||
d := &DirectClient{}
|
||||
|
||||
nStr := url.Query().Get("fullcone")
|
||||
if nStr == "true" || nStr == "1" {
|
||||
d.isfullcone = true
|
||||
}
|
||||
|
||||
return d, nil
|
||||
}
|
||||
|
||||
func (DirectCreator) NewClient(dc *DialConf) (Client, error) {
|
||||
d := &DirectClient{}
|
||||
d.isfullcone = dc.Fullcone
|
||||
return d, nil
|
||||
}
|
||||
|
||||
type DirectClient struct {
|
||||
Base
|
||||
isfullcone bool
|
||||
}
|
||||
|
||||
func (*DirectClient) Name() string { return DirectName }
|
||||
@@ -67,10 +60,10 @@ func (d *DirectClient) Handshake(underlay net.Conn, firstPayload []byte, target
|
||||
//direct的Client的 EstablishUDPChannel 直接 监听一个udp端口,无视传入的net.Conn.
|
||||
func (d *DirectClient) EstablishUDPChannel(_ net.Conn, firstPayload []byte, target netLayer.Addr) (netLayer.MsgConn, error) {
|
||||
if len(firstPayload) == 0 {
|
||||
return netLayer.NewUDPMsgConn(nil, d.isfullcone, false)
|
||||
return netLayer.NewUDPMsgConn(nil, d.IsFullcone, false)
|
||||
|
||||
} else {
|
||||
mc, err := netLayer.NewUDPMsgConn(nil, d.isfullcone, false)
|
||||
mc, err := netLayer.NewUDPMsgConn(nil, d.IsFullcone, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ type CommonConf struct {
|
||||
|
||||
Xver int `toml:"xver"` //可选,只能为0/1/2. 若不为0, 则使用 PROXY protocol 协议头.
|
||||
|
||||
Fullcone bool `toml:"fullcone"` //在direct会用到, fullcone的话因为不能关闭udp连接, 所以 时间长后, 可能会导致too many open files. fullcone 的话一般人是用不到的, 所以 有需要的人自行手动打开 即可
|
||||
|
||||
/////////////////// tls层 ///////////////////
|
||||
|
||||
TLS bool `toml:"tls"` //tls层; 可选. 如果不使用 's' 后缀法,则还可以配置这一项来更清晰第标明使用tls
|
||||
@@ -121,8 +123,7 @@ type ListenConf struct {
|
||||
// CommonConf.Host , CommonConf.IP, CommonConf.Port is the addr and port for dialing.
|
||||
type DialConf struct {
|
||||
CommonConf
|
||||
Utls bool `toml:"utls"` //是否使用 uTls 库 替换 go官方tls库
|
||||
Fullcone bool `toml:"fullcone"` //在direct会用到, fullcone的话因为不能关闭udp连接, 所以可能会导致too many open files. fullcone 的话一般人是用不到的, 所以 有需要的人自行手动打开 即可
|
||||
Utls bool `toml:"utls"` //是否使用 uTls 库 替换 go官方tls库
|
||||
|
||||
Mux bool `toml:"use_mux"` //是否使用内层mux。在某些支持mux命令的协议中(vless v1/trojan), 开启此开关会让 dial 使用 内层mux。
|
||||
}
|
||||
|
||||
@@ -140,14 +140,22 @@ func configCommonURLQueryForServer(ser BaseInterface, u *url.URL) {
|
||||
}
|
||||
|
||||
//SetAddrStr, setNetwork
|
||||
func configCommonByURL(ser BaseInterface, u *url.URL) {
|
||||
func configCommonByURL(baseI BaseInterface, u *url.URL) {
|
||||
if u.Scheme != DirectName {
|
||||
ser.SetAddrStr(u.Host) //若不给出port,那就只有host名,这样不好,我们 默认 配置里肯定给了port
|
||||
baseI.SetAddrStr(u.Host) //若不给出port,那就只有host名,这样不好,我们 默认 配置里肯定给了port
|
||||
|
||||
}
|
||||
serc := ser.GetBase()
|
||||
if serc == nil {
|
||||
base := baseI.GetBase()
|
||||
if base == nil {
|
||||
return
|
||||
}
|
||||
serc.setNetwork(u.Query().Get("network"))
|
||||
base.setNetwork(u.Query().Get("network"))
|
||||
|
||||
base.IsFullcone = GetFullconeFromUrl(u)
|
||||
|
||||
}
|
||||
|
||||
func GetFullconeFromUrl(url *url.URL) bool {
|
||||
nStr := url.Query().Get("fullcone")
|
||||
return nStr == "true" || nStr == "1"
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ func (c *Client) EstablishUDPChannel(underlay net.Conn, firstPayload []byte, tar
|
||||
|
||||
uc := NewUDPConn(underlay, nil)
|
||||
uc.handshakeBuf = buf
|
||||
uc.fullcone = c.IsFullcone
|
||||
|
||||
if len(firstPayload) == 0 {
|
||||
return uc, nil
|
||||
|
||||
@@ -99,7 +99,9 @@ realPart:
|
||||
}
|
||||
|
||||
if isudp {
|
||||
return nil, NewUDPConn(underlay, io.MultiReader(readbuf, underlay)), targetAddr, nil
|
||||
x := NewUDPConn(underlay, io.MultiReader(readbuf, underlay))
|
||||
x.fullcone = s.IsFullcone
|
||||
return nil, x, targetAddr, nil
|
||||
|
||||
} else {
|
||||
return &TCPConn{
|
||||
|
||||
@@ -16,6 +16,7 @@ type UDPConn struct {
|
||||
|
||||
bufr *bufio.Reader
|
||||
handshakeBuf *bytes.Buffer
|
||||
fullcone bool
|
||||
}
|
||||
|
||||
func NewUDPConn(conn net.Conn, optionalReader io.Reader) (uc *UDPConn) {
|
||||
@@ -30,8 +31,8 @@ func NewUDPConn(conn net.Conn, optionalReader io.Reader) (uc *UDPConn) {
|
||||
return
|
||||
}
|
||||
|
||||
func (*UDPConn) Fullcone() bool {
|
||||
return true
|
||||
func (u *UDPConn) Fullcone() bool {
|
||||
return u.fullcone
|
||||
}
|
||||
func (u *UDPConn) CloseConnWithRaddr(raddr netLayer.Addr) error {
|
||||
return u.Close()
|
||||
|
||||
@@ -159,6 +159,7 @@ func (c *Client) EstablishUDPChannel(underlay net.Conn, firstPayload []byte, tar
|
||||
ServerAddr: &net.TCPAddr{
|
||||
IP: ua.IP,
|
||||
},
|
||||
fullcone: c.IsFullcone,
|
||||
}
|
||||
cpc.UDPConn, err = net.DialUDP("udp", nil, ua)
|
||||
if err != nil {
|
||||
|
||||
@@ -19,6 +19,7 @@ type ClientUDPConn struct {
|
||||
ServerUDPPort_forMe int //socks5服务会为每一个socks5客户端留一个专用的udp端口
|
||||
|
||||
WriteUDP_Target *net.UDPAddr
|
||||
fullcone bool
|
||||
}
|
||||
|
||||
func (cpc *ClientUDPConn) Associate() (err error) {
|
||||
@@ -144,7 +145,7 @@ func (cpc *ClientUDPConn) CloseConnWithRaddr(raddr netLayer.Addr) error {
|
||||
}
|
||||
|
||||
func (cpc *ClientUDPConn) Fullcone() bool {
|
||||
return true
|
||||
return cpc.fullcone
|
||||
}
|
||||
|
||||
//传入 conn必须非nil,否则panic
|
||||
|
||||
@@ -44,6 +44,7 @@ func (ServerCreator) NewServerFromURL(u *url.URL) (proxy.Server, error) {
|
||||
if userPass.InitWithUrl(u) {
|
||||
s.AddUser(&userPass)
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
@@ -280,8 +281,13 @@ For:
|
||||
// 更不用说这样 的 udp associate 会重复使用很多 随机udp端口,特征很明显。
|
||||
// 总之 udp associate 只能用于内网环境。
|
||||
|
||||
//旧代码每次遇到 associate都会返回一个新的随机端口,而实际上这应该是有问题的
|
||||
//如果一些不良的socks5客户端 每次 udp请求都使用 associate的话,会造成端口数量无限增长,最后产生 too many open files 错误。
|
||||
|
||||
if cmd == CmdUDPAssociate {
|
||||
|
||||
utils.Debug("socks5 got CmdUDPAssociate")
|
||||
|
||||
//这里我们serverAddr直接返回0.0.0.0即可,也实在想不到谁会返回 另一个ip地址出来。肯定应该和原ip相同的。
|
||||
|
||||
//随机生成一个端口专门用于处理该客户端。这是我的想法。
|
||||
@@ -323,6 +329,7 @@ For:
|
||||
uc := &ServerUDPConn{
|
||||
clientSupposedAddr: clientFutureAddr.ToUDPAddr(), //这里为了解析域名, 就用了 netLayer.Addr 作为中介的方式
|
||||
UDPConn: udpRC,
|
||||
fullcone: s.IsFullcone,
|
||||
}
|
||||
return nil, uc, clientFutureAddr, nil
|
||||
|
||||
@@ -355,6 +362,7 @@ For:
|
||||
type ServerUDPConn struct {
|
||||
*net.UDPConn
|
||||
clientSupposedAddr *net.UDPAddr //客户端指定的客户端自己未来将使用的公网UDP的Addr
|
||||
fullcone bool
|
||||
}
|
||||
|
||||
func (u *ServerUDPConn) CloseConnWithRaddr(raddr netLayer.Addr) error {
|
||||
@@ -362,7 +370,7 @@ func (u *ServerUDPConn) CloseConnWithRaddr(raddr netLayer.Addr) error {
|
||||
}
|
||||
|
||||
func (u *ServerUDPConn) Fullcone() bool {
|
||||
return true
|
||||
return u.fullcone
|
||||
}
|
||||
|
||||
//将远程地址发来的响应 传给客户端
|
||||
|
||||
@@ -9,12 +9,14 @@ import (
|
||||
"github.com/e1732a364fed/v2ray_simple/netLayer"
|
||||
"github.com/e1732a364fed/v2ray_simple/proxy"
|
||||
"github.com/e1732a364fed/v2ray_simple/proxy/socks5"
|
||||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||||
)
|
||||
|
||||
//tcp就不测了,我们实践直接测试完全好使,这里重点测试UDP
|
||||
// 因为chrome也是无法通过 socks5去申请udp链接的,所以没法自己用浏览器测试
|
||||
|
||||
func TestUDP(t *testing.T) {
|
||||
utils.InitLog("")
|
||||
|
||||
s := socks5.NewServer()
|
||||
|
||||
|
||||
@@ -2,17 +2,23 @@
|
||||
|
||||
This package imports proxy/socks5 and proxy/http package.
|
||||
|
||||
Naming
|
||||
|
||||
socks5http 与 clash的 "mixed" 等价。之所以不用 "mixed"这个名称,是因为这容易在本作中引起歧义。
|
||||
|
||||
clash是一个客户端,它没有服务端,所以它的监听只是用于内网监听,所以监听协议 只有http和socks5 两种,所以 它 叫 "mixed" 是没有歧义的;
|
||||
|
||||
而本作与v2ray一样,是支持多种服务端协议的,如果也叫 mixed 的话,会让人误以为,这是一个 "万能协议", 啥都能监听, 而这显然是误区。 命名为 socks5http, 则清晰地指出了 该协议的功能。
|
||||
|
||||
Password
|
||||
|
||||
为了避免混淆,本包不支持密码验证。你要是有这么高的密码要求 那你不妨用单独的协议,而不要用混合版。
|
||||
|
||||
实际上本包就是先经过http,然后如果不是http代理请求,就会回落到socks5.
|
||||
|
||||
所以你可以通过 设计回落的方式来达到 有密码 的 混合端口 的需求。
|
||||
|
||||
socks5http 与 clash的 "mixed" 等价。之所以不用 "mixed"这个名称,是因为这容易在本作中引起歧义。
|
||||
|
||||
clash是一个客户端,它没有服务端,所以它的监听只是用于内网监听,所以监听协议 只有http和socks5 两种,所以 它 叫 "mixed" 是没有歧义的;
|
||||
|
||||
而本作与v2ray一样,是支持多种服务端协议的,如果也叫 mixed 的话,会让人误以为,这是一个 "万能协议", 啥都能监听, 而这显然是误区。 命名为 socks5http, 则清晰地指出了 该协议的功能。
|
||||
*/
|
||||
package socks5http
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ func (c *Client) EstablishUDPChannel(underlay net.Conn, firstPayload []byte, tar
|
||||
buf.WriteByte(CmdUDPAssociate)
|
||||
WriteAddrToBuf(target, buf)
|
||||
|
||||
uc := NewUDPConn(underlay, nil)
|
||||
uc := NewUDPConn(underlay, nil, c.IsFullcone)
|
||||
uc.User = c.User
|
||||
uc.handshakeBuf = buf
|
||||
if len(firstPayload) == 0 {
|
||||
|
||||
@@ -202,7 +202,7 @@ realPart:
|
||||
}
|
||||
|
||||
if isudp {
|
||||
uc := NewUDPConn(underlay, io.MultiReader(readbuf, underlay))
|
||||
uc := NewUDPConn(underlay, io.MultiReader(readbuf, underlay), s.IsFullcone)
|
||||
uc.User = theUser.(User)
|
||||
return nil, uc, targetAddr, nil
|
||||
|
||||
|
||||
@@ -18,11 +18,14 @@ type UDPConn struct {
|
||||
bufr *bufio.Reader
|
||||
|
||||
handshakeBuf *bytes.Buffer
|
||||
|
||||
isfullcone bool
|
||||
}
|
||||
|
||||
func NewUDPConn(conn net.Conn, optionalReader io.Reader) (uc *UDPConn) {
|
||||
func NewUDPConn(conn net.Conn, optionalReader io.Reader, fullcone bool) (uc *UDPConn) {
|
||||
uc = new(UDPConn)
|
||||
uc.Conn = conn
|
||||
uc.isfullcone = fullcone
|
||||
if optionalReader != nil {
|
||||
uc.optionalReader = optionalReader
|
||||
uc.bufr = bufio.NewReader(optionalReader)
|
||||
@@ -32,8 +35,8 @@ func NewUDPConn(conn net.Conn, optionalReader io.Reader) (uc *UDPConn) {
|
||||
return
|
||||
}
|
||||
|
||||
func (*UDPConn) Fullcone() bool {
|
||||
return true
|
||||
func (u *UDPConn) Fullcone() bool {
|
||||
return u.isfullcone
|
||||
}
|
||||
func (u *UDPConn) CloseConnWithRaddr(raddr netLayer.Addr) error {
|
||||
return u.Close()
|
||||
|
||||
@@ -211,6 +211,7 @@ func (c *Client) EstablishUDPChannel(underlay net.Conn, firstPayload []byte, tar
|
||||
raddr: target,
|
||||
udp_multi: c.udp_multi,
|
||||
handshakeBuf: buf,
|
||||
fullcone: c.IsFullcone,
|
||||
}
|
||||
if len(firstPayload) == 0 {
|
||||
return uc, nil
|
||||
|
||||
@@ -267,6 +267,7 @@ realPart:
|
||||
raddr: targetAddr,
|
||||
remainFirstBufLen: readbuf.Len(),
|
||||
udp_multi: use_udp_multi,
|
||||
fullcone: s.IsFullcone,
|
||||
}, targetAddr, nil
|
||||
|
||||
} else {
|
||||
|
||||
@@ -30,13 +30,15 @@ type UDPConn struct {
|
||||
raddr netLayer.Addr
|
||||
|
||||
handshakeBuf *bytes.Buffer
|
||||
|
||||
fullcone bool
|
||||
}
|
||||
|
||||
func (u *UDPConn) CloseConnWithRaddr(raddr netLayer.Addr) error {
|
||||
return u.Close()
|
||||
}
|
||||
func (u *UDPConn) Fullcone() bool {
|
||||
return u.version != 0
|
||||
return u.fullcone && u.version != 0
|
||||
}
|
||||
|
||||
func (u *UDPConn) GetProtocolVersion() int {
|
||||
|
||||
Reference in New Issue
Block a user