mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-04 07:17:55 +07:00
fix: simple-obfs host problem
This commit is contained in:
@ -8,6 +8,7 @@ import (
|
||||
"github.com/v2rayA/dae/common"
|
||||
"github.com/v2rayA/dae/component/outbound/dialer"
|
||||
"github.com/v2rayA/dae/component/outbound/transport/simpleobfs"
|
||||
"golang.org/x/net/proxy"
|
||||
"net"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@ -49,22 +50,35 @@ func (s *Shadowsocks) Dialer(option *dialer.GlobalOption, iOption dialer.Instanc
|
||||
return nil, fmt.Errorf("unsupported shadowsocks encryption method: %v", s.Cipher)
|
||||
}
|
||||
var err error
|
||||
d := dialer.FullconeDirect // Shadowsocks Proxy supports full-cone.
|
||||
var d proxy.Dialer
|
||||
switch s.Plugin.Name {
|
||||
case "simple-obfs":
|
||||
d = dialer.SymmetricDirect // Simple-obfs does not supports UDP.
|
||||
switch s.Plugin.Opts.Obfs {
|
||||
case "http", "tls":
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported obfs %v of plugin %v", s.Plugin.Opts.Obfs, s.Plugin.Name)
|
||||
}
|
||||
host := s.Plugin.Opts.Host
|
||||
if host == "" {
|
||||
host = "cloudflare.com"
|
||||
}
|
||||
path := s.Plugin.Opts.Path
|
||||
uSimpleObfs := url.URL{
|
||||
Scheme: "simple-obfs",
|
||||
Host: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
RawQuery: url.Values{
|
||||
"obfs": []string{s.Plugin.Opts.Obfs},
|
||||
"host": []string{s.Plugin.Opts.Host},
|
||||
"uri": []string{s.Plugin.Opts.Path},
|
||||
"host": []string{host},
|
||||
"uri": []string{path},
|
||||
}.Encode(),
|
||||
}
|
||||
d, err = simpleobfs.NewSimpleObfs(uSimpleObfs.String(), d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
d = dialer.FullconeDirect // Shadowsocks Proxy supports full-cone.
|
||||
}
|
||||
d, err = protocol.NewDialer("shadowsocks", d, protocol.Header{
|
||||
ProxyAddress: net.JoinHostPort(s.Server, strconv.Itoa(s.Port)),
|
||||
|
@ -152,6 +152,10 @@ func (g *DialerGroup) SetSelectionPolicy(policy DialerSelectionPolicy) {
|
||||
g.selectionPolicy = &policy
|
||||
}
|
||||
|
||||
func (g *DialerGroup) GetSelectionPolicy() (policy consts.DialerSelectionPolicy) {
|
||||
return g.selectionPolicy.Policy
|
||||
}
|
||||
|
||||
func (d *DialerGroup) MustGetAliveDialerSet(typ *dialer.NetworkType) *dialer.AliveDialerSet {
|
||||
if typ.IsDns {
|
||||
switch typ.L4Proto {
|
||||
|
@ -6,12 +6,13 @@ import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/mzz2017/softwind/pkg/fastrand"
|
||||
"github.com/mzz2017/softwind/pool"
|
||||
"io"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// HTTPObfs is shadowsocks http simple-obfs implementation
|
||||
@ -24,9 +25,13 @@ type HTTPObfs struct {
|
||||
offset int
|
||||
firstRequest bool
|
||||
firstResponse bool
|
||||
wMu sync.Mutex
|
||||
rMu sync.Mutex
|
||||
}
|
||||
|
||||
func (ho *HTTPObfs) Read(b []byte) (int, error) {
|
||||
ho.rMu.Lock()
|
||||
defer ho.rMu.Unlock()
|
||||
if ho.buf != nil {
|
||||
n := copy(b, ho.buf[ho.offset:])
|
||||
ho.offset += n
|
||||
@ -64,17 +69,18 @@ func (ho *HTTPObfs) Read(b []byte) (int, error) {
|
||||
}
|
||||
|
||||
func (ho *HTTPObfs) Write(b []byte) (int, error) {
|
||||
ho.wMu.Lock()
|
||||
defer ho.wMu.Unlock()
|
||||
if ho.firstRequest {
|
||||
randBytes := make([]byte, 16)
|
||||
rand.Read(randBytes)
|
||||
req, _ := http.NewRequest("GET", fmt.Sprintf("http://%s%s", ho.host, ho.path), bytes.NewBuffer(b[:]))
|
||||
req.Header.Set("User-Agent", fmt.Sprintf("curl/7.%d.%d", rand.Int()%54, rand.Int()%2))
|
||||
req.Header.Set("User-Agent", fmt.Sprintf("curl/7.%d.%d", fastrand.Rand().Int()%87, fastrand.Rand().Int()%2))
|
||||
req.Header.Set("Upgrade", "websocket")
|
||||
req.Header.Set("Connection", "Upgrade")
|
||||
req.Host = ho.host
|
||||
if ho.port != "80" {
|
||||
req.Host = fmt.Sprintf("%s:%s", ho.host, ho.port)
|
||||
}
|
||||
randBytes := make([]byte, 16)
|
||||
fastrand.Read(randBytes)
|
||||
req.Header.Set("Sec-WebSocket-Key", base64.URLEncoding.EncodeToString(randBytes))
|
||||
req.ContentLength = int64(len(b))
|
||||
err := req.Write(ho.Conn)
|
||||
|
@ -66,18 +66,19 @@ func (s *SimpleObfs) Dial(network, addr string) (c net.Conn, err error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("[simpleobfs]: dial to %s: %w", s.addr, err)
|
||||
}
|
||||
|
||||
host, port, err := net.SplitHostPort(s.addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.host != "" {
|
||||
host = s.host
|
||||
}
|
||||
switch s.obfstype {
|
||||
case HTTP:
|
||||
rs := strings.Split(s.addr, ":")
|
||||
var port string
|
||||
if len(rs) == 1 {
|
||||
port = "80"
|
||||
} else {
|
||||
port = rs[1]
|
||||
}
|
||||
c = NewHTTPObfs(rc, rs[0], port, s.path)
|
||||
c = NewHTTPObfs(rc, host, port, s.path)
|
||||
case TLS:
|
||||
c = NewTLSObfs(rc, s.host)
|
||||
c = NewTLSObfs(rc, host)
|
||||
}
|
||||
return c, err
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/mzz2017/softwind/pkg/fastrand"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -22,6 +23,8 @@ type TLSObfs struct {
|
||||
remain int
|
||||
firstRequest bool
|
||||
firstResponse bool
|
||||
rMu sync.Mutex
|
||||
wMu sync.Mutex
|
||||
}
|
||||
|
||||
func (to *TLSObfs) read(b []byte, discardN int) (int, error) {
|
||||
@ -50,6 +53,8 @@ func (to *TLSObfs) read(b []byte, discardN int) (int, error) {
|
||||
}
|
||||
|
||||
func (to *TLSObfs) Read(b []byte) (int, error) {
|
||||
to.rMu.Lock()
|
||||
defer to.rMu.Unlock()
|
||||
if to.remain > 0 {
|
||||
length := to.remain
|
||||
if length > len(b) {
|
||||
@ -73,6 +78,8 @@ func (to *TLSObfs) Read(b []byte) (int, error) {
|
||||
return to.read(b, 3)
|
||||
}
|
||||
func (to *TLSObfs) Write(b []byte) (int, error) {
|
||||
to.wMu.Lock()
|
||||
defer to.wMu.Unlock()
|
||||
length := len(b)
|
||||
for i := 0; i < length; i += chunkSize {
|
||||
end := i + chunkSize
|
||||
|
@ -276,7 +276,7 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
|
||||
if dialerForNew == nil {
|
||||
dialerForNew, _, err = outbound.Select(networkType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to select dialer from group %v (%v): %w", outbound.Name, networkType.String(), err)
|
||||
return fmt.Errorf("failed to select dialer from group %v (%v, dns?:%v,from: %v): %w", outbound.Name, networkType.String()[:4], isDns, realSrc.String(), err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -309,7 +309,7 @@ func (c *ControlPlane) handlePkt(lConn *net.UDPConn, data []byte, src, pktDst, r
|
||||
Target: destToSend,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to GetOrCreate: %w", err)
|
||||
return fmt.Errorf("failed to GetOrCreate (%v): %w", outbound.GetSelectionPolicy(), err)
|
||||
}
|
||||
// If the udp endpoint has been not alive, remove it from pool and get a new one.
|
||||
if !isNew && !ue.Dialer.MustGetAlive(networkType) {
|
||||
|
Reference in New Issue
Block a user