Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e972dd660d | |||
| 7067276170 | |||
| 0f1763877c |
@@ -126,6 +126,12 @@ func (t *HTTP3Transport) newTransport() *http3.Transport {
|
||||
conn.Close()
|
||||
return nil, dialErr
|
||||
}
|
||||
// quic-go does not take ownership of the packet conn passed to
|
||||
// DialEarly: when the connection ends it only stops reading.
|
||||
go func() {
|
||||
<-quicConn.Context().Done()
|
||||
conn.Close()
|
||||
}()
|
||||
return quicConn, nil
|
||||
},
|
||||
TLSClientConfig: t.tlsConfig,
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/quic-go"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@@ -117,6 +118,12 @@ func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg,
|
||||
rawConn.Close()
|
||||
return nil, E.Cause(err, "establish QUIC connection")
|
||||
}
|
||||
// quic-go does not take ownership of the packet conn passed to
|
||||
// DialEarly: when the connection ends it only stops reading.
|
||||
go func() {
|
||||
<-earlyConnection.Context().Done()
|
||||
rawConn.Close()
|
||||
}()
|
||||
return earlyConnection, nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -144,6 +151,11 @@ func (t *Transport) exchange(ctx context.Context, message *mDNS.Msg, conn *quic.
|
||||
return nil, E.Cause(err, "open stream")
|
||||
}
|
||||
defer stream.CancelRead(0)
|
||||
stopWatch := context.AfterFunc(ctx, func() {
|
||||
stream.CancelRead(0)
|
||||
_ = stream.SetWriteDeadline(time.Now())
|
||||
})
|
||||
defer stopWatch()
|
||||
err = transport.WriteMessage(stream, 0, message)
|
||||
if err != nil {
|
||||
stream.Close()
|
||||
|
||||
@@ -17,6 +17,7 @@ icon: material/new-box
|
||||
"idle_session_check_interval": "30s",
|
||||
"idle_session_timeout": "30s",
|
||||
"min_idle_session": 5,
|
||||
"disable_reuse": false,
|
||||
"tls": {},
|
||||
|
||||
... // Dial Fields
|
||||
@@ -55,6 +56,10 @@ In the check, close sessions that have been idle for longer than this. Default:
|
||||
|
||||
In the check, at least the first `n` idle sessions are kept open. Default value: `n`=0
|
||||
|
||||
#### disable_reuse
|
||||
|
||||
Disable TLS connection reuse. Default: false.
|
||||
|
||||
#### tls
|
||||
|
||||
==Required==
|
||||
|
||||
@@ -17,6 +17,7 @@ icon: material/new-box
|
||||
"idle_session_check_interval": "30s",
|
||||
"idle_session_timeout": "30s",
|
||||
"min_idle_session": 5,
|
||||
"disable_reuse": false,
|
||||
"tls": {},
|
||||
|
||||
... // 拨号字段
|
||||
@@ -55,6 +56,10 @@ AnyTLS 密码。
|
||||
|
||||
在检查中,至少前 `n` 个空闲会话保持打开状态。默认值:`n`=0
|
||||
|
||||
#### disable_reuse
|
||||
|
||||
禁用 TLS 连接复用。默认值:false。
|
||||
|
||||
#### tls
|
||||
|
||||
==必填==
|
||||
|
||||
@@ -4,7 +4,7 @@ go 1.24.7
|
||||
|
||||
require (
|
||||
github.com/anthropics/anthropic-sdk-go v1.26.0
|
||||
github.com/anytls/sing-anytls v0.0.11
|
||||
github.com/anytls/sing-anytls v0.0.13
|
||||
github.com/caddyserver/certmagic v0.25.2
|
||||
github.com/coder/websocket v1.8.14
|
||||
github.com/cretz/bine v0.2.0
|
||||
@@ -35,7 +35,7 @@ require (
|
||||
github.com/sagernet/quic-go v0.59.0-sing-box-mod.4
|
||||
github.com/sagernet/sing v0.8.11
|
||||
github.com/sagernet/sing-mux v0.3.5
|
||||
github.com/sagernet/sing-quic v0.6.1
|
||||
github.com/sagernet/sing-quic v0.6.3
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
|
||||
|
||||
@@ -12,8 +12,8 @@ github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1
|
||||
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||
github.com/anthropics/anthropic-sdk-go v1.26.0 h1:oUTzFaUpAevfuELAP1sjL6CQJ9HHAfT7CoSYSac11PY=
|
||||
github.com/anthropics/anthropic-sdk-go v1.26.0/go.mod h1:qUKmaW+uuPB64iy1l+4kOSvaLqPXnHTTBKH6RVZ7q5Q=
|
||||
github.com/anytls/sing-anytls v0.0.11 h1:w8e9Uj1oP3m4zxkyZDewPk0EcQbvVxb7Nn+rapEx4fc=
|
||||
github.com/anytls/sing-anytls v0.0.11/go.mod h1:7rjN6IukwysmdusYsrV51Fgu1uW6vsrdd6ctjnEAln8=
|
||||
github.com/anytls/sing-anytls v0.0.13 h1:FL+krjOmwpYYLpl5rrV/BrzDMfxbi05YgIQh+NAA37c=
|
||||
github.com/anytls/sing-anytls v0.0.13/go.mod h1:7rjN6IukwysmdusYsrV51Fgu1uW6vsrdd6ctjnEAln8=
|
||||
github.com/caddyserver/certmagic v0.25.2 h1:D7xcS7ggX/WEY54x0czj7ioTkmDWKIgxtIi2OcQclUc=
|
||||
github.com/caddyserver/certmagic v0.25.2/go.mod h1:llW/CvsNmza8S6hmsuggsZeiX+uS27dkqY27wDIuBWg=
|
||||
github.com/caddyserver/zerossl v0.1.5 h1:dkvOjBAEEtY6LIGAHei7sw2UgqSD6TrWweXpV7lvEvE=
|
||||
@@ -240,8 +240,8 @@ github.com/sagernet/sing v0.8.11 h1:AKZRvjFPHtAXwGCjOJrzAQPiZxr8mobhuSUqkHf+VQw=
|
||||
github.com/sagernet/sing v0.8.11/go.mod h1:olXxWQNqRW/l2Q6JI3b2Qmz8iQnIFlOeeH8bx6JhgUA=
|
||||
github.com/sagernet/sing-mux v0.3.5 h1:RHnhVEc+SFqkrK4xMygYjDwwLhzp2Bj3lztSukONfhI=
|
||||
github.com/sagernet/sing-mux v0.3.5/go.mod h1:QvlKMyNBNrQoyX4x+gq028uPbLM2XeRpWtDsWBJbFSk=
|
||||
github.com/sagernet/sing-quic v0.6.1 h1:lx0tcm99wIA1RkyvILNzRSsMy1k7TTQYIhx71E/WBlw=
|
||||
github.com/sagernet/sing-quic v0.6.1/go.mod h1:K5bWvITOm4vE10fwLfrWpw27bCoVJ+tfQ79tOWg+Ko8=
|
||||
github.com/sagernet/sing-quic v0.6.3 h1:0wSPqCNJsC7CadB5GZS1aPkyU27aRwHPd5SlsijbBNw=
|
||||
github.com/sagernet/sing-quic v0.6.3/go.mod h1:K5bWvITOm4vE10fwLfrWpw27bCoVJ+tfQ79tOWg+Ko8=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8 h1:PURj5PRoAkqeHh2ZW205RWzN9E9RtKCVCzByXruQWfE=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnqqs2gQ2/Qioo=
|
||||
|
||||
@@ -22,4 +22,5 @@ type AnyTLSOutboundOptions struct {
|
||||
IdleSessionCheckInterval badoption.Duration `json:"idle_session_check_interval,omitempty"`
|
||||
IdleSessionTimeout badoption.Duration `json:"idle_session_timeout,omitempty"`
|
||||
MinIdleSession int `json:"min_idle_session,omitempty"`
|
||||
DisableReuse bool `json:"disable_reuse,omitempty"`
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/adapter/outbound"
|
||||
@@ -19,10 +20,15 @@ import (
|
||||
"github.com/sagernet/sing/common/uot"
|
||||
|
||||
anytls "github.com/anytls/sing-anytls"
|
||||
"github.com/anytls/sing-anytls/util"
|
||||
)
|
||||
|
||||
func RegisterOutbound(registry *outbound.Registry) {
|
||||
outbound.Register[option.AnyTLSOutboundOptions](registry, C.TypeAnyTLS, NewOutbound)
|
||||
|
||||
if !strings.Contains(util.Version, "sing-box") {
|
||||
util.Version = util.Version + " sing-box/" + C.Version
|
||||
}
|
||||
}
|
||||
|
||||
type Outbound struct {
|
||||
@@ -74,6 +80,7 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
||||
IdleSessionCheckInterval: options.IdleSessionCheckInterval.Build(),
|
||||
IdleSessionTimeout: options.IdleSessionTimeout.Build(),
|
||||
MinIdleSession: options.MinIdleSession,
|
||||
DisableReuse: options.DisableReuse,
|
||||
DialOut: outbound.dialOut,
|
||||
Logger: logger,
|
||||
})
|
||||
|
||||
@@ -87,22 +87,27 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
||||
request.Header.Set("Upgrade", "websocket")
|
||||
err = request.Write(conn)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
bufReader := std_bufio.NewReader(conn)
|
||||
response, err := http.ReadResponse(bufReader, request)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
if response.StatusCode != 101 ||
|
||||
!strings.EqualFold(response.Header.Get("Connection"), "upgrade") ||
|
||||
!strings.EqualFold(response.Header.Get("Upgrade"), "websocket") {
|
||||
conn.Close()
|
||||
response.Body.Close()
|
||||
return nil, E.New("v2ray-http-upgrade: unexpected status: ", response.Status)
|
||||
}
|
||||
if bufReader.Buffered() > 0 {
|
||||
buffer := buf.NewSize(bufReader.Buffered())
|
||||
_, err = buffer.ReadFullFrom(bufReader, buffer.Len())
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
conn = bufio.NewCachedConn(conn, buffer)
|
||||
|
||||
@@ -78,6 +78,12 @@ func (c *Client) offerNew() (*quic.Conn, error) {
|
||||
packetConn.Close()
|
||||
return nil, err
|
||||
}
|
||||
// quic-go does not take ownership of the packet conn passed to Dial:
|
||||
// when the connection ends it only stops reading.
|
||||
go func() {
|
||||
<-quicConn.Context().Done()
|
||||
packetConn.Close()
|
||||
}()
|
||||
c.conn.Store(quicConn)
|
||||
c.rawConn = udpConn
|
||||
return quicConn, nil
|
||||
|
||||
@@ -2,6 +2,7 @@ package v2rayquic
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/quic-go"
|
||||
qtls "github.com/sagernet/sing-quic"
|
||||
@@ -37,5 +38,8 @@ func (s *StreamWrapper) Upstream() any {
|
||||
func (s *StreamWrapper) Close() error {
|
||||
s.CancelRead(0)
|
||||
s.Stream.Close()
|
||||
// quic-go's Stream.Close does not unblock a Write blocked on flow control,
|
||||
// but a past write deadline does; buffered data and the FIN are unaffected.
|
||||
s.Stream.SetWriteDeadline(time.Now())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -93,12 +93,14 @@ func (c *Client) dialContext(ctx context.Context, requestURL *url.URL, headers h
|
||||
reader, _, err := ws.Dialer{Header: ws.HandshakeHeaderHTTP(headers), Protocols: protocols}.Upgrade(deadlineConn, requestURL)
|
||||
deadlineConn.SetDeadline(time.Time{})
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
if reader != nil {
|
||||
buffer := buf.NewSize(reader.Buffered())
|
||||
_, err = buffer.ReadFullFrom(reader, buffer.Len())
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
conn = bufio.NewCachedConn(conn, buffer)
|
||||
|
||||
@@ -187,6 +187,7 @@ func (c *EarlyWebsocketConn) writeRequest(content []byte) error {
|
||||
if len(lateData) > 0 {
|
||||
_, err = conn.Write(lateData)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user