mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-10-20 08:14:24 +00:00
Fix protocol input validation
This commit is contained in:
+13
-5
@@ -264,16 +264,24 @@ func (j *ClientHello) parseExtensions(exs []byte) error {
|
||||
return &ParseError{LengthErr, 19}
|
||||
}
|
||||
versionsLen := int(sex[0])
|
||||
for i := 0; i < versionsLen; i += 2 {
|
||||
versions = append(versions, binary.BigEndian.Uint16(sex[1:][i:]))
|
||||
sex = sex[versionExtensionHeaderLen:]
|
||||
if len(sex) < versionsLen {
|
||||
return &ParseError{LengthErr, 21}
|
||||
}
|
||||
for i := range versionsLen / 2 {
|
||||
versions = append(versions, binary.BigEndian.Uint16(sex[i*2:]))
|
||||
}
|
||||
case signatureAlgorithmsExtensionType:
|
||||
if len(sex) < signatureAlgorithmsExtensionHeaderLen {
|
||||
return &ParseError{LengthErr, 20}
|
||||
}
|
||||
ssaLen := binary.BigEndian.Uint16(sex)
|
||||
for i := 0; i < int(ssaLen); i += 2 {
|
||||
signatureAlgorithms = append(signatureAlgorithms, binary.BigEndian.Uint16(sex[2:][i:]))
|
||||
ssaLen := int(binary.BigEndian.Uint16(sex))
|
||||
sex = sex[signatureAlgorithmsExtensionHeaderLen:]
|
||||
if len(sex) < ssaLen {
|
||||
return &ParseError{LengthErr, 22}
|
||||
}
|
||||
for i := range ssaLen / 2 {
|
||||
signatureAlgorithms = append(signatureAlgorithms, binary.BigEndian.Uint16(sex[i*2:]))
|
||||
}
|
||||
}
|
||||
exs = exs[4+exLen:]
|
||||
|
||||
@@ -245,6 +245,9 @@ func QUICClientHello(ctx context.Context, metadata *adapter.InboundContext, pack
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if length > uint64(decryptedReader.Len()) {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
index := len(decrypted) - decryptedReader.Len()
|
||||
fragments = append(fragments, qCryptoFragment{offset, length, decrypted[index : index+int(length)]})
|
||||
_, err = decryptedReader.Seek(int64(length), io.SeekCurrent)
|
||||
@@ -291,7 +294,7 @@ func QUICClientHello(ctx context.Context, metadata *adapter.InboundContext, pack
|
||||
find:
|
||||
for {
|
||||
for _, fragment := range fragments {
|
||||
if fragment.offset == index {
|
||||
if fragment.offset == index && fragment.length > 0 {
|
||||
buffer.Write(fragment.payload)
|
||||
index = fragment.offset + fragment.length
|
||||
length++
|
||||
|
||||
@@ -67,7 +67,11 @@ func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg,
|
||||
if question.Qtype == mDNS.TypeA && !t.inet4Enabled || question.Qtype == mDNS.TypeAAAA && !t.inet6Enabled {
|
||||
return dns.FixedResponseStatus(message, mDNS.RcodeSuccess), nil
|
||||
}
|
||||
address, err := t.store.Create(dns.FqdnToDomain(question.Name), question.Qtype == mDNS.TypeAAAA)
|
||||
domain := dns.FqdnToDomain(question.Name)
|
||||
if len(domain) > 255 {
|
||||
return nil, E.New("domain name too long for fakeip")
|
||||
}
|
||||
address, err := t.store.Create(domain, question.Qtype == mDNS.TypeAAAA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -45,19 +45,19 @@ require (
|
||||
github.com/sagernet/netlink v0.0.0-20260814022025-64455d367bbf
|
||||
github.com/sagernet/nftables v0.3.0-mod.4
|
||||
github.com/sagernet/quic-go v0.61.0-sing-box-mod.7
|
||||
github.com/sagernet/sing v0.9.6
|
||||
github.com/sagernet/sing-cloudflared v0.1.3
|
||||
github.com/sagernet/sing-mux v0.3.9
|
||||
github.com/sagernet/sing-openconnect v0.1.0
|
||||
github.com/sagernet/sing-openvpn v0.1.0
|
||||
github.com/sagernet/sing v0.9.7-0.20260929145605-8d939df03478
|
||||
github.com/sagernet/sing-cloudflared v0.1.4-0.20260929150702-b3a1e8f3018c
|
||||
github.com/sagernet/sing-mux v0.3.10-0.20260929204512-caf09fe32475
|
||||
github.com/sagernet/sing-openconnect v0.1.1-0.20260929151225-cbd68c45de58
|
||||
github.com/sagernet/sing-openvpn v0.1.1-0.20260929151220-7c3045dbddce
|
||||
github.com/sagernet/sing-quic v0.7.2-0.20261002084117-75c3ac4fa12b
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||
github.com/sagernet/sing-shadowtls v0.2.1
|
||||
github.com/sagernet/sing-shadowsocks v0.2.9-0.20260929204512-65740e0f0e3e
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.2-0.20260929152114-a69d1086332b
|
||||
github.com/sagernet/sing-shadowtls v0.2.2-0.20260928201441-a9c0127d5c99
|
||||
github.com/sagernet/sing-snell v0.0.0-20260904135315-bc5a12ac736f
|
||||
github.com/sagernet/sing-tun v0.9.7-0.20260928080829-8ab0e83967b4
|
||||
github.com/sagernet/sing-tun v0.9.7-0.20260929152151-0bdadeb4c934
|
||||
github.com/sagernet/sing-usbip v0.0.0-20260817040617-28bd42667eca
|
||||
github.com/sagernet/sing-vmess v0.2.8
|
||||
github.com/sagernet/sing-vmess v0.2.9-0.20260929152519-9b95ab8c9478
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1
|
||||
github.com/sagernet/tailscale v1.102.1-sing-box-1.14-mod.5
|
||||
github.com/sagernet/wireguard-go v0.0.7
|
||||
|
||||
@@ -318,32 +318,32 @@ github.com/sagernet/nftables v0.3.0-mod.4 h1:vnOtcDYeSXv2e5RoRuGH0lrpttQFJ8iC4IC
|
||||
github.com/sagernet/nftables v0.3.0-mod.4/go.mod h1:8kslHG4VvYNihcco+i6uxIX7qbT8A56T0y5q7U44ZaQ=
|
||||
github.com/sagernet/quic-go v0.61.0-sing-box-mod.7 h1:sW2O+DoNF+my1PGlSZ3zG2N+fdxLR3DC0l4sXCM0lBE=
|
||||
github.com/sagernet/quic-go v0.61.0-sing-box-mod.7/go.mod h1:hmLC8GJPp+BrpBgrgJnacvI4fZGIhasuy1ROJJ8GR4E=
|
||||
github.com/sagernet/sing v0.9.6 h1:LXTpEMbr4G/65PSjopjfg+Zp1Xq1ilJnGWq47y/eObI=
|
||||
github.com/sagernet/sing v0.9.6/go.mod h1:K3Owt3xPhHugvlnlPPxZJ/exXdaJfEPOTNorGk4AXjo=
|
||||
github.com/sagernet/sing-cloudflared v0.1.3 h1:J5v401QFvUzzamw0udgs1kOPgnmPyPjo9jbPUiJgBXo=
|
||||
github.com/sagernet/sing-cloudflared v0.1.3/go.mod h1:XEqEDYRCAYLaoPjZ1ifVWJg5iWAJHL2gOAXe/PM28Cg=
|
||||
github.com/sagernet/sing-mux v0.3.9 h1:fhk1tA1OHkDXHedXLanyu/mUepykCXENM9s6sEymo84=
|
||||
github.com/sagernet/sing-mux v0.3.9/go.mod h1:jricpwCOndDsTEM1TM3piJvhL/2Mm7OhLkm+JadJJ1Q=
|
||||
github.com/sagernet/sing-openconnect v0.1.0 h1:nen3Hhr52CHASJtduUwZfMhqgLD30A1LE+SN6Ju2X0Y=
|
||||
github.com/sagernet/sing-openconnect v0.1.0/go.mod h1:4AKZLVcvY3r54UaK2Gbnm7aN8pOwdLz+y4EP0QFZ5Eg=
|
||||
github.com/sagernet/sing-openvpn v0.1.0 h1:bmULMzzDP0EsO0UMkbiiNLIvEIKBlozM+ZD3GiJ2Vtg=
|
||||
github.com/sagernet/sing-openvpn v0.1.0/go.mod h1:PWX7WygD8jpwfqfaGNySXpJYTn0SOwjBI1BKHHC2+Bw=
|
||||
github.com/sagernet/sing v0.9.7-0.20260929145605-8d939df03478 h1:c3Jpk13MOAc516zCuqAGBr7ok9UcpGjCjgWWOQslL0w=
|
||||
github.com/sagernet/sing v0.9.7-0.20260929145605-8d939df03478/go.mod h1:K3Owt3xPhHugvlnlPPxZJ/exXdaJfEPOTNorGk4AXjo=
|
||||
github.com/sagernet/sing-cloudflared v0.1.4-0.20260929150702-b3a1e8f3018c h1:36zXD/qnDk7sh/J4zSEJsnHf4W3TYNCbmjo9MNIlrE4=
|
||||
github.com/sagernet/sing-cloudflared v0.1.4-0.20260929150702-b3a1e8f3018c/go.mod h1:XEqEDYRCAYLaoPjZ1ifVWJg5iWAJHL2gOAXe/PM28Cg=
|
||||
github.com/sagernet/sing-mux v0.3.10-0.20260929204512-caf09fe32475 h1:aG0DqHEOjax7DyfE1GTAXZotOg3QGVCz3/8rCSua2kg=
|
||||
github.com/sagernet/sing-mux v0.3.10-0.20260929204512-caf09fe32475/go.mod h1:jricpwCOndDsTEM1TM3piJvhL/2Mm7OhLkm+JadJJ1Q=
|
||||
github.com/sagernet/sing-openconnect v0.1.1-0.20260929151225-cbd68c45de58 h1:WOPVlvbw3zGl4IzpRcfqB901blgDKuiplVrpptf/TOY=
|
||||
github.com/sagernet/sing-openconnect v0.1.1-0.20260929151225-cbd68c45de58/go.mod h1:4AKZLVcvY3r54UaK2Gbnm7aN8pOwdLz+y4EP0QFZ5Eg=
|
||||
github.com/sagernet/sing-openvpn v0.1.1-0.20260929151220-7c3045dbddce h1:uB2DkIJLZ9waR/ZLBO9IF/ws5BWg0FEegLi90ibhX5I=
|
||||
github.com/sagernet/sing-openvpn v0.1.1-0.20260929151220-7c3045dbddce/go.mod h1:PWX7WygD8jpwfqfaGNySXpJYTn0SOwjBI1BKHHC2+Bw=
|
||||
github.com/sagernet/sing-quic v0.7.2-0.20261002084117-75c3ac4fa12b h1:2Jx/URJAPt32MEbLmAR5nzH87tO6NQZLRfRFvFqBWuk=
|
||||
github.com/sagernet/sing-quic v0.7.2-0.20261002084117-75c3ac4fa12b/go.mod h1:rJFeVxbEej2iuyeCJ3drKW+p5rOgtLIW3XhZ6ty7Fig=
|
||||
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=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||
github.com/sagernet/sing-shadowtls v0.2.1 h1:ZiHZdnEnP+YS73NMsxiZmIFCwNd0M4k7PkGCKNXhbaM=
|
||||
github.com/sagernet/sing-shadowtls v0.2.1/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.9-0.20260929204512-65740e0f0e3e h1:LKgE/uuqp/D2kgxYViOz8vf4slaCUfpFywXjtuwD5gU=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.9-0.20260929204512-65740e0f0e3e/go.mod h1:lo7TWEMDcN5/h5B8S0ew+r78ZODn6SwVaFhvB6H+PTI=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.2-0.20260929152114-a69d1086332b h1:VH65QNqSHat2b+N3Rlzo5Qe44gRmQGwzY5atuy3D0A8=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.2-0.20260929152114-a69d1086332b/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||
github.com/sagernet/sing-shadowtls v0.2.2-0.20260928201441-a9c0127d5c99 h1:l/tdZjaoDp3iqEG4NVrFHtphy1+Qjt9bpWAgNbF8iGg=
|
||||
github.com/sagernet/sing-shadowtls v0.2.2-0.20260928201441-a9c0127d5c99/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
|
||||
github.com/sagernet/sing-snell v0.0.0-20260904135315-bc5a12ac736f h1:tbTCI+iis5sTmua7a6Q7vebcSRURok/LGgnEafnQAsc=
|
||||
github.com/sagernet/sing-snell v0.0.0-20260904135315-bc5a12ac736f/go.mod h1:et8Lws4f5QbOrY65DmjevHGup3mijJkhswkto6cwciM=
|
||||
github.com/sagernet/sing-tun v0.9.7-0.20260928080829-8ab0e83967b4 h1:8LMh5gE8agrhOqeaTg9xML99oVeP8ApxqC0uKeS+ruk=
|
||||
github.com/sagernet/sing-tun v0.9.7-0.20260928080829-8ab0e83967b4/go.mod h1:3EgPst7agntRO7D6GOsiZ1l9FoqdLeuWmKT5TnWkmf0=
|
||||
github.com/sagernet/sing-tun v0.9.7-0.20260929152151-0bdadeb4c934 h1:CC1NMvo1hpRY33IJCwXldUOSgCLjYh0T4vq9pX30+tM=
|
||||
github.com/sagernet/sing-tun v0.9.7-0.20260929152151-0bdadeb4c934/go.mod h1:3EgPst7agntRO7D6GOsiZ1l9FoqdLeuWmKT5TnWkmf0=
|
||||
github.com/sagernet/sing-usbip v0.0.0-20260817040617-28bd42667eca h1:5wA+IE0Fq1CGVLOgSpm0gKKZ03HzugcJ2JyhmDqeX6A=
|
||||
github.com/sagernet/sing-usbip v0.0.0-20260817040617-28bd42667eca/go.mod h1:ADAZZU85MnM91XNhd2TdZRTaIbA7RjTZuQ1KCHcUbNg=
|
||||
github.com/sagernet/sing-vmess v0.2.8 h1:xd5nnDOMlC76RgrLksS4jlk3eMt3c3CvQY3NsjWPWeI=
|
||||
github.com/sagernet/sing-vmess v0.2.8/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY=
|
||||
github.com/sagernet/sing-vmess v0.2.9-0.20260929152519-9b95ab8c9478 h1:q2eQn4nq8oWGxRm9zXesXSlPr9GEgPrOGzf4iPtzG9A=
|
||||
github.com/sagernet/sing-vmess v0.2.9-0.20260929152519-9b95ab8c9478/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY=
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1 h1:XkJcivBC9V4wBjiGXIXZ229aZCU1hzcbp6kSkkyQ478=
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1/go.mod h1:NjhsCEWedJm7eFLyhuBgIEzwfhRmytrUoiLluxs5Sk8=
|
||||
github.com/sagernet/tailscale v1.102.1-sing-box-1.14-mod.5 h1:mGLWVgj2Pl2NlgE1+sEUIDIMB42JdWEPwYmxTnVWg44=
|
||||
|
||||
@@ -75,6 +75,9 @@ func fixReturnChecksum(packet []byte) {
|
||||
return
|
||||
}
|
||||
ipHdr := header.IPv6(packet)
|
||||
if !ipHdr.IsValid(len(packet)) {
|
||||
return
|
||||
}
|
||||
recomputeTransportChecksum(ipHdr.TransportProtocol(), ipHdr.Payload(), ipHdr.SourceAddressSlice(), ipHdr.DestinationAddressSlice())
|
||||
}
|
||||
}
|
||||
@@ -86,6 +89,10 @@ func recomputeTransportChecksum(protocol tcpip.TransportProtocolNumber, transpor
|
||||
return
|
||||
}
|
||||
tcpHdr := header.TCP(transport)
|
||||
dataOffset := int(tcpHdr.DataOffset())
|
||||
if dataOffset < header.TCPMinimumSize || dataOffset > len(transport) {
|
||||
return
|
||||
}
|
||||
tcpHdr.SetChecksum(0)
|
||||
payloadChecksum := checksum.Checksum(tcpHdr.Payload(), 0)
|
||||
pseudoChecksum := header.PseudoHeaderChecksum(header.TCPProtocolNumber, source, destination, uint16(len(transport)))
|
||||
|
||||
@@ -18,6 +18,8 @@ import (
|
||||
"github.com/sagernet/sing-box/transport/v2rayhttp"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/auth"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
@@ -184,11 +186,22 @@ func (n *Inbound) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
destination := M.ParseSocksaddr(hostPort).Unwrap()
|
||||
|
||||
if hijacker, isHijacker := writer.(http.Hijacker); isHijacker {
|
||||
conn, _, err := hijacker.Hijack()
|
||||
conn, reader, err := hijacker.Hijack()
|
||||
if err != nil {
|
||||
n.badRequest(ctx, request, E.New("hijack failed"))
|
||||
return
|
||||
}
|
||||
if cacheLen := reader.Reader.Buffered(); cacheLen > 0 {
|
||||
cache := buf.NewSize(cacheLen)
|
||||
_, err = cache.ReadFullFrom(reader.Reader, cacheLen)
|
||||
if err != nil {
|
||||
cache.Release()
|
||||
conn.Close()
|
||||
n.badRequest(ctx, request, E.Cause(err, "read cache"))
|
||||
return
|
||||
}
|
||||
conn = bufio.NewCachedConn(conn, cache)
|
||||
}
|
||||
n.newConnection(ctx, false, &naiveConn{Conn: conn}, userName, source, destination)
|
||||
} else {
|
||||
n.newConnection(ctx, true, &naiveH2Conn{
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
@@ -35,13 +36,14 @@ var (
|
||||
|
||||
type MultiInbound struct {
|
||||
inbound.Adapter
|
||||
ctx context.Context
|
||||
router adapter.ConnectionRouterEx
|
||||
logger logger.ContextLogger
|
||||
listener *listener.Listener
|
||||
service shadowsocks.MultiService[int]
|
||||
users []option.ShadowsocksUser
|
||||
tracker adapter.SSMTracker
|
||||
ctx context.Context
|
||||
router adapter.ConnectionRouterEx
|
||||
logger logger.ContextLogger
|
||||
listener *listener.Listener
|
||||
service shadowsocks.MultiService[int]
|
||||
usersAccess sync.RWMutex
|
||||
users []option.ShadowsocksUser
|
||||
tracker adapter.SSMTracker
|
||||
}
|
||||
|
||||
func newMultiInbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowsocksInboundOptions) (*MultiInbound, error) {
|
||||
@@ -123,6 +125,8 @@ func (h *MultiInbound) SetTracker(tracker adapter.SSMTracker) {
|
||||
}
|
||||
|
||||
func (h *MultiInbound) UpdateUsers(users []string, uPSKs []string) error {
|
||||
h.usersAccess.Lock()
|
||||
defer h.usersAccess.Unlock()
|
||||
err := h.service.UpdateUsersWithPasswords(common.MapIndexed(users, func(index int, user string) int {
|
||||
return index
|
||||
}), uPSKs)
|
||||
@@ -137,6 +141,15 @@ func (h *MultiInbound) UpdateUsers(users []string, uPSKs []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *MultiInbound) userName(userIndex int) string {
|
||||
h.usersAccess.RLock()
|
||||
defer h.usersAccess.RUnlock()
|
||||
if userIndex >= len(h.users) {
|
||||
return ""
|
||||
}
|
||||
return h.users[userIndex].Name
|
||||
}
|
||||
|
||||
//nolint:staticcheck
|
||||
func (h *MultiInbound) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext, onClose N.CloseHandlerFunc) {
|
||||
err := h.service.NewConnection(ctx, conn, adapter.UpstreamMetadata(metadata))
|
||||
@@ -163,7 +176,7 @@ func (h *MultiInbound) newConnection(ctx context.Context, conn net.Conn, metadat
|
||||
if !loaded {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
user := h.users[userIndex].Name
|
||||
user := h.userName(userIndex)
|
||||
if user == "" {
|
||||
user = F.ToString(userIndex)
|
||||
} else {
|
||||
@@ -186,7 +199,7 @@ func (h *MultiInbound) newPacketConnection(ctx context.Context, conn N.PacketCon
|
||||
if !loaded {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
user := h.users[userIndex].Name
|
||||
user := h.userName(userIndex)
|
||||
if user == "" {
|
||||
user = F.ToString(userIndex)
|
||||
} else {
|
||||
|
||||
@@ -186,16 +186,22 @@ func (t *DNSTransport) createResolver(directDialer func() N.Dialer, resolver *dn
|
||||
myDialer = dialer.NewResolveDialer(t.ctx, myDialer, false, "", t.endpoint.queryOptions, 0)
|
||||
}
|
||||
if isHTTPScheme {
|
||||
if serverURL.Hostname() == "" {
|
||||
return nil, E.New("missing host in resolver address: ", resolver.Addr)
|
||||
}
|
||||
serverAddr := M.ParseSocksaddrHostPortStr(serverURL.Hostname(), serverURL.Port())
|
||||
switch serverURL.Scheme {
|
||||
case "https":
|
||||
if serverAddr.Port == 0 {
|
||||
serverAddr.Port = 443
|
||||
}
|
||||
tlsConfig := common.Must1(tls.NewClient(t.ctx, t.logger, serverAddr.AddrString(), option.OutboundTLSOptions{
|
||||
tlsConfig, err := tls.NewClient(t.ctx, t.logger, serverAddr.AddrString(), option.OutboundTLSOptions{
|
||||
Enabled: true,
|
||||
ALPN: []string{http2.NextProtoTLS, "http/1.1"},
|
||||
}))
|
||||
})
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "create TLS config for resolver ", resolver.Addr)
|
||||
}
|
||||
return transport.NewHTTPSRaw(t.TransportAdapter, t.logger, myDialer, serverURL, http.Header{}, serverAddr, tlsConfig), nil
|
||||
case "http":
|
||||
if serverAddr.Port == 0 {
|
||||
|
||||
@@ -361,7 +361,7 @@ func validateTaildropFileName(name string) error {
|
||||
|
||||
var (
|
||||
taildropExtensionSuffix = regexp.MustCompile(`(\.[a-zA-Z0-9]{0,3}[a-zA-Z][a-zA-Z0-9]{0,3})*$`)
|
||||
taildropNumberSuffix = regexp.MustCompile(` \([0-9]+\)`)
|
||||
taildropNumberSuffix = regexp.MustCompile(` \([0-9]+\)$`)
|
||||
)
|
||||
|
||||
func nextFileName(name string) string {
|
||||
|
||||
@@ -55,7 +55,7 @@ func (t *Endpoint) SendTaildropFile(ctx context.Context, peerStableID string, fi
|
||||
if !peer.Valid() {
|
||||
return E.New("taildrop: peer not found: ", peerStableID)
|
||||
}
|
||||
if peer.Hostinfo().OS() == "tvOS" {
|
||||
if !peer.Hostinfo().Valid() || peer.Hostinfo().OS() == "tvOS" {
|
||||
return E.New("taildrop: peer cannot receive files")
|
||||
}
|
||||
if self.User() != peer.User() && !nodeBackend.PeerHasCap(peer, tailcfg.PeerCapabilityFileSharingTarget) {
|
||||
@@ -187,7 +187,7 @@ func (t *Endpoint) taildropTargets() (canShareFiles bool, targets map[string]boo
|
||||
}
|
||||
targets = make(map[string]bool)
|
||||
for _, peer := range nodeBackend.Peers() {
|
||||
if !peer.Valid() || peer.Hostinfo().OS() == "tvOS" {
|
||||
if !peer.Valid() || !peer.Hostinfo().Valid() || peer.Hostinfo().OS() == "tvOS" {
|
||||
continue
|
||||
}
|
||||
if self.User() != peer.User() && !nodeBackend.PeerHasCap(peer, tailcfg.PeerCapabilityFileSharingTarget) {
|
||||
|
||||
@@ -334,6 +334,9 @@ func (s *Server) authenticate(ctx gliderssh.Context, conn gossh.ConnMetadata) (*
|
||||
func (s *Server) evaluatePolicy(policy *tailcfg.SSHPolicy, sshUser string, node tailcfg.NodeView, userProfile tailcfg.UserProfile, srcIP netip.Addr) (*sshConnInfo, error) {
|
||||
now := time.Now()
|
||||
for _, rule := range policy.Rules {
|
||||
if rule == nil {
|
||||
continue
|
||||
}
|
||||
if rule.RuleExpires != nil && now.After(*rule.RuleExpires) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -811,7 +811,6 @@ func (r *Router) actionSniff(
|
||||
}
|
||||
goto finally
|
||||
}
|
||||
packetBuffers = inputPacketBuffers
|
||||
for {
|
||||
var (
|
||||
sniffBuffer = buf.NewPacket()
|
||||
|
||||
@@ -103,8 +103,14 @@ func (d *systemStackDevice) writeBuffers(packetBuffers []*buf.Buffer) error {
|
||||
func packetDestination(packet []byte) netip.Addr {
|
||||
switch header.IPVersion(packet) {
|
||||
case header.IPv4Version:
|
||||
if len(packet) < header.IPv4MinimumSize {
|
||||
return netip.Addr{}
|
||||
}
|
||||
return header.IPv4(packet).DestinationAddr()
|
||||
case header.IPv6Version:
|
||||
if len(packet) < header.IPv6MinimumSize {
|
||||
return netip.Addr{}
|
||||
}
|
||||
return header.IPv6(packet).DestinationAddr()
|
||||
default:
|
||||
return netip.Addr{}
|
||||
|
||||
@@ -104,8 +104,14 @@ func (d *systemStackDevice) writeBuffers(packetBuffers []*buf.Buffer) error {
|
||||
func packetDestination(packet []byte) netip.Addr {
|
||||
switch header.IPVersion(packet) {
|
||||
case header.IPv4Version:
|
||||
if len(packet) < header.IPv4MinimumSize {
|
||||
return netip.Addr{}
|
||||
}
|
||||
return header.IPv4(packet).DestinationAddr()
|
||||
case header.IPv6Version:
|
||||
if len(packet) < header.IPv6MinimumSize {
|
||||
return netip.Addr{}
|
||||
}
|
||||
return header.IPv6(packet).DestinationAddr()
|
||||
default:
|
||||
return netip.Addr{}
|
||||
|
||||
@@ -60,8 +60,9 @@ func newMuxConnection0(ctx context.Context, conn net.Conn, source M.Socksaddr, h
|
||||
}
|
||||
if reader.Buffered() > 0 {
|
||||
buffer := buf.NewSize(reader.Buffered())
|
||||
_, err = buffer.ReadFullFrom(reader, buffer.Len())
|
||||
_, err = buffer.ReadFullFrom(reader, buffer.FreeLen())
|
||||
if err != nil {
|
||||
buffer.Release()
|
||||
return err
|
||||
}
|
||||
conn = bufio.NewCachedConn(conn, buffer)
|
||||
|
||||
@@ -29,7 +29,7 @@ type GunConn struct {
|
||||
create chan struct{}
|
||||
err error
|
||||
cancel context.CancelFunc
|
||||
readRemaining int
|
||||
readRemaining uint64
|
||||
onClose func()
|
||||
}
|
||||
|
||||
@@ -73,11 +73,11 @@ func (c *GunConn) read(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
if c.readRemaining > 0 {
|
||||
if len(b) > c.readRemaining {
|
||||
if uint64(len(b)) > c.readRemaining {
|
||||
b = b[:c.readRemaining]
|
||||
}
|
||||
n, err = c.reader.Read(b)
|
||||
c.readRemaining -= n
|
||||
c.readRemaining -= uint64(n)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -91,14 +91,13 @@ func (c *GunConn) read(b []byte) (n int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
readLen := int(dataLen)
|
||||
c.readRemaining = readLen
|
||||
if len(b) > readLen {
|
||||
b = b[:readLen]
|
||||
c.readRemaining = dataLen
|
||||
if uint64(len(b)) > dataLen {
|
||||
b = b[:dataLen]
|
||||
}
|
||||
|
||||
n, err = c.reader.Read(b)
|
||||
c.readRemaining -= n
|
||||
c.readRemaining -= uint64(n)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -105,11 +105,16 @@ func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
|
||||
source := sHttp.SourceAddress(request)
|
||||
if h, ok := writer.(http.Hijacker); ok {
|
||||
if request.ContentLength > buf.MaxPooledBufferSize {
|
||||
s.invalidRequest(writer, request, http.StatusRequestEntityTooLarge, E.New("request body too large: ", request.ContentLength))
|
||||
return
|
||||
}
|
||||
var requestBody *buf.Buffer
|
||||
if contentLength := int(request.ContentLength); contentLength > 0 {
|
||||
requestBody = buf.NewSize(contentLength)
|
||||
_, err := requestBody.ReadFullFrom(request.Body, contentLength)
|
||||
if err != nil {
|
||||
requestBody.Release()
|
||||
s.invalidRequest(writer, request, 0, E.Cause(err, "read request"))
|
||||
return
|
||||
}
|
||||
@@ -118,6 +123,7 @@ func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.(http.Flusher).Flush()
|
||||
conn, reader, err := h.Hijack()
|
||||
if err != nil {
|
||||
requestBody.Release()
|
||||
s.invalidRequest(writer, request, 0, E.Cause(err, "hijack conn"))
|
||||
return
|
||||
}
|
||||
@@ -125,6 +131,8 @@ func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
cache := buf.NewSize(cacheLen)
|
||||
_, err = cache.ReadFullFrom(reader.Reader, cacheLen)
|
||||
if err != nil {
|
||||
cache.Release()
|
||||
requestBody.Release()
|
||||
conn.Close()
|
||||
s.invalidRequest(writer, request, 0, E.Cause(err, "read cache"))
|
||||
return
|
||||
|
||||
@@ -105,8 +105,9 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
||||
}
|
||||
if bufReader.Buffered() > 0 {
|
||||
buffer := buf.NewSize(bufReader.Buffered())
|
||||
_, err = buffer.ReadFullFrom(bufReader, buffer.Len())
|
||||
_, err = buffer.ReadFullFrom(bufReader, buffer.FreeLen())
|
||||
if err != nil {
|
||||
buffer.Release()
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -14,6 +14,8 @@ import (
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/transport/v2rayhttp"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
@@ -107,11 +109,22 @@ func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
s.invalidRequest(writer, request, http.StatusInternalServerError, E.New("invalid connection, maybe HTTP/2"))
|
||||
return
|
||||
}
|
||||
conn, _, err := hijacker.Hijack()
|
||||
conn, reader, err := hijacker.Hijack()
|
||||
if err != nil {
|
||||
s.invalidRequest(writer, request, http.StatusInternalServerError, E.Cause(err, "hijack failed"))
|
||||
return
|
||||
}
|
||||
if cacheLen := reader.Reader.Buffered(); cacheLen > 0 {
|
||||
cache := buf.NewSize(cacheLen)
|
||||
_, err = cache.ReadFullFrom(reader.Reader, cacheLen)
|
||||
if err != nil {
|
||||
cache.Release()
|
||||
conn.Close()
|
||||
s.invalidRequest(writer, request, 0, E.Cause(err, "read cache"))
|
||||
return
|
||||
}
|
||||
conn = bufio.NewCachedConn(conn, cache)
|
||||
}
|
||||
s.handler.NewConnectionEx(v2rayhttp.DupContext(request.Context()), conn, sHttp.SourceAddress(request), M.Socksaddr{}, nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -97,8 +97,10 @@ func (c *Client) upgrade(conn net.Conn, requestURL *url.URL, headers http.Header
|
||||
}
|
||||
deadlineConn.SetDeadline(time.Now().Add(C.TCPTimeout))
|
||||
var protocols []string
|
||||
if protocolHeader := headers.Get("Sec-WebSocket-Protocol"); protocolHeader != "" {
|
||||
protocolHeader := headers.Get("Sec-WebSocket-Protocol")
|
||||
if protocolHeader != "" {
|
||||
protocols = []string{protocolHeader}
|
||||
headers = headers.Clone()
|
||||
headers.Del("Sec-WebSocket-Protocol")
|
||||
}
|
||||
reader, _, err := ws.Dialer{Header: ws.HandshakeHeaderHTTP(headers), Protocols: protocols}.Upgrade(deadlineConn, requestURL)
|
||||
@@ -109,7 +111,7 @@ func (c *Client) upgrade(conn net.Conn, requestURL *url.URL, headers http.Header
|
||||
}
|
||||
if reader != nil {
|
||||
buffer := buf.NewSize(reader.Buffered())
|
||||
_, err = buffer.ReadFullFrom(reader, buffer.Len())
|
||||
_, err = buffer.ReadFullFrom(reader, buffer.FreeLen())
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
|
||||
@@ -29,7 +29,13 @@ type WebsocketConn struct {
|
||||
}
|
||||
|
||||
func NewConn(conn net.Conn, remoteAddr net.Addr, state ws.State) *WebsocketConn {
|
||||
controlHandler := wsutil.ControlFrameHandler(conn, state)
|
||||
defaultControlHandler := wsutil.ControlFrameHandler(conn, state)
|
||||
controlHandler := func(header ws.Header, reader io.Reader) error {
|
||||
if header.Length > ws.MaxControlFramePayloadSize {
|
||||
return ws.ErrProtocolControlPayloadOverflow
|
||||
}
|
||||
return defaultControlHandler(header, reader)
|
||||
}
|
||||
return &WebsocketConn{
|
||||
Conn: conn,
|
||||
state: state,
|
||||
@@ -75,10 +81,6 @@ func (c *WebsocketConn) Read(b []byte) (n int, err error) {
|
||||
return
|
||||
}
|
||||
if header.OpCode.IsControl() {
|
||||
if header.Length > 128 {
|
||||
err = wsutil.ErrFrameTooLarge
|
||||
return
|
||||
}
|
||||
err = wrapWsError(c.controlHandler(header, c.reader))
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user