mirror of
https://github.com/nadoo/glider.git
synced 2026-07-17 17:30:11 +08:00
This commit is contained in:
parent
38b34030bc
commit
579b427e9d
2
go.mod
2
go.mod
@ -13,7 +13,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
github.com/klauspost/cpuid/v2 v2.4.0 // indirect
|
||||||
github.com/klauspost/reedsolomon v1.14.1 // indirect
|
github.com/klauspost/reedsolomon v1.14.1 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.27 // indirect
|
github.com/pierrec/lz4/v4 v4.1.27 // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
|
|||||||
4
go.sum
4
go.sum
@ -29,8 +29,8 @@ github.com/insomniacslk/dhcp v0.0.0-20260603135910-a415979eb11e h1:7j1+lOuGBg7PQ
|
|||||||
github.com/insomniacslk/dhcp v0.0.0-20260603135910-a415979eb11e/go.mod h1:qfvBmyDNp+/liLEYWRvqny/PEz9hGe2Dz833eXILSmo=
|
github.com/insomniacslk/dhcp v0.0.0-20260603135910-a415979eb11e/go.mod h1:qfvBmyDNp+/liLEYWRvqny/PEz9hGe2Dz833eXILSmo=
|
||||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw=
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
|
||||||
github.com/klauspost/reedsolomon v1.14.1 h1:swE9kzyWXD/wVG+l5Pe8bWnQ0giIY7D1GjCBKk3kG2U=
|
github.com/klauspost/reedsolomon v1.14.1 h1:swE9kzyWXD/wVG+l5Pe8bWnQ0giIY7D1GjCBKk3kG2U=
|
||||||
github.com/klauspost/reedsolomon v1.14.1/go.mod h1:yjqqjgMTQkBUHSG97/rm4zipffCNbCiZcB3kTqr++sQ=
|
github.com/klauspost/reedsolomon v1.14.1/go.mod h1:yjqqjgMTQkBUHSG97/rm4zipffCNbCiZcB3kTqr++sQ=
|
||||||
github.com/mdlayher/packet v1.1.2 h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY=
|
github.com/mdlayher/packet v1.1.2 h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY=
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package proxy
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ func DialerFromURL(s string, dialer Dialer) (Dialer, error) {
|
|||||||
s = s + "://"
|
s = s + "://"
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme := s[:strings.Index(s, ":")]
|
scheme, _, _ := strings.Cut(s, ":")
|
||||||
c, ok := dialerCreators[strings.ToLower(scheme)]
|
c, ok := dialerCreators[strings.ToLower(scheme)]
|
||||||
if ok {
|
if ok {
|
||||||
return c(s, dialer)
|
return c(s, dialer)
|
||||||
@ -74,6 +74,6 @@ func DialerSchemes() string {
|
|||||||
for name := range dialerCreators {
|
for name := range dialerCreators {
|
||||||
s = append(s, name)
|
s = append(s, name)
|
||||||
}
|
}
|
||||||
sort.Strings(s)
|
slices.Sort(s)
|
||||||
return strings.Join(s, " ")
|
return strings.Join(s, " ")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -60,13 +60,15 @@ func NewHTTP(s string, d proxy.Dialer, p proxy.Proxy) (*HTTP, error) {
|
|||||||
|
|
||||||
// parseStartLine parses "GET /foo HTTP/1.1" OR "HTTP/1.1 200 OK" into its three parts.
|
// parseStartLine parses "GET /foo HTTP/1.1" OR "HTTP/1.1 200 OK" into its three parts.
|
||||||
func parseStartLine(line string) (r1, r2, r3 string, ok bool) {
|
func parseStartLine(line string) (r1, r2, r3 string, ok bool) {
|
||||||
s1 := strings.Index(line, " ")
|
r1, rest, ok := strings.Cut(line, " ")
|
||||||
s2 := strings.Index(line[s1+1:], " ")
|
if !ok {
|
||||||
if s1 < 0 || s2 < 0 {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s2 += s1 + 1
|
r2, r3, ok = strings.Cut(rest, " ")
|
||||||
return line[:s1], line[s1+1 : s2], line[s2+1:], true
|
if !ok {
|
||||||
|
return "", "", "", false
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanHeaders(header textproto.MIMEHeader) {
|
func cleanHeaders(header textproto.MIMEHeader) {
|
||||||
@ -95,22 +97,23 @@ func writeHeaders(w io.Writer, header textproto.MIMEHeader) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func extractUserPass(auth string) (username, password string, ok bool) {
|
func extractUserPass(auth string) (username, password string, ok bool) {
|
||||||
if !strings.HasPrefix(auth, "Basic ") {
|
token, ok := strings.CutPrefix(auth, "Basic ")
|
||||||
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := base64.StdEncoding.DecodeString(strings.TrimPrefix(auth, "Basic "))
|
b, err := base64.StdEncoding.DecodeString(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s := string(b)
|
s := string(b)
|
||||||
idx := strings.IndexByte(s, ':')
|
username, password, ok = strings.Cut(s, ":")
|
||||||
if idx < 0 {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return s[:idx], s[idx+1:], true
|
return username, password, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
@ -3,7 +3,7 @@ package proxy
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ func ServerFromURL(s string, proxy Proxy) (Server, error) {
|
|||||||
s = "mixed://" + s
|
s = "mixed://" + s
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme := s[:strings.Index(s, ":")]
|
scheme, _, _ := strings.Cut(s, ":")
|
||||||
c, ok := serverCreators[strings.ToLower(scheme)]
|
c, ok := serverCreators[strings.ToLower(scheme)]
|
||||||
if ok {
|
if ok {
|
||||||
return c(s, proxy)
|
return c(s, proxy)
|
||||||
@ -59,6 +59,6 @@ func ServerSchemes() string {
|
|||||||
for name := range serverCreators {
|
for name := range serverCreators {
|
||||||
s = append(s, name)
|
s = append(s, name)
|
||||||
}
|
}
|
||||||
sort.Strings(s)
|
slices.Sort(s)
|
||||||
return strings.Join(s, " ")
|
return strings.Join(s, " ")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,8 +33,7 @@ func sealVMessAEADHeader(key [16]byte, data []byte) []byte {
|
|||||||
connectionNonce := make([]byte, 8)
|
connectionNonce := make([]byte, 8)
|
||||||
rand.Read(connectionNonce)
|
rand.Read(connectionNonce)
|
||||||
|
|
||||||
aeadPayloadLengthSerializedByte := make([]byte, 2)
|
aeadPayloadLengthSerializedByte := binary.BigEndian.AppendUint16(nil, uint16(len(data)))
|
||||||
binary.BigEndian.PutUint16(aeadPayloadLengthSerializedByte, uint16(len(data)))
|
|
||||||
|
|
||||||
var payloadHeaderLengthAEADEncrypted []byte
|
var payloadHeaderLengthAEADEncrypted []byte
|
||||||
|
|
||||||
|
|||||||
@ -93,13 +93,15 @@ func NewWS(s string, d proxy.Dialer, p proxy.Proxy, withTLS bool) (*WS, error) {
|
|||||||
// parseFirstLine parses "GET /foo HTTP/1.1" OR "HTTP/1.1 200 OK" into its three parts.
|
// parseFirstLine parses "GET /foo HTTP/1.1" OR "HTTP/1.1 200 OK" into its three parts.
|
||||||
// TODO: move to separate http lib package for reuse(also for http proxy module)
|
// TODO: move to separate http lib package for reuse(also for http proxy module)
|
||||||
func parseFirstLine(line string) (r1, r2, r3 string, ok bool) {
|
func parseFirstLine(line string) (r1, r2, r3 string, ok bool) {
|
||||||
s1 := strings.Index(line, " ")
|
r1, rest, ok := strings.Cut(line, " ")
|
||||||
s2 := strings.Index(line[s1+1:], " ")
|
if !ok {
|
||||||
if s1 < 0 || s2 < 0 {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s2 += s1 + 1
|
r2, r3, ok = strings.Cut(rest, " ")
|
||||||
return line[:s1], line[s1+1 : s2], line[s2+1:], true
|
if !ok {
|
||||||
|
return "", "", "", false
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func generateClientKey() string {
|
func generateClientKey() string {
|
||||||
|
|||||||
@ -33,9 +33,9 @@ type Forwarder struct {
|
|||||||
func ForwarderFromURL(s, intface string, dialTimeout, relayTimeout time.Duration) (f *Forwarder, err error) {
|
func ForwarderFromURL(s, intface string, dialTimeout, relayTimeout time.Duration) (f *Forwarder, err error) {
|
||||||
f = &Forwarder{url: s}
|
f = &Forwarder{url: s}
|
||||||
|
|
||||||
ss := strings.Split(s, "#")
|
chain, option, found := strings.Cut(s, "#")
|
||||||
if len(ss) > 1 {
|
if found {
|
||||||
err = f.parseOption(ss[1])
|
err = f.parseOption(option)
|
||||||
}
|
}
|
||||||
|
|
||||||
iface := intface
|
iface := intface
|
||||||
@ -50,7 +50,7 @@ func ForwarderFromURL(s, intface string, dialTimeout, relayTimeout time.Duration
|
|||||||
}
|
}
|
||||||
|
|
||||||
var addrs []string
|
var addrs []string
|
||||||
for _, url := range strings.Split(ss[0], ",") {
|
for url := range strings.SplitSeq(chain, ",") {
|
||||||
d, err = proxy.DialerFromURL(url, d)
|
d, err = proxy.DialerFromURL(url, d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"sort"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@ -16,18 +16,11 @@ import (
|
|||||||
"github.com/nadoo/glider/proxy"
|
"github.com/nadoo/glider/proxy"
|
||||||
)
|
)
|
||||||
|
|
||||||
// forwarder slice orderd by priority.
|
|
||||||
type priSlice []*Forwarder
|
|
||||||
|
|
||||||
func (p priSlice) Len() int { return len(p) }
|
|
||||||
func (p priSlice) Less(i, j int) bool { return p[i].Priority() > p[j].Priority() }
|
|
||||||
func (p priSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
|
||||||
|
|
||||||
// FwdrGroup is a forwarder group.
|
// FwdrGroup is a forwarder group.
|
||||||
type FwdrGroup struct {
|
type FwdrGroup struct {
|
||||||
name string
|
name string
|
||||||
config *Strategy
|
config *Strategy
|
||||||
fwdrs priSlice
|
fwdrs []*Forwarder
|
||||||
avail []*Forwarder // available forwarders
|
avail []*Forwarder // available forwarders
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
index uint32
|
index uint32
|
||||||
@ -66,7 +59,16 @@ func NewFwdrGroup(rulePath string, s []string, c *Strategy) *FwdrGroup {
|
|||||||
// newFwdrGroup returns a new FwdrGroup.
|
// newFwdrGroup returns a new FwdrGroup.
|
||||||
func newFwdrGroup(name string, fwdrs []*Forwarder, c *Strategy) *FwdrGroup {
|
func newFwdrGroup(name string, fwdrs []*Forwarder, c *Strategy) *FwdrGroup {
|
||||||
p := &FwdrGroup{name: name, fwdrs: fwdrs, config: c}
|
p := &FwdrGroup{name: name, fwdrs: fwdrs, config: c}
|
||||||
sort.Sort(p.fwdrs)
|
slices.SortFunc(p.fwdrs, func(a, b *Forwarder) int {
|
||||||
|
switch {
|
||||||
|
case a.Priority() > b.Priority():
|
||||||
|
return -1
|
||||||
|
case a.Priority() < b.Priority():
|
||||||
|
return 1
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
p.init()
|
p.init()
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,7 @@ func NewProxy(mainForwarders []string, mainStrategy *Strategy, rules []*Config)
|
|||||||
// if there's any forwarder defined in main config, make sure they will be accessed directly.
|
// if there's any forwarder defined in main config, make sure they will be accessed directly.
|
||||||
if len(mainForwarders) > 0 {
|
if len(mainForwarders) > 0 {
|
||||||
for _, f := range rd.main.fwdrs {
|
for _, f := range rd.main.fwdrs {
|
||||||
addr := strings.Split(f.addr, ",")[0]
|
addr, _, _ := strings.Cut(f.addr, ",")
|
||||||
host, _, _ := net.SplitHostPort(addr)
|
host, _, _ := net.SplitHostPort(addr)
|
||||||
if _, err := netip.ParseAddr(host); err != nil {
|
if _, err := netip.ParseAddr(host); err != nil {
|
||||||
rd.domainMap.Store(strings.ToLower(host), direct)
|
rd.domainMap.Store(strings.ToLower(host), direct)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user