mirror of
https://github.com/nadoo/glider.git
synced 2025-04-11 14:53:15 +08:00
proxy: optimize timeout handling in udp copy
This commit is contained in:
parent
4b313a3fe1
commit
2ad3498abd
@ -96,7 +96,7 @@ glider -verbose -listen :8443 -forward SCHEME://HOST:PORT
|
||||
#### Help
|
||||
|
||||
<details>
|
||||
<summary>glider -help</summary>
|
||||
<summary> glider -help</summary>
|
||||
|
||||
```bash
|
||||
Usage: glider [-listen URL]... [-forward URL]... [OPTION]...
|
||||
@ -228,7 +228,7 @@ glider 0.16.0, https://github.com/nadoo/glider
|
||||
#### Schemes
|
||||
|
||||
<details>
|
||||
<summary>glider -scheme all</summary>
|
||||
<summary> glider -scheme all</summary>
|
||||
|
||||
```bash
|
||||
KCP scheme:
|
||||
@ -343,7 +343,7 @@ TLS and Websocket with a specified proxy protocol:
|
||||
#### Examples
|
||||
|
||||
<details>
|
||||
<summary>glider -example</summary>
|
||||
<summary> glider -example</summary>
|
||||
|
||||
```bash
|
||||
Examples:
|
||||
@ -397,7 +397,8 @@ Examples:
|
||||
- service=dhcpd,eth1,192.168.1.100,192.168.1.199,720
|
||||
- service=dhcpd,eth2,192.168.2.100,192.168.2.199,720,fc:23:34:9e:25:01=192.168.2.101
|
||||
- service=dhcpd-failover,INTERFACE,START_IP,END_IP,LEASE_MINUTES[,MAC=IP,MAC=IP...]
|
||||
- note: only serve requests when there's no other dhcp server exists
|
||||
- note: only serve requests when there's no other dhcp server exists in lan
|
||||
- detect interval: 1min
|
||||
|
||||
## Linux Service
|
||||
|
||||
|
4
go.mod
4
go.mod
@ -12,7 +12,7 @@ require (
|
||||
github.com/nadoo/ipset v0.4.1-0.20220218075046-ca3cdce74266
|
||||
github.com/xtaci/kcp-go/v5 v5.6.1
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292
|
||||
golang.org/x/sys v0.0.0-20220224003255-dbe011f71a99
|
||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7
|
||||
)
|
||||
|
||||
require (
|
||||
@ -26,7 +26,7 @@ require (
|
||||
github.com/templexxx/xorsimd v0.4.1 // indirect
|
||||
github.com/tjfoc/gmsm v1.4.1 // indirect
|
||||
github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 // indirect
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect
|
||||
)
|
||||
|
||||
// Replace dependency modules with local developing copy
|
||||
|
9
go.sum
9
go.sum
@ -49,7 +49,6 @@ github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqo
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
||||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.11 h1:i2lw1Pm7Yi/4O6XCSyJWqEHI2MDw2FzUK6o/D21xn2A=
|
||||
@ -137,8 +136,8 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk=
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f h1:oA4XRj0qtSt8Yo1Zms0CUlsT3KG69V2UGQWPBxujDmc=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -165,8 +164,8 @@ golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220224003255-dbe011f71a99 h1:Us899Z5PCfOrSgeCYWobI1/bSigAz9Rhf8+fz5Grkzc=
|
||||
golang.org/x/sys v0.0.0-20220224003255-dbe011f71a99/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7 h1:BXxu8t6QN0G1uff4bzZzSkpsax8+ALqTGUtz08QrV00=
|
||||
golang.org/x/sys v0.0.0-20220224120231-95c6836cb0e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
@ -175,13 +175,20 @@ func CopyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
|
||||
return written, err
|
||||
}
|
||||
|
||||
// RelayUDP copys from src to dst at target with read timeout.
|
||||
func RelayUDP(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration) error {
|
||||
// CopyUDP copys from src to dst at target with read timeout.
|
||||
// if step sets to non-zero value,
|
||||
// the read timeout will be increased from 0 to timeout by step in every read operation.
|
||||
func CopyUDP(dst net.PacketConn, target net.Addr, src net.PacketConn, timeout time.Duration, step time.Duration) error {
|
||||
b := pool.GetBuffer(UDPBufSize)
|
||||
defer pool.PutBuffer(b)
|
||||
|
||||
var t time.Duration
|
||||
for {
|
||||
src.SetReadDeadline(time.Now().Add(timeout))
|
||||
if t += step; t == 0 || t > timeout {
|
||||
t = timeout
|
||||
}
|
||||
|
||||
src.SetReadDeadline(time.Now().Add(t))
|
||||
n, _, err := src.ReadFrom(b)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -151,7 +151,7 @@ func (s *Socks5) serveSession(session *Session) {
|
||||
defer dstPC.Close()
|
||||
|
||||
go func() {
|
||||
proxy.RelayUDP(session.srcPC, session.src, dstPC, 2*time.Minute)
|
||||
proxy.CopyUDP(session.srcPC, session.src, dstPC, 2*time.Minute, 5*time.Second)
|
||||
nm.Delete(session.key)
|
||||
close(session.finCh)
|
||||
}()
|
||||
|
@ -138,7 +138,7 @@ func (s *SS) serveSession(session *Session) {
|
||||
defer dstPC.Close()
|
||||
|
||||
go func() {
|
||||
proxy.RelayUDP(session.srcPC, session.src, dstPC, 2*time.Minute)
|
||||
proxy.CopyUDP(session.srcPC, session.src, dstPC, 2*time.Minute, 5*time.Second)
|
||||
nm.Delete(session.key)
|
||||
close(session.finCh)
|
||||
}()
|
||||
|
@ -118,7 +118,7 @@ func (s *TProxy) serveSession(session *Session) {
|
||||
defer srcPC.Close()
|
||||
|
||||
go func() {
|
||||
proxy.RelayUDP(srcPC, session.src, dstPC, 2*time.Minute)
|
||||
proxy.CopyUDP(srcPC, session.src, dstPC, 2*time.Minute, 5*time.Second)
|
||||
nm.Delete(session.key)
|
||||
close(session.finCh)
|
||||
}()
|
||||
|
@ -35,7 +35,7 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
return 0, nil, err
|
||||
}
|
||||
|
||||
// TODO: we know that we use it in proxy.RelayUDP and the length of b is enough, check it later.
|
||||
// TODO: we know that we use it in proxy.CopyUDP and the length of b is enough, check it later.
|
||||
if len(b) < 2 {
|
||||
return 0, nil, errors.New("buf size is not enough")
|
||||
}
|
||||
|
@ -210,6 +210,6 @@ func (s *Trojan) ServeUoT(c net.Conn, tgt socks.Addr) {
|
||||
pc := NewPktConn(c, tgt)
|
||||
log.F("[trojan] %s <-tcp-> %s - %s <-udp-> %s", c.RemoteAddr(), c.LocalAddr(), rc.LocalAddr(), tgt)
|
||||
|
||||
go proxy.RelayUDP(rc, tgtAddr, pc, 2*time.Minute)
|
||||
proxy.RelayUDP(pc, nil, rc, 2*time.Minute)
|
||||
go proxy.CopyUDP(rc, tgtAddr, pc, 2*time.Minute, 5*time.Second)
|
||||
proxy.CopyUDP(pc, nil, rc, 2*time.Minute, 5*time.Second)
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ func (s *UDP) serveSession(session *Session) {
|
||||
defer dstPC.Close()
|
||||
|
||||
go func() {
|
||||
proxy.RelayUDP(session.srcPC, session.src, dstPC, 2*time.Minute)
|
||||
proxy.CopyUDP(session.srcPC, session.src, dstPC, 2*time.Minute, 5*time.Second)
|
||||
nm.Delete(session.key)
|
||||
close(session.finCh)
|
||||
}()
|
||||
|
@ -148,7 +148,7 @@ func (s *Unix) serveSession(session *Session) {
|
||||
defer dstPC.Close()
|
||||
|
||||
go func() {
|
||||
proxy.RelayUDP(session.srcPC, session.src, dstPC, 2*time.Minute)
|
||||
proxy.CopyUDP(session.srcPC, session.src, dstPC, 2*time.Minute, 5*time.Second)
|
||||
nm.Delete(session.key)
|
||||
close(session.finCh)
|
||||
}()
|
||||
|
@ -16,7 +16,7 @@ type PktConn struct{ net.Conn }
|
||||
func NewPktConn(c net.Conn) *PktConn { return &PktConn{Conn: c} }
|
||||
|
||||
// ReadFrom implements the necessary function of net.PacketConn.
|
||||
// TODO: we know that we use it in proxy.RelayUDP and the length of b is enough, check it later.
|
||||
// TODO: we know that we use it in proxy.CopyUDP and the length of b is enough, check it later.
|
||||
func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
if len(b) < 2 {
|
||||
return 0, nil, errors.New("buf size is not enough")
|
||||
|
@ -165,8 +165,8 @@ func (s *VLess) ServeUoT(c net.Conn, tgt string) {
|
||||
pc := NewPktConn(c)
|
||||
log.F("[vless] %s <-tcp-> %s - %s <-udp-> %s", c.RemoteAddr(), c.LocalAddr(), rc.LocalAddr(), tgt)
|
||||
|
||||
go proxy.RelayUDP(rc, tgtAddr, pc, 2*time.Minute)
|
||||
proxy.RelayUDP(pc, nil, rc, 2*time.Minute)
|
||||
go proxy.CopyUDP(rc, tgtAddr, pc, 2*time.Minute, 5*time.Second)
|
||||
proxy.CopyUDP(pc, nil, rc, 2*time.Minute, 5*time.Second)
|
||||
}
|
||||
|
||||
// ServerConn is a vless client connection.
|
||||
|
@ -19,7 +19,7 @@ func discovery(intf *net.Interface) (found bool) {
|
||||
}
|
||||
defer pc.Close()
|
||||
|
||||
discovery, err := dhcpv4.NewDiscovery(intf.HardwareAddr, dhcpv4.WithBroadcast(true), dhcpv4.WithRequestedOptions(dhcpv4.OptionDomainNameServer))
|
||||
discovery, err := dhcpv4.NewDiscovery(intf.HardwareAddr, dhcpv4.WithBroadcast(true))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ func New(failover bool, args ...string) (*dhcpd, error) {
|
||||
}
|
||||
|
||||
log.F("[dhcpd] Listening on interface %s(%s/%d.%d.%d.%d), failover mode: %t",
|
||||
iface, ip, mask[0], mask[1], mask[2], mask[3], dhcpd.getFailover())
|
||||
iface, ip, mask[0], mask[1], mask[2], mask[3], dhcpd.isFailover())
|
||||
|
||||
return dhcpd, nil
|
||||
}
|
||||
@ -109,7 +109,12 @@ func New(failover bool, args ...string) (*dhcpd, error) {
|
||||
func (d *dhcpd) Run() {
|
||||
if d.failover {
|
||||
d.setFailover(discovery(d.iface))
|
||||
go d.detect(time.Second * 60)
|
||||
go func() {
|
||||
for {
|
||||
d.setFailover(discovery(d.iface))
|
||||
time.Sleep(time.Second * 60)
|
||||
}
|
||||
}()
|
||||
}
|
||||
d.server.Serve()
|
||||
}
|
||||
@ -117,6 +122,10 @@ func (d *dhcpd) Run() {
|
||||
func (d *dhcpd) handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4.Handler {
|
||||
return func(conn net.PacketConn, peer net.Addr, m *dhcpv4.DHCPv4) {
|
||||
|
||||
if d.isFailover() || bytes.Equal(d.iface.HardwareAddr, m.ClientHWAddr) {
|
||||
return
|
||||
}
|
||||
|
||||
var reqType, replyType dhcpv4.MessageType
|
||||
switch reqType = m.MessageType(); reqType {
|
||||
case dhcpv4.MessageTypeDiscover:
|
||||
@ -136,10 +145,6 @@ func (d *dhcpd) handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4
|
||||
return
|
||||
}
|
||||
|
||||
if d.getFailover() || bytes.Equal(d.iface.HardwareAddr, m.ClientHWAddr) {
|
||||
return
|
||||
}
|
||||
|
||||
replyIP, err := pool.LeaseIP(m.ClientHWAddr)
|
||||
if err != nil {
|
||||
log.F("[dpcpd] %s: can not assign IP, error %s", d.name, err)
|
||||
@ -176,7 +181,7 @@ func (d *dhcpd) handleDHCP(serverIP net.IP, mask net.IPMask, pool *Pool) server4
|
||||
}
|
||||
}
|
||||
|
||||
func (d *dhcpd) getFailover() bool {
|
||||
func (d *dhcpd) isFailover() bool {
|
||||
d.mu.Lock()
|
||||
defer d.mu.Unlock()
|
||||
return d.failover
|
||||
@ -190,19 +195,12 @@ func (d *dhcpd) setFailover(v bool) {
|
||||
if v {
|
||||
log.F("[dpcpd] %s: dhcp server detected, enter failover mode", d.iface.Name)
|
||||
} else {
|
||||
log.F("[dpcpd] %s: no dhcp server detected, exit failover mode", d.iface.Name)
|
||||
log.F("[dpcpd] %s: no dhcp server detected, exit failover mode and serve requests", d.iface.Name)
|
||||
}
|
||||
}
|
||||
d.failover = v
|
||||
}
|
||||
|
||||
func (d *dhcpd) detect(interval time.Duration) {
|
||||
for {
|
||||
d.setFailover(discovery(d.iface))
|
||||
time.Sleep(interval)
|
||||
}
|
||||
}
|
||||
|
||||
func ifaceAddr(iface string) (*net.Interface, net.IP, net.IPMask, error) {
|
||||
intf, err := net.InterfaceByName(iface)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user