vless: support udp in server mode

This commit is contained in:
nadoo 2020-10-04 00:10:24 +08:00
parent cd42337169
commit 422869b37a
5 changed files with 74 additions and 19 deletions

View File

@ -306,7 +306,7 @@ Examples:
Services:
dhcpd: service=dhcpd,INTERFACE,START_IP,END_IP
e.g.,service=dhcpd,en0,192.168.50.100,192.168.50.199
e.g.,service=dhcpd,eth1,192.168.50.100,192.168.50.199
```
</details>
@ -335,7 +335,7 @@ glider -config CONFIGPATH -listen :8080 -verbose
- dhcpd:
- service=dhcpd,INTERFACE,START_IP,END_IP
- e.g., service=dhcpd,en0,192.168.50.100,192.168.50.199
- e.g., service=dhcpd,eth1,192.168.50.100,192.168.50.199
## Linux Service

View File

@ -321,6 +321,6 @@ func usage() {
fmt.Fprintf(w, "Services:\n")
fmt.Fprintf(w, " dhcpd: service=dhcpd,INTERFACE,START_IP,END_IP\n")
fmt.Fprintf(w, " e.g.,service=dhcpd,en0,192.168.50.100,192.168.50.199\n")
fmt.Fprintf(w, " e.g.,service=dhcpd,eth1,192.168.50.100,192.168.50.199\n")
fmt.Fprintf(w, "\n")
}

View File

@ -221,7 +221,7 @@ dnsrecord=www.example.com/2606:2800:220:1:248:1893:25c8:1946
# SERVICES
# service=dhcpd,INTERFACE,START_IP,END_IP
# e.g.:
# service=dhcpd,en0,192.168.50.100,192.168.50.199
# service=dhcpd,eth1,192.168.50.100,192.168.50.199
# INTERFACE SPECIFIC
# ------------------

View File

@ -67,7 +67,7 @@ func (s *SS) Serve(c net.Conn) {
if uot && dialer.Addr() == "DIRECT" {
rc, err := net.ListenPacket("udp", "")
if err != nil {
log.F("[ssuot] UDP remote listen error: %v", err)
log.F("[ss] UDP remote listen error: %v", err)
}
defer rc.Close()
@ -76,7 +76,7 @@ func (s *SS) Serve(c net.Conn) {
n, err := c.Read(buf)
if err != nil {
log.F("[ssuot] error in read: %s\n", err)
log.F("[ss] error in read: %s\n", err)
return
}
@ -85,7 +85,7 @@ func (s *SS) Serve(c net.Conn) {
n, _, err = rc.ReadFrom(buf)
if err != nil {
log.F("[ssuot] read error: %v", err)
log.F("[ss] read error: %v", err)
}
c.Write(buf[:n])

View File

@ -2,6 +2,7 @@ package vless
import (
"bytes"
"encoding/binary"
"fmt"
"io"
"io/ioutil"
@ -61,18 +62,18 @@ func (s *VLess) Serve(c net.Conn) {
return
}
switch cmd {
case CmdTCP:
s.ServeTCP(c, tgt)
case CmdUDP:
s.ServeUOT(c, tgt)
}
}
// ServeTCP serves tcp requests.
func (s *VLess) ServeTCP(c net.Conn, tgt string) {
network := "tcp"
dialer := s.proxy.NextDialer(tgt)
rc, err := dialer.Dial("tcp", tgt)
if cmd == CmdUDP {
// there is no upstream proxy, just serve it
if dialer.Addr() == "DIRECT" {
s.ServeUoT(c, tgt)
return
}
network = "udp"
}
rc, err := dialer.Dial(network, tgt)
if err != nil {
log.F("[vless] %s <-> %s via %s, error in dial: %v", c.RemoteAddr(), tgt, dialer.Addr(), err)
return
@ -91,7 +92,61 @@ func (s *VLess) ServeTCP(c net.Conn, tgt string) {
}
// ServeUOT serves udp over tcp requests.
func (s *VLess) ServeUOT(c net.Conn, tgt string) {
func (s *VLess) ServeUoT(c net.Conn, tgt string) {
rc, err := net.ListenPacket("udp", "")
if err != nil {
log.F("[vless] UDP remote listen error: %v", err)
return
}
defer rc.Close()
tgtAddr, err := net.ResolveUDPAddr("udp", tgt)
if err != nil {
log.F("[vless] error in ResolveUDPAddr: %v", err)
return
}
go func() {
buf := pool.GetBuffer(proxy.UDPBufSize)
defer pool.PutBuffer(buf)
for {
_, err := io.ReadFull(c, buf[:2])
if err != nil {
log.F("[vless] read c error: %s\n", err)
return
}
length := binary.BigEndian.Uint16(buf[:2])
n, err := io.ReadFull(c, buf[:length])
_, err = rc.WriteTo(buf[:n], tgtAddr)
if err != nil {
log.F("[vless] write rc error: %s\n", err)
return
}
}
}()
log.F("[vless] %s <-tcp-> %s - %s <-udp-> %s via DIRECT", c.RemoteAddr(), c.LocalAddr(), rc.LocalAddr(), tgt)
buf := pool.GetBuffer(proxy.UDPBufSize)
defer pool.PutBuffer(buf)
for {
n, _, err := rc.ReadFrom(buf[2:])
if err != nil {
log.F("[vless] read rc error: %v", err)
break
}
binary.BigEndian.PutUint16(buf[:2], uint16(n))
_, err = c.Write(buf[:2+n])
if err != nil {
log.F("[vless] write c error: %v", err)
break
}
}
}
func (s *VLess) readHeader(r io.Reader) (CmdType, error) {