mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 09:25:41 +08:00
vless: support fallback to a http server
This commit is contained in:
parent
422869b37a
commit
829a0d7f80
20
.github/workflows/docker.yml
vendored
20
.github/workflows/docker.yml
vendored
@ -1,20 +0,0 @@
|
|||||||
name: Publish Docker image
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
push_to_registry:
|
|
||||||
name: Push Docker image to Docker Hub
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Check out the repo
|
|
||||||
uses: actions/checkout@v2
|
|
||||||
- name: Push to Docker Hub
|
|
||||||
uses: docker/build-push-action@v1
|
|
||||||
with:
|
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
|
||||||
repository: nadoo/glider
|
|
||||||
tag_with_ref: true
|
|
||||||
|
|
@ -167,7 +167,7 @@ VMess scheme:
|
|||||||
vmess://[security:]uuid@host:port?alterID=num
|
vmess://[security:]uuid@host:port?alterID=num
|
||||||
|
|
||||||
VLESS scheme:
|
VLESS scheme:
|
||||||
vless://uuid@host:port
|
vless://uuid@host:port[?fallback=127.0.0.1:80]
|
||||||
|
|
||||||
Trojan scheme:
|
Trojan scheme:
|
||||||
trojan://pass@host:port[?skipVerify=true]
|
trojan://pass@host:port[?skipVerify=true]
|
||||||
|
@ -162,7 +162,7 @@ func usage() {
|
|||||||
fmt.Fprintf(w, "\n")
|
fmt.Fprintf(w, "\n")
|
||||||
|
|
||||||
fmt.Fprintf(w, "VLESS scheme:\n")
|
fmt.Fprintf(w, "VLESS scheme:\n")
|
||||||
fmt.Fprintf(w, " vless://uuid@host:port\n")
|
fmt.Fprintf(w, " vless://uuid@host:port[?fallback=127.0.0.1:80]\n")
|
||||||
fmt.Fprintf(w, "\n")
|
fmt.Fprintf(w, "\n")
|
||||||
|
|
||||||
fmt.Fprintf(w, "Trojan scheme:\n")
|
fmt.Fprintf(w, "Trojan scheme:\n")
|
||||||
|
@ -45,6 +45,8 @@ listen=socks5://:1080
|
|||||||
|
|
||||||
# listen on 1234 as vless proxy server.
|
# listen on 1234 as vless proxy server.
|
||||||
# listen=vless://uuid@:1234
|
# listen=vless://uuid@:1234
|
||||||
|
# listen on 1234 as vless proxy server, fallback to 127.0.0.1:8080 http server when client auth failed.
|
||||||
|
# listen=vless://uuid@:1234?fallback=127.0.0.1:8080
|
||||||
|
|
||||||
# listen on 1081 as a linux transparent proxy server.
|
# listen on 1081 as a linux transparent proxy server.
|
||||||
# listen=redir://:1081
|
# listen=redir://:1081
|
||||||
|
@ -49,41 +49,62 @@ func (s *VLess) Serve(c net.Conn) {
|
|||||||
c.SetKeepAlive(true)
|
c.SetKeepAlive(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
c = NewServerConn(c)
|
var fallback bool
|
||||||
cmd, err := s.readHeader(c)
|
var dialer proxy.Dialer
|
||||||
if err != nil {
|
target := s.fallback
|
||||||
log.F("[vless] verify header error: %v", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tgt, err := ReadAddrString(c)
|
wbuf := pool.GetWriteBuffer()
|
||||||
|
defer pool.PutWriteBuffer(wbuf)
|
||||||
|
|
||||||
|
cmd, err := s.readHeader(io.TeeReader(c, wbuf))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[vless] get target error: %v", err)
|
if s.fallback == "" {
|
||||||
return
|
log.F("[vless] verify header error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fallback = true
|
||||||
|
log.F("[vless] verify header error: %v, fallback to %s", err, s.fallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
network := "tcp"
|
network := "tcp"
|
||||||
dialer := s.proxy.NextDialer(tgt)
|
dialer = s.proxy.NextDialer(target)
|
||||||
if cmd == CmdUDP {
|
if !fallback {
|
||||||
// there is no upstream proxy, just serve it
|
c = NewServerConn(c)
|
||||||
if dialer.Addr() == "DIRECT" {
|
target, err = ReadAddrString(c)
|
||||||
s.ServeUoT(c, tgt)
|
if err != nil {
|
||||||
|
log.F("[vless] get target error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
network = "udp"
|
|
||||||
|
if cmd == CmdUDP {
|
||||||
|
// there is no upstream proxy, just serve it
|
||||||
|
if dialer.Addr() == "DIRECT" {
|
||||||
|
s.ServeUoT(c, target)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
network = "udp"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, err := dialer.Dial(network, tgt)
|
rc, err := dialer.Dial(network, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[vless] %s <-> %s via %s, error in dial: %v", c.RemoteAddr(), tgt, dialer.Addr(), err)
|
log.F("[vless] %s <-> %s via %s, error in dial: %v", c.RemoteAddr(), target, dialer.Addr(), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rc.Close()
|
defer rc.Close()
|
||||||
|
|
||||||
log.F("[vless] %s <-> %s via %s", c.RemoteAddr(), tgt, dialer.Addr())
|
if fallback {
|
||||||
|
_, err := rc.Write(wbuf.Bytes())
|
||||||
|
if err != nil {
|
||||||
|
log.F("[vless] write to rc error: %v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
log.F("[vless] %s <-> %s via %s", c.RemoteAddr(), target, dialer.Addr())
|
||||||
|
|
||||||
if err = proxy.Relay(c, rc); err != nil {
|
if err = proxy.Relay(c, rc); err != nil {
|
||||||
log.F("[vless] %s <-> %s via %s, relay error: %v", c.RemoteAddr(), tgt, dialer.Addr(), err)
|
log.F("[vless] %s <-> %s via %s, relay error: %v", c.RemoteAddr(), target, dialer.Addr(), err)
|
||||||
// record remote conn failure only
|
// record remote conn failure only
|
||||||
if !strings.Contains(err.Error(), s.addr) {
|
if !strings.Contains(err.Error(), s.addr) {
|
||||||
s.proxy.Record(dialer, false)
|
s.proxy.Record(dialer, false)
|
||||||
@ -91,7 +112,7 @@ func (s *VLess) Serve(c net.Conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServeUOT serves udp over tcp requests.
|
// 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", "")
|
rc, err := net.ListenPacket("udp", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -118,6 +139,10 @@ func (s *VLess) ServeUoT(c net.Conn, tgt string) {
|
|||||||
|
|
||||||
length := binary.BigEndian.Uint16(buf[:2])
|
length := binary.BigEndian.Uint16(buf[:2])
|
||||||
n, err := io.ReadFull(c, buf[:length])
|
n, err := io.ReadFull(c, buf[:length])
|
||||||
|
if err != nil {
|
||||||
|
log.F("[vless] read payload error: %s\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
_, err = rc.WriteTo(buf[:n], tgtAddr)
|
_, err = rc.WriteTo(buf[:n], tgtAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -127,7 +152,7 @@ func (s *VLess) ServeUoT(c net.Conn, tgt string) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
log.F("[vless] %s <-tcp-> %s - %s <-udp-> %s via DIRECT", c.RemoteAddr(), c.LocalAddr(), rc.LocalAddr(), tgt)
|
log.F("[vless] %s <-tcp-> %s - %s <-udp-> %s", c.RemoteAddr(), c.LocalAddr(), rc.LocalAddr(), tgt)
|
||||||
|
|
||||||
buf := pool.GetBuffer(proxy.UDPBufSize)
|
buf := pool.GetBuffer(proxy.UDPBufSize)
|
||||||
defer pool.PutBuffer(buf)
|
defer pool.PutBuffer(buf)
|
||||||
|
@ -24,10 +24,11 @@ const (
|
|||||||
|
|
||||||
// VLess struct.
|
// VLess struct.
|
||||||
type VLess struct {
|
type VLess struct {
|
||||||
dialer proxy.Dialer
|
dialer proxy.Dialer
|
||||||
proxy proxy.Proxy
|
proxy proxy.Proxy
|
||||||
addr string
|
addr string
|
||||||
uuid [16]byte
|
uuid [16]byte
|
||||||
|
fallback string
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -55,6 +56,11 @@ func NewVLess(s string, d proxy.Dialer, p proxy.Proxy) (*VLess, error) {
|
|||||||
uuid: uuid,
|
uuid: uuid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v.fallback = "127.0.0.1:80"
|
||||||
|
if custom := u.Query().Get("fallback"); custom != "" {
|
||||||
|
v.fallback = custom
|
||||||
|
}
|
||||||
|
|
||||||
return v, nil
|
return v, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user