mirror of
https://github.com/e1732a364fed/v2ray_simple.git
synced 2025-12-24 13:27:56 +08:00
取消Client的LocalAddr,改为 LocalTCPAddr 和 LocalUDPAddr 删除direct中的对应条目。这样可更清晰地配置双本地地址 将设置sendthrough设置双地址的代码移动到 proxy.newClient函数 这样不仅direct可指定不同的tcp和udp的本地地址,任何client协议都可以了 为ClientCreator 接口 添加 UseUDPAsMsgConn 方法,direct和ss返回true 在ss的client的EstablishUDPChannel进行自行拨号 在ss的server建立后,自动循环监听udp,绕过vs的基本监听机制。因为vs架构的限制,一个代理只能有一个唯一的传输层协议。 ServerCreator 接口 添加 AfterCommonConfServer 方法
100 lines
3.1 KiB
Go
100 lines
3.1 KiB
Go
/*
|
||
Package dokodemo implements a dokodemo-door proxy.Server.
|
||
|
||
Server that wants to relay data to a dokodemo target address.
|
||
|
||
dokodemo 是 v2ray的 dokodemo-door 协议的实现。不含透明代理功能。
|
||
|
||
严格来说 dokodemo-door 并不是一个 "协议", 而是一个预先指定目标的转发方式。
|
||
|
||
dokodemo 是 listen端, 监听一个普通的tcp/udp端口,试图将一切流量转发到特定的预定义的地址. 并不是直接连接,而是转发到dial。
|
||
|
||
dokodemo 属于 “单目标”代理,而其它proxy.Server 一般都属于 “泛目标”代理。
|
||
|
||
内部实际上就是 指定了目标的 纯tcp/udp协议,属于监听协议中最简单、最纯粹的一种。
|
||
|
||
# Example 应用例子
|
||
|
||
使用 dokodemo 做监听,用direct 拨号,指定一个target,那么实际上就是把 该监听的节点 与远程target间建立了一个信道;
|
||
|
||
dokodemo 每监听到一个新连接, 就会新增一条 与 target 间的信道.
|
||
|
||
所以可能比较适合 中转机的情况,
|
||
|
||
比如如果有两个服务器 A和 B, 和客户C。
|
||
|
||
我们只告诉C 服务器B 的地址,然后告诉它B使用vless协议。然后C就会用vless协议对B 拨号。
|
||
|
||
此时B我们实际配置 为用 dokodemo 监听,而不是用vless监听;然后 dokodemo 的目标 指向 服务器A 的 vless监听端口.
|
||
这样就形成了一个中转机制.
|
||
|
||
实际例子:
|
||
https://www.40huo.cn/blog/wireguard-over-vless.html
|
||
|
||
就是说,任意门把客户数据的出口、自己的入口点从本地搬到了某个代理服务器的入口,然后指定了该数据的实际远程目标;就好像数据是从代理服务器直接发出的一样.
|
||
|
||
到底是哪个代理服务器,由outbound(即本作的dial)以及routing配置决定的。如果没有配置routing,那就是默认走第一个dial.
|
||
*/
|
||
package dokodemo
|
||
|
||
import (
|
||
"net"
|
||
"net/url"
|
||
|
||
"github.com/e1732a364fed/v2ray_simple/netLayer"
|
||
"github.com/e1732a364fed/v2ray_simple/proxy"
|
||
"github.com/e1732a364fed/v2ray_simple/utils"
|
||
)
|
||
|
||
const name = "dokodemo"
|
||
|
||
func init() {
|
||
proxy.RegisterServer(name, &ServerCreator{})
|
||
}
|
||
|
||
type ServerCreator struct{ proxy.CreatorCommonStruct }
|
||
|
||
func (ServerCreator) URLToListenConf(url *url.URL, lc *proxy.ListenConf, format int) (*proxy.ListenConf, error) {
|
||
if format != proxy.StandardMode {
|
||
return lc, utils.ErrUnImplemented
|
||
}
|
||
if lc == nil {
|
||
return nil, utils.ErrNilParameter
|
||
}
|
||
|
||
return lc, nil
|
||
}
|
||
|
||
// use lc.TargetAddr
|
||
func (ServerCreator) NewServer(lc *proxy.ListenConf) (proxy.Server, error) {
|
||
ta, e := netLayer.NewAddrByURL(lc.TargetAddr)
|
||
if e != nil {
|
||
return nil, e
|
||
}
|
||
s := &Server{
|
||
targetAddr: ta,
|
||
}
|
||
return s, nil
|
||
}
|
||
|
||
// implements proxy.Server
|
||
type Server struct {
|
||
proxy.Base
|
||
|
||
targetAddr netLayer.Addr
|
||
}
|
||
|
||
func NewServer() (proxy.Server, error) {
|
||
d := &Server{}
|
||
return d, nil
|
||
}
|
||
func (*Server) Name() string { return name }
|
||
|
||
func (s *Server) Handshake(underlay net.Conn) (net.Conn, netLayer.MsgConn, netLayer.Addr, error) {
|
||
if s.targetAddr.IsUDP() {
|
||
return nil, netLayer.UniTargetMsgConn{Conn: underlay, Target: s.targetAddr}, s.targetAddr, nil
|
||
} else {
|
||
return underlay, nil, s.targetAddr, nil
|
||
}
|
||
}
|