更新代码,文档; 令tproxy支持sniffing以及分流; 令tproxy在关闭时不卡住

关联 #98 中 下面的评论中 ctermiii 所反映的两个问题
This commit is contained in:
e1732a364fed
2000-01-01 00:00:00 +00:00
parent 41db97b8cf
commit 3af4eefd74
9 changed files with 89 additions and 21 deletions

View File

@@ -92,11 +92,15 @@ func cleanup() {
}
}
for _, tm := range tproxyList {
if tm != nil {
tm.Stop()
if len(tproxyList) > 0 {
log.Println("closing tproxies")
for _, tm := range tproxyList {
if tm != nil {
tm.Stop()
}
}
}
}
func main() {
@@ -393,18 +397,27 @@ func mainFunc() (result int) {
}
for _, thisConf := range tproxyConfs {
tm := vs.ListenTproxy(thisConf.GetAddrStrForListenOrDial(), defaultOutClient, routingEnv.RoutePolicy)
enableSniff := false
if thisConf.SniffConf != nil {
enableSniff = thisConf.SniffConf.Enable
}
lc := proxy.LesserConf{
Addr: thisConf.GetAddrStrForListenOrDial(),
Tag: thisConf.Tag,
UseSniffing: enableSniff,
}
tm := vs.ListenTproxy(lc, defaultOutClient, routingEnv.RoutePolicy)
if tm != nil {
tproxyList = append(tproxyList, tm)
}
}
}
} //if len(tproxyConfs) > 0 {
}
} //if mode == proxy.SimpleMode {
}
} //if (defaultOutClient != nil) && (defaultInServer != nil || len(allServers) > 0 || len(tproxyConfs) > 0) {
//没可用的listen/dial而且还无法动态更改配置
if noFuture() {

6
doc.go
View File

@@ -13,6 +13,12 @@ utils -> netLayer-> tlsLayer -> httpLayer -> advLayer -> proxy -> v2ray_simple -
ListenSer函数用于主要 代理的转发ListenTproxy函数用于转发透明代理。内置了 lazy的转发逻辑。
Tproxy
tproxy没有 TLS层 以及更上层的所有参数,只包含网络层和传输层的参数,网络层只包含 ip和端口这两个参数传输层只包含 "是否开启sniffing" 这一个参数; 然后还有一个 tag参数然后就没了。
所以tproxy不能算是一个完整的 proxy.Server. 所以要用单独的函数启动转发。
Chain

View File

@@ -64,6 +64,9 @@ type incomingInserverConnState struct {
inServer proxy.Server //可为 nil
defaultClient proxy.Client
inTag string //在inServer为nil时可用此项确定 inTag
useSniffing bool //在inServer为nil时可用此项确定 是否使用sniffing
cachedRemoteAddr string
inServerTlsConn *tlsLayer.Conn

16
main.go
View File

@@ -516,8 +516,8 @@ func handshakeInserver_and_passToOutClient(iics incomingInserverConnState) {
}
//被 handshakeInserver_and_passToOutClient 和 handshakeInserver 的innerMux部分 调用。 iics.inServer可能为nil。
// 本函数可能是本文件中 最长的函数。分别处理 回落firstpayloadsniffdns解析分流以及lazy。
//被 handshakeInserver_and_passToOutClient 和 handshakeInserver 的innerMux部分 以及 tproxy 调用。 iics.inServer可能为nil。
// 本函数可能是本文件中 最长的函数。分别处理 回落firstpayloadsniffdns解析分流以及lazy,最终转发到 某个 outClient
//
// 会调用 dialClient_andRelay. 若isfallback为true传入的 wlc 和 udp_wlc 必须为niltargetAddr必须为空值。
func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Conn, udp_wlc netLayer.MsgConn, targetAddr netLayer.Addr) {
@@ -607,7 +607,7 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co
}
if wlc == nil && udp_wlc == nil {
//无wlc证明 inServer 握手失败,且 没有任何回落可用, 直接退出。
//证明 inServer 握手失败,且 没有任何回落可用, 直接退出。
if ce := iics.CanLogDebug("invalid request and no matched fallback, hung up"); ce != nil {
ce.Write()
}
@@ -729,7 +729,13 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co
if len(iics.firstPayload) > 0 {
inserverMarkedSniffing := (inServer != nil && inServer.Sniffing())
inserverMarkedSniffing := false
if inServer == nil {
inserverMarkedSniffing = iics.useSniffing
} else {
inserverMarkedSniffing = inServer.Sniffing()
}
dialIslazy := iics.defaultClient.IsLazyTls()
@@ -793,6 +799,8 @@ func passToOutClient(iics incomingInserverConnState, isfallback bool, wlc net.Co
}
if inServer != nil {
desc.InTag = inServer.GetTag()
} else {
desc.InTag = iics.inTag
}
if uc, ok := wlc.(utils.User); ok {
desc.UserIdentityStr = uc.IdentityStr()

View File

@@ -105,7 +105,9 @@ http://ivo-wang.github.io/2018/02/24/ss-redir/
package tproxy
import (
"log"
"net"
"time"
"github.com/e1732a364fed/v2ray_simple/netLayer"
)
@@ -120,10 +122,26 @@ type Machine struct {
func (m *Machine) Stop() {
if m.Listener != nil {
m.Listener.Close()
log.Println("closing tproxy listener")
//后来发现,不知为何,这个 Close调用会卡住
ch := make(chan int)
go func() {
m.Listener.Close()
close(ch)
}()
tCh := time.After(time.Second)
select {
case <-tCh:
log.Println("close tproxy listener timeout")
case <-ch:
break
}
}
if m.UDPConn != nil {
log.Println("closing tproxy udp conn")
m.UDPConn.Close()
}

View File

@@ -8,6 +8,13 @@ import (
"github.com/e1732a364fed/v2ray_simple/utils"
)
//用于 tproxy 和 tun/tap 这种 只有 网络层 和传输层的情况
type LesserConf struct {
Addr string
Tag string
UseSniffing bool
}
// CommonConf is the common part of ListenConf and DialConf.
type CommonConf struct {
Tag string `toml:"tag"` //可选

View File

@@ -61,16 +61,25 @@ func (ClientCreator) NewClient(dc *proxy.DialConf) (proxy.Client, error) {
c.user = utils.V2rayUser(uuid)
c.opt = OptChunkStream
hasSetSecurityByExtra := false
if len(dc.Extra) > 0 {
if thing := dc.Extra["vmess_security"]; thing != nil {
if str, ok := thing.(string); ok {
if err = c.specifySecurityByStr(str); err != nil {
err = c.specifySecurityByStr(str)
if err == nil {
hasSetSecurityByExtra = true
} else {
return nil, err
}
}
}
} else {
}
if !hasSetSecurityByExtra {
c.specifySecurityByStr("")
}

View File

@@ -11,15 +11,15 @@ import (
)
//非阻塞。监听透明代理
func ListenTproxy(addr string, defaultOutClientForThis proxy.Client, routePolicy *netLayer.RoutePolicy) (tm *tproxy.Machine) {
func ListenTproxy(lc proxy.LesserConf, defaultOutClientForThis proxy.Client, routePolicy *netLayer.RoutePolicy) (tm *tproxy.Machine) {
utils.Info("Start running Tproxy")
ad, err := netLayer.NewAddr(addr)
ad, err := netLayer.NewAddr(lc.Addr)
if err != nil {
panic(err)
}
//因为 tproxy比较特殊, 不属于 proxy.Server, 所以 需要 独立的 转发过程去处理.
lis, err := startLoopTCP(ad, defaultOutClientForThis, &proxy.RoutingEnv{
lis, err := startLoopTCP(ad, lc, defaultOutClientForThis, &proxy.RoutingEnv{
RoutePolicy: routePolicy,
})
if err != nil {
@@ -28,7 +28,7 @@ func ListenTproxy(addr string, defaultOutClientForThis proxy.Client, routePolicy
}
return
}
udpConn := startLoopUDP(ad, defaultOutClientForThis, &proxy.RoutingEnv{
udpConn := startLoopUDP(ad, lc, defaultOutClientForThis, &proxy.RoutingEnv{
RoutePolicy: routePolicy,
})
@@ -38,7 +38,7 @@ func ListenTproxy(addr string, defaultOutClientForThis proxy.Client, routePolicy
}
//非阻塞
func startLoopTCP(ad netLayer.Addr, defaultOutClientForThis proxy.Client, env *proxy.RoutingEnv) (net.Listener, error) {
func startLoopTCP(ad netLayer.Addr, lc proxy.LesserConf, defaultOutClientForThis proxy.Client, env *proxy.RoutingEnv) (net.Listener, error) {
return netLayer.ListenAndAccept("tcp", ad.String(), &netLayer.Sockopt{TProxy: true}, 0, func(conn net.Conn) {
tcpconn := conn.(*net.TCPConn)
targetAddr := tproxy.HandshakeTCP(tcpconn)
@@ -48,6 +48,8 @@ func startLoopTCP(ad netLayer.Addr, defaultOutClientForThis proxy.Client, env *p
}
passToOutClient(incomingInserverConnState{
inTag: lc.Tag,
useSniffing: lc.UseSniffing,
wrappedConn: tcpconn,
defaultClient: defaultOutClientForThis,
routingEnv: env,
@@ -57,7 +59,7 @@ func startLoopTCP(ad netLayer.Addr, defaultOutClientForThis proxy.Client, env *p
}
//非阻塞
func startLoopUDP(ad netLayer.Addr, defaultOutClientForThis proxy.Client, env *proxy.RoutingEnv) *net.UDPConn {
func startLoopUDP(ad netLayer.Addr, lc proxy.LesserConf, defaultOutClientForThis proxy.Client, env *proxy.RoutingEnv) *net.UDPConn {
ad.Network = "udp"
conn, err := ad.ListenUDP_withOpt(&netLayer.Sockopt{TProxy: true})
if err != nil {
@@ -83,6 +85,8 @@ func startLoopUDP(ad netLayer.Addr, defaultOutClientForThis proxy.Client, env *p
}
go passToOutClient(incomingInserverConnState{
inTag: lc.Tag,
useSniffing: lc.UseSniffing,
defaultClient: defaultOutClientForThis,
routingEnv: env,
}, false, nil, msgConn, raddr)

View File

@@ -11,7 +11,7 @@ import (
)
//非阻塞。在非linux系统中无效。
func ListenTproxy(string, proxy.Client, *netLayer.RoutePolicy) (_ *tproxy.Machine) {
func ListenTproxy(lc proxy.LesserConf, defaultClient proxy.Client, routePolicy *netLayer.RoutePolicy) (_ *tproxy.Machine) {
utils.Error("Tproxy not possible on non-linux device")
return
}