fix: simple-obfs host problem

This commit is contained in:
mzz2017
2023-02-13 14:59:18 +08:00
parent 0324d4a5d9
commit d88961681e
6 changed files with 51 additions and 19 deletions

View File

@ -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)),

View File

@ -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 {

View File

@ -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)

View File

@ -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
}

View File

@ -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

View File

@ -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) {