mirror of
https://github.com/nadoo/glider.git
synced 2025-02-23 09:25:41 +08:00
proxy: support server mode of PROXY protocol v1
This commit is contained in:
parent
32e1c37cfe
commit
7486373821
@ -65,7 +65,8 @@ we can set up local listeners as proxy servers, and forward requests to internet
|
|||||||
|Unix |√|√|√|√|transport client & server
|
|Unix |√|√|√|√|transport client & server
|
||||||
|Smux |√| |√| |transport client & server
|
|Smux |√| |√| |transport client & server
|
||||||
|Websocket(WS)|√| |√| |transport client & server
|
|Websocket(WS)|√| |√| |transport client & server
|
||||||
|WS Secure |√| |√| |transport client & server
|
|WS Secure |√| |√| |websocket secure (wss)
|
||||||
|
|Proxy Proto |√| |√| |transport client & server
|
||||||
|Simple-Obfs | | |√| |transport client only
|
|Simple-Obfs | | |√| |transport client only
|
||||||
|Redir |√| | | |linux redirect proxy
|
|Redir |√| | | |linux redirect proxy
|
||||||
|Redir6 |√| | | |linux redirect proxy(ipv6)
|
|Redir6 |√| | | |linux redirect proxy(ipv6)
|
||||||
@ -182,8 +183,8 @@ glider -verbose -listen :8443 -forward SCHEME://HOST:PORT
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
Available schemes:
|
Available schemes:
|
||||||
listen: mixed ss socks5 http vless trojan trojanc redir redir6 tproxy tcp udp tls ws wss unix smux kcp
|
listen: mixed ss socks5 http vless trojan trojanc redir redir6 tproxy tcp udp tls ws wss unix smux kcp pxyproto
|
||||||
forward: direct reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tcp udp tls ws wss unix smux kcp simple-obfs
|
forward: direct reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tcp udp tls ws wss unix smux kcp simple-obfs pxyproto
|
||||||
|
|
||||||
Socks5 scheme:
|
Socks5 scheme:
|
||||||
socks://[user:pass@]host:port
|
socks://[user:pass@]host:port
|
||||||
@ -397,7 +398,7 @@ Examples:
|
|||||||
// _ "github.com/nadoo/glider/proxy/kcp"
|
// _ "github.com/nadoo/glider/proxy/kcp"
|
||||||
```
|
```
|
||||||
|
|
||||||
3. Build it(requires **Go 1.16+** )
|
3. Build it(requires **Go 1.17+** )
|
||||||
```bash
|
```bash
|
||||||
go build -v -ldflags "-s -w"
|
go build -v -ldflags "-s -w"
|
||||||
```
|
```
|
||||||
|
@ -150,8 +150,8 @@ func usage() {
|
|||||||
fmt.Fprintf(w, "\n")
|
fmt.Fprintf(w, "\n")
|
||||||
|
|
||||||
fmt.Fprintf(w, "Available schemes:\n")
|
fmt.Fprintf(w, "Available schemes:\n")
|
||||||
fmt.Fprintf(w, " listen: mixed ss socks5 http vless trojan trojanc redir redir6 tproxy tcp udp tls ws wss unix smux kcp\n")
|
fmt.Fprintf(w, " listen: mixed ss socks5 http vless trojan trojanc redir redir6 tproxy tcp udp tls ws wss unix smux kcp pxyproto\n")
|
||||||
fmt.Fprintf(w, " forward: direct reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tcp udp tls ws wss unix smux kcp simple-obfs\n")
|
fmt.Fprintf(w, " forward: direct reject ss socks4 socks5 http ssr ssh vless vmess trojan trojanc tcp udp tls ws wss unix smux kcp simple-obfs pxyproto\n")
|
||||||
fmt.Fprintf(w, "\n")
|
fmt.Fprintf(w, "\n")
|
||||||
|
|
||||||
fmt.Fprintf(w, "Socks5 scheme:\n")
|
fmt.Fprintf(w, "Socks5 scheme:\n")
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// UDPMaxLen is the max size of udp dns request.
|
// UDPMaxLen is the max size of udp dns request.
|
||||||
// https://tools.ietf.org/html/rfc1035#section-4.2.1
|
// https://www.rfc-editor.org/rfc/rfc1035#section-4.2.1
|
||||||
// Messages carried by UDP are restricted to 512 bytes (not counting the IP
|
// Messages carried by UDP are restricted to 512 bytes (not counting the IP
|
||||||
// or UDP headers). Longer messages are truncated and the TC bit is set in
|
// or UDP headers). Longer messages are truncated and the TC bit is set in
|
||||||
// the header.
|
// the header.
|
||||||
@ -36,7 +36,7 @@ const (
|
|||||||
const ClassINET uint16 = 1
|
const ClassINET uint16 = 1
|
||||||
|
|
||||||
// Message format:
|
// Message format:
|
||||||
// https://tools.ietf.org/html/rfc1035#section-4.1
|
// https://www.rfc-editor.org/rfc/rfc1035#section-4.1
|
||||||
// All communications inside of the domain protocol are carried in a single
|
// All communications inside of the domain protocol are carried in a single
|
||||||
// format called a message. The top level format of message is divided
|
// format called a message. The top level format of message is divided
|
||||||
// into 5 sections (some of which are empty in certain cases) shown below:
|
// into 5 sections (some of which are empty in certain cases) shown below:
|
||||||
@ -165,7 +165,7 @@ func UnmarshalMessage(b []byte) (*Message, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Header format:
|
// Header format:
|
||||||
// https://tools.ietf.org/html/rfc1035#section-4.1.1
|
// https://www.rfc-editor.org/rfc/rfc1035#section-4.1.1
|
||||||
// The header contains the following fields:
|
// The header contains the following fields:
|
||||||
//
|
//
|
||||||
// 1 1 1 1 1 1
|
// 1 1 1 1 1 1
|
||||||
@ -244,7 +244,7 @@ func UnmarshalHeader(b []byte, h *Header) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Question format:
|
// Question format:
|
||||||
// https://tools.ietf.org/html/rfc1035#section-4.1.2
|
// https://www.rfc-editor.org/rfc/rfc1035#section-4.1.2
|
||||||
// The question section is used to carry the "question" in most queries,
|
// The question section is used to carry the "question" in most queries,
|
||||||
// i.e., the parameters that define what is being asked. The section
|
// i.e., the parameters that define what is being asked. The section
|
||||||
// contains QDCOUNT (usually 1) entries, each of the following format:
|
// contains QDCOUNT (usually 1) entries, each of the following format:
|
||||||
@ -322,8 +322,8 @@ func (m *Message) UnmarshalQuestion(b []byte, q *Question) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RR format:
|
// RR format:
|
||||||
// https://tools.ietf.org/html/rfc1035#section-3.2.1
|
// https://www.rfc-editor.org/rfc/rfc1035#section-3.2.1
|
||||||
// https://tools.ietf.org/html/rfc1035#section-4.1.3
|
// https://www.rfc-editor.org/rfc/rfc1035#section-4.1.3
|
||||||
// The answer, authority, and additional sections all share the same
|
// The answer, authority, and additional sections all share the same
|
||||||
// format: a variable number of resource records, where the number of
|
// format: a variable number of resource records, where the number of
|
||||||
// records is specified in the corresponding count field in the header.
|
// records is specified in the corresponding count field in the header.
|
||||||
@ -479,7 +479,7 @@ func (m *Message) UnmarshalDomainTo(sb *strings.Builder, b []byte) (int, error)
|
|||||||
var idx, size int
|
var idx, size int
|
||||||
|
|
||||||
for len(b[idx:]) != 0 {
|
for len(b[idx:]) != 0 {
|
||||||
// https://tools.ietf.org/html/rfc1035#section-4.1.4
|
// https://www.rfc-editor.org/rfc/rfc1035#section-4.1.4
|
||||||
// "Message compression",
|
// "Message compression",
|
||||||
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
// +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
// | 1 1| OFFSET |
|
// | 1 1| OFFSET |
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
_ "github.com/nadoo/glider/proxy/kcp"
|
_ "github.com/nadoo/glider/proxy/kcp"
|
||||||
_ "github.com/nadoo/glider/proxy/mixed"
|
_ "github.com/nadoo/glider/proxy/mixed"
|
||||||
_ "github.com/nadoo/glider/proxy/obfs"
|
_ "github.com/nadoo/glider/proxy/obfs"
|
||||||
|
_ "github.com/nadoo/glider/proxy/pxyproto"
|
||||||
_ "github.com/nadoo/glider/proxy/reject"
|
_ "github.com/nadoo/glider/proxy/reject"
|
||||||
_ "github.com/nadoo/glider/proxy/smux"
|
_ "github.com/nadoo/glider/proxy/smux"
|
||||||
_ "github.com/nadoo/glider/proxy/socks4"
|
_ "github.com/nadoo/glider/proxy/socks4"
|
||||||
|
4
go.mod
4
go.mod
@ -9,8 +9,8 @@ require (
|
|||||||
github.com/dgryski/go-rc2 v0.0.0-20150621095337-8a9021637152
|
github.com/dgryski/go-rc2 v0.0.0-20150621095337-8a9021637152
|
||||||
github.com/ebfe/rc2 v0.0.0-20131011165748-24b9757f5521 // indirect
|
github.com/ebfe/rc2 v0.0.0-20131011165748-24b9757f5521 // indirect
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20210621130208-1cac67f12b1e
|
github.com/insomniacslk/dhcp v0.0.0-20210621130208-1cac67f12b1e
|
||||||
github.com/klauspost/cpuid/v2 v2.0.8 // indirect
|
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||||
github.com/klauspost/reedsolomon v1.9.12 // indirect
|
github.com/klauspost/reedsolomon v1.9.13 // indirect
|
||||||
github.com/mdlayher/raw v0.0.0-20210412142147-51b895745faf // indirect
|
github.com/mdlayher/raw v0.0.0-20210412142147-51b895745faf // indirect
|
||||||
github.com/nadoo/conflag v0.2.3
|
github.com/nadoo/conflag v0.2.3
|
||||||
github.com/nadoo/ipset v0.3.0
|
github.com/nadoo/ipset v0.3.0
|
||||||
|
10
go.sum
10
go.sum
@ -49,12 +49,12 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
|||||||
github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
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 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
|
||||||
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.2/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.6/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.8 h1:bhR2mgIlno/Sfk4oUbH4sPlc83z1yGrN9bvqiq3C33I=
|
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.8/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo=
|
github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo=
|
||||||
github.com/klauspost/reedsolomon v1.9.12 h1:EyOucRmcrLH+2hqKGdoA5SM8pwPKR6BJsf3r6zpYOA0=
|
github.com/klauspost/reedsolomon v1.9.13 h1:Xr0COKf7F0ACTXUNnz2ZFCWlUKlUTAUX3y7BODdUxqU=
|
||||||
github.com/klauspost/reedsolomon v1.9.12/go.mod h1:nLvuzNvy1ZDNQW30IuMc2ZWCbiqrJgdLoUS2X8HAUVg=
|
github.com/klauspost/reedsolomon v1.9.13/go.mod h1:eqPAcE7xar5CIzcdfwydOEdcmchAKAP/qs14y4GCBOk=
|
||||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE=
|
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7 h1:lez6TS6aAau+8wXUP3G9I3TGlmPFEq2CTxBaRqY6AGE=
|
||||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
|
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
|
||||||
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||||
|
@ -45,6 +45,12 @@ func (c *Conn) Peek(n int) ([]byte, error) { return c.r.Peek(n) }
|
|||||||
// WriteTo implements io.WriterTo.
|
// WriteTo implements io.WriterTo.
|
||||||
func (c *Conn) WriteTo(w io.Writer) (n int64, err error) { return c.r.WriteTo(w) }
|
func (c *Conn) WriteTo(w io.Writer) (n int64, err error) { return c.r.WriteTo(w) }
|
||||||
|
|
||||||
|
// Close closes the Conn.
|
||||||
|
func (c *Conn) Close() error {
|
||||||
|
pool.PutBufReader(c.r)
|
||||||
|
return c.Conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
// Relay relays between left and right.
|
// Relay relays between left and right.
|
||||||
func Relay(left, right net.Conn) error {
|
func Relay(left, right net.Conn) error {
|
||||||
var err, err1 error
|
var err, err1 error
|
||||||
@ -73,12 +79,6 @@ func Relay(left, right net.Conn) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the Conn.
|
|
||||||
func (c *Conn) Close() error {
|
|
||||||
pool.PutBufReader(c.r)
|
|
||||||
return c.Conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy copies from src to dst.
|
// Copy copies from src to dst.
|
||||||
func Copy(dst io.Writer, src io.Reader) (written int64, err error) {
|
func Copy(dst io.Writer, src io.Reader) (written int64, err error) {
|
||||||
dst = underlyingWriter(dst)
|
dst = underlyingWriter(dst)
|
||||||
|
@ -3,7 +3,7 @@ package http
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"fmt"
|
||||||
"net/textproto"
|
"net/textproto"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@ -12,7 +12,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Methods are http methods from rfc.
|
// Methods are http methods from rfc.
|
||||||
// https://www.ietf.org/rfc/rfc2616.txt, http methods must be uppercase
|
// https://www.rfc-editor.org/rfc/rfc2616, http methods must be uppercase
|
||||||
var Methods = [...][]byte{
|
var Methods = [...][]byte{
|
||||||
[]byte("GET"),
|
[]byte("GET"),
|
||||||
[]byte("POST"),
|
[]byte("POST"),
|
||||||
@ -46,7 +46,7 @@ func parseRequest(r *bufio.Reader) (*request, error) {
|
|||||||
|
|
||||||
method, uri, proto, ok := parseStartLine(line)
|
method, uri, proto, ok := parseStartLine(line)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("error in parseStartLine")
|
return nil, fmt.Errorf("error in parseStartLine: %s", line)
|
||||||
}
|
}
|
||||||
|
|
||||||
header, err := tpr.ReadMIMEHeader()
|
header, err := tpr.ReadMIMEHeader()
|
||||||
|
@ -51,7 +51,7 @@ func (s *HTTP) Serve(cc net.Conn) {
|
|||||||
c := proxy.NewConn(cc)
|
c := proxy.NewConn(cc)
|
||||||
req, err := parseRequest(c.Reader())
|
req, err := parseRequest(c.Reader())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.F("[http] can not parse request from %s", c.RemoteAddr())
|
log.F("[http] can not parse request from %s, error: %v", c.RemoteAddr(), err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// https://www.ietf.org/rfc/rfc5246.txt
|
// https://www.rfc-editor.org/rfc/rfc5246
|
||||||
// https://golang.org/src/crypto/tls/handshake_messages.go
|
// https://golang.org/src/crypto/tls/handshake_messages.go
|
||||||
|
|
||||||
// NOTE:
|
// NOTE:
|
||||||
|
134
proxy/pxyproto/server.go
Normal file
134
proxy/pxyproto/server.go
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
package pxyproto
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/nadoo/glider/log"
|
||||||
|
"github.com/nadoo/glider/proxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proxy.RegisterServer("pxyproto", NewPxyProtoServer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PxyProtoServer struct.
|
||||||
|
type PxyProtoServer struct {
|
||||||
|
addr string
|
||||||
|
proxy proxy.Proxy
|
||||||
|
server proxy.Server
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPxyProtoServer returns a PxyProtoServer struct.
|
||||||
|
func NewPxyProtoServer(s string, p proxy.Proxy) (proxy.Server, error) {
|
||||||
|
schemes := strings.SplitN(s, ",", 2)
|
||||||
|
u, err := url.Parse(schemes[0])
|
||||||
|
if err != nil {
|
||||||
|
log.F("[pxyproto] parse url err: %s", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t := &PxyProtoServer{proxy: p, addr: u.Host}
|
||||||
|
if len(schemes) < 2 {
|
||||||
|
return nil, errors.New("[pxyproto] you must use pxyproto with a proxy server, e.g: pxyproto://:1234,http://")
|
||||||
|
}
|
||||||
|
|
||||||
|
t.server, err = proxy.ServerFromURL(schemes[1], p)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListenAndServe listens on server's addr and serves connections.
|
||||||
|
func (s *PxyProtoServer) ListenAndServe() {
|
||||||
|
l, err := net.Listen("tcp", s.addr)
|
||||||
|
if err != nil {
|
||||||
|
log.F("[pxyproto] failed to listen on %s: %v", s.addr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer l.Close()
|
||||||
|
|
||||||
|
log.F("[pxyproto] listening TCP on %s", s.addr)
|
||||||
|
|
||||||
|
for {
|
||||||
|
c, err := l.Accept()
|
||||||
|
if err != nil {
|
||||||
|
log.F("[pxyproto] failed to accept: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
go s.Serve(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Serve serves a connection.
|
||||||
|
func (s *PxyProtoServer) Serve(cc net.Conn) {
|
||||||
|
c, err := newServerConn(cc)
|
||||||
|
if err != nil {
|
||||||
|
log.F("[pxyproto] parse header failed, error: %v", err)
|
||||||
|
cc.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// log.F("[pxyproto] %s <-> %s <-> %s <-> %s",
|
||||||
|
// c.RemoteAddr(), c.LocalAddr(), cc.RemoteAddr(), cc.LocalAddr())
|
||||||
|
|
||||||
|
if s.server != nil {
|
||||||
|
s.server.Serve(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type serverConn struct {
|
||||||
|
*proxy.Conn
|
||||||
|
src, dst net.Addr
|
||||||
|
}
|
||||||
|
|
||||||
|
func newServerConn(c net.Conn) (*serverConn, error) {
|
||||||
|
sc := &serverConn{
|
||||||
|
Conn: proxy.NewConn(c),
|
||||||
|
src: c.RemoteAddr(),
|
||||||
|
dst: c.LocalAddr(),
|
||||||
|
}
|
||||||
|
return sc, sc.parseHeader()
|
||||||
|
}
|
||||||
|
|
||||||
|
// "PROXY TCPx SRC_IP DST_IP SRC_PORT DST_PORT"
|
||||||
|
func (c *serverConn) parseHeader() error {
|
||||||
|
line, err := c.Conn.Reader().ReadString('\n')
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
line = strings.ReplaceAll(line, "\r\n", "")
|
||||||
|
// log.F("[pxyproto] req header: %s", line)
|
||||||
|
|
||||||
|
header := strings.Split(line, " ")
|
||||||
|
if len(header) != 6 {
|
||||||
|
return fmt.Errorf("invalid header: %s", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
if header[0] != "PROXY" {
|
||||||
|
return fmt.Errorf("invalid header: %s", line)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.src, err = net.ResolveTCPAddr("tcp", net.JoinHostPort(header[2], header[4]))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parse header: %s, error: %v", line, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.dst, err = net.ResolveTCPAddr("tcp", net.JoinHostPort(header[3], header[5]))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("parse header: %s, error: %v", line, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *serverConn) LocalAddr() net.Addr { return c.dst }
|
||||||
|
func (c *serverConn) RemoteAddr() net.Addr { return c.src }
|
@ -66,7 +66,7 @@ func (pc *PktConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
|||||||
return n, raddr, errors.New("not enough size to get addr")
|
return n, raddr, errors.New("not enough size to get addr")
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://tools.ietf.org/html/rfc1928#section-7
|
// https://www.rfc-editor.org/rfc/rfc1928#section-7
|
||||||
// +----+------+------+----------+----------+----------+
|
// +----+------+------+----------+----------+----------+
|
||||||
// |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
|
// |RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
|
||||||
// +----+------+------+----------+----------+----------+
|
// +----+------+------+----------+----------+----------+
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// https://tools.ietf.org/html/rfc1928
|
// https://www.rfc-editor.org/rfc/rfc1928
|
||||||
|
|
||||||
// socks5 client:
|
// socks5 client:
|
||||||
// https://github.com/golang/net/tree/master/proxy
|
// https://github.com/golang/net/tree/master/proxy
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// https://tools.ietf.org/html/rfc6455#section-5.2
|
// https://www.rfc-editor.org/rfc/rfc6455#section-5.2
|
||||||
//
|
//
|
||||||
// Frame Format
|
// Frame Format
|
||||||
// 0 1 2 3
|
// 0 1 2 3
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package rule
|
package rule
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/nadoo/glider/pool"
|
"github.com/nadoo/glider/pool"
|
||||||
@ -71,12 +71,12 @@ func (c *httpChecker) Check(dialer proxy.Dialer) (time.Duration, error) {
|
|||||||
r := pool.GetBufReader(rc)
|
r := pool.GetBufReader(rc)
|
||||||
defer pool.PutBufReader(r)
|
defer pool.PutBufReader(r)
|
||||||
|
|
||||||
line, _, err := r.ReadLine()
|
line, err := r.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Contains(line, []byte(c.expect)) {
|
if !strings.Contains(line, c.expect) {
|
||||||
return 0, fmt.Errorf("expect: %s, got: %s", c.expect, line)
|
return 0, fmt.Errorf("expect: %s, got: %s", c.expect, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user