Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: 1 typo in comments #1623

Open
wants to merge 22 commits into
base: dev-next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
d695091
badtls: Support uTLS and TLS ECH for read waiter
nekohasekai Dec 27, 2023
25dc323
Remove `PROCESS_NAME_NATIVE` dwFlag in process query output
nekohasekai Jan 5, 2024
1989cd0
Improve domain suffix match behavior
nekohasekai Jan 5, 2024
b782dbd
Handle Windows power events
nekohasekai Feb 22, 2024
28c12c2
Migrate ntp service to library
nekohasekai Mar 26, 2024
1278edd
Fix timezone for Android and iOS
nekohasekai Jan 16, 2024
97b7733
Add address filter support for DNS rules
nekohasekai Feb 3, 2024
dd8cc4c
Add support for `client-subnet` DNS options
nekohasekai Feb 9, 2024
247fae2
Add rejected DNS response cache support
nekohasekai Feb 14, 2024
d8e305e
Fix DNS fallthrough incorrectly
nekohasekai Mar 15, 2024
4cbd3df
Improve DNS truncate behavior
nekohasekai Feb 14, 2024
cce00be
Fix missing `rule_set_ipcidr_match_source` item in DNS rules
nekohasekai Feb 21, 2024
a6c0b58
Always disable cache for fake-ip DNS transport if `independent_cache`…
PuerNya Feb 4, 2024
2fc4cb1
Fix DNS exchange index
szouc Mar 19, 2024
5bf6e1f
Fixed order for Clash modes
nekohasekai Feb 6, 2024
cacde52
Update quic-go to v0.42.0
nekohasekai Feb 10, 2024
71f0297
Update gVisor to 20240212.0-65-g71212d503
nekohasekai Feb 14, 2024
9008d04
Add `bypass_domain` and `search_domain` platform HTTP proxy options
nekohasekai Feb 18, 2024
4bb1b94
Add `rule-set match` command
nekohasekai Mar 24, 2024
88b1298
documentation: Update DNS manual
nekohasekai Mar 15, 2024
cc8ae72
documentation: Bump version
nekohasekai Feb 14, 2024
5b597fa
Fix: 1 typo
RoboSchmied Mar 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions adapter/experimental.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"time"

"github.com/sagernet/sing-box/common/urltest"
"github.com/sagernet/sing-dns"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/rw"
)
Expand All @@ -30,6 +31,9 @@ type CacheFile interface {
StoreFakeIP() bool
FakeIPStorage

StoreRDRC() bool
dns.RDRCStore

LoadMode() string
StoreMode(mode string) error
LoadSelected(group string) string
Expand Down
13 changes: 8 additions & 5 deletions adapter/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,13 @@ type InboundContext struct {

// rule cache

IPCIDRMatchSource bool
SourceAddressMatch bool
SourcePortMatch bool
DestinationAddressMatch bool
DestinationPortMatch bool
IPCIDRMatchSource bool
SourceAddressMatch bool
SourcePortMatch bool
DestinationAddressMatch bool
DestinationPortMatch bool
DidMatch bool
IgnoreDestinationIPCIDRMatch bool
}

func (c *InboundContext) ResetRuleCache() {
Expand All @@ -64,6 +66,7 @@ func (c *InboundContext) ResetRuleCache() {
c.SourcePortMatch = false
c.DestinationAddressMatch = false
c.DestinationPortMatch = false
c.DidMatch = false
}

type inboundContextKey struct{}
Expand Down
6 changes: 5 additions & 1 deletion adapter/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ func RouterFromContext(ctx context.Context) Router {

type HeadlessRule interface {
Match(metadata *InboundContext) bool
String() string
}

type Rule interface {
Expand All @@ -79,13 +80,15 @@ type Rule interface {
Type() string
UpdateGeosite() error
Outbound() string
String() string
}

type DNSRule interface {
Rule
DisableCache() bool
RewriteTTL() *uint32
ClientSubnet() *netip.Addr
WithAddressLimit() bool
MatchAddressLimit(metadata *InboundContext) bool
}

type RuleSet interface {
Expand All @@ -99,6 +102,7 @@ type RuleSet interface {
type RuleSetMetadata struct {
ContainsProcessRule bool
ContainsWIFIRule bool
ContainsIPCIDRRule bool
}

type RuleSetStartContext interface {
Expand Down
86 changes: 86 additions & 0 deletions cmd/sing-box/cmd_rule_set_match.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package main

import (
"bytes"
"io"
"os"

"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/srs"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/route"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json"

"github.com/spf13/cobra"
)

var flagRuleSetMatchFormat string

var commandRuleSetMatch = &cobra.Command{
Use: "match <rule-set path> <domain>",
Short: "Check if a domain matches the rule set",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
err := ruleSetMatch(args[0], args[1])
if err != nil {
log.Fatal(err)
}
},
}

func init() {
commandRuleSetMatch.Flags().StringVarP(&flagRuleSetMatchFormat, "format", "f", "source", "rule-set format")
commandRuleSet.AddCommand(commandRuleSetMatch)
}

func ruleSetMatch(sourcePath string, domain string) error {
var (
reader io.Reader
err error
)
if sourcePath == "stdin" {
reader = os.Stdin
} else {
reader, err = os.Open(sourcePath)
if err != nil {
return E.Cause(err, "read rule-set")
}
}
content, err := io.ReadAll(reader)
if err != nil {
return E.Cause(err, "read rule-set")
}
var plainRuleSet option.PlainRuleSet
switch flagRuleSetMatchFormat {
case C.RuleSetFormatSource:
var compat option.PlainRuleSetCompat
compat, err = json.UnmarshalExtended[option.PlainRuleSetCompat](content)
if err != nil {
return err
}
plainRuleSet = compat.Upgrade()
case C.RuleSetFormatBinary:
plainRuleSet, err = srs.Read(bytes.NewReader(content), false)
if err != nil {
return err
}
default:
return E.New("unknown rule set format: ", flagRuleSetMatchFormat)
}
for i, ruleOptions := range plainRuleSet.Rules {
var currentRule adapter.HeadlessRule
currentRule, err = route.NewHeadlessRule(nil, ruleOptions)
if err != nil {
return E.Cause(err, "parse rule_set.rules.[", i, "]")
}
if currentRule.Match(&adapter.InboundContext{
Domain: domain,
}) {
println("match rules.[", i, "]: "+currentRule.String())
}
}
return nil
}
78 changes: 55 additions & 23 deletions common/badtls/read_wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ package badtls

import (
"bytes"
"context"
"net"
"os"
"reflect"
"sync"
Expand All @@ -18,20 +20,32 @@ import (
var _ N.ReadWaiter = (*ReadWaitConn)(nil)

type ReadWaitConn struct {
*tls.STDConn
halfAccess *sync.Mutex
rawInput *bytes.Buffer
input *bytes.Reader
hand *bytes.Buffer
readWaitOptions N.ReadWaitOptions
tls.Conn
halfAccess *sync.Mutex
rawInput *bytes.Buffer
input *bytes.Reader
hand *bytes.Buffer
readWaitOptions N.ReadWaitOptions
tlsReadRecord func() error
tlsHandlePostHandshakeMessage func() error
}

func NewReadWaitConn(conn tls.Conn) (tls.Conn, error) {
stdConn, isSTDConn := conn.(*tls.STDConn)
if !isSTDConn {
var (
loaded bool
tlsReadRecord func() error
tlsHandlePostHandshakeMessage func() error
)
for _, tlsCreator := range tlsRegistry {
loaded, tlsReadRecord, tlsHandlePostHandshakeMessage = tlsCreator(conn)
if loaded {
break
}
}
if !loaded {
return nil, os.ErrInvalid
}
rawConn := reflect.Indirect(reflect.ValueOf(stdConn))
rawConn := reflect.Indirect(reflect.ValueOf(conn))
rawHalfConn := rawConn.FieldByName("in")
if !rawHalfConn.IsValid() || rawHalfConn.Kind() != reflect.Struct {
return nil, E.New("badtls: invalid half conn")
Expand All @@ -57,11 +71,13 @@ func NewReadWaitConn(conn tls.Conn) (tls.Conn, error) {
}
hand := (*bytes.Buffer)(unsafe.Pointer(rawHand.UnsafeAddr()))
return &ReadWaitConn{
STDConn: stdConn,
halfAccess: halfAccess,
rawInput: rawInput,
input: input,
hand: hand,
Conn: conn,
halfAccess: halfAccess,
rawInput: rawInput,
input: input,
hand: hand,
tlsReadRecord: tlsReadRecord,
tlsHandlePostHandshakeMessage: tlsHandlePostHandshakeMessage,
}, nil
}

Expand All @@ -71,19 +87,19 @@ func (c *ReadWaitConn) InitializeReadWaiter(options N.ReadWaitOptions) (needCopy
}

func (c *ReadWaitConn) WaitReadBuffer() (buffer *buf.Buffer, err error) {
err = c.Handshake()
err = c.HandshakeContext(context.Background())
if err != nil {
return
}
c.halfAccess.Lock()
defer c.halfAccess.Unlock()
for c.input.Len() == 0 {
err = tlsReadRecord(c.STDConn)
err = c.tlsReadRecord()
if err != nil {
return
}
for c.hand.Len() > 0 {
err = tlsHandlePostHandshakeMessage(c.STDConn)
err = c.tlsHandlePostHandshakeMessage()
if err != nil {
return
}
Expand All @@ -100,7 +116,7 @@ func (c *ReadWaitConn) WaitReadBuffer() (buffer *buf.Buffer, err error) {
if n != 0 && c.input.Len() == 0 && c.rawInput.Len() > 0 &&
// recordType(c.rawInput.Bytes()[0]) == recordTypeAlert {
c.rawInput.Bytes()[0] == 21 {
_ = tlsReadRecord(c.STDConn)
_ = c.tlsReadRecord()
// return n, err // will be io.EOF on closeNotify
}

Expand All @@ -109,11 +125,27 @@ func (c *ReadWaitConn) WaitReadBuffer() (buffer *buf.Buffer, err error) {
}

func (c *ReadWaitConn) Upstream() any {
return c.STDConn
return c.Conn
}

var tlsRegistry []func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error)

func init() {
tlsRegistry = append(tlsRegistry, func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error) {
tlsConn, loaded := conn.(*tls.STDConn)
if !loaded {
return
}
return true, func() error {
return stdTLSReadRecord(tlsConn)
}, func() error {
return stdTLSHandlePostHandshakeMessage(tlsConn)
}
})
}

//go:linkname tlsReadRecord crypto/tls.(*Conn).readRecord
func tlsReadRecord(c *tls.STDConn) error
//go:linkname stdTLSReadRecord crypto/tls.(*Conn).readRecord
func stdTLSReadRecord(c *tls.STDConn) error

//go:linkname tlsHandlePostHandshakeMessage crypto/tls.(*Conn).handlePostHandshakeMessage
func tlsHandlePostHandshakeMessage(c *tls.STDConn) error
//go:linkname stdTLSHandlePostHandshakeMessage crypto/tls.(*Conn).handlePostHandshakeMessage
func stdTLSHandlePostHandshakeMessage(c *tls.STDConn) error
31 changes: 31 additions & 0 deletions common/badtls/read_wait_ech.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//go:build go1.21 && !without_badtls && with_ech

package badtls

import (
"net"
_ "unsafe"

"github.com/sagernet/cloudflare-tls"
"github.com/sagernet/sing/common"
)

func init() {
tlsRegistry = append(tlsRegistry, func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error) {
tlsConn, loaded := common.Cast[*tls.Conn](conn)
if !loaded {
return
}
return true, func() error {
return echReadRecord(tlsConn)
}, func() error {
return echHandlePostHandshakeMessage(tlsConn)
}
})
}

//go:linkname echReadRecord github.com/sagernet/cloudflare-tls.(*Conn).readRecord
func echReadRecord(c *tls.Conn) error

//go:linkname echHandlePostHandshakeMessage github.com/sagernet/cloudflare-tls.(*Conn).handlePostHandshakeMessage
func echHandlePostHandshakeMessage(c *tls.Conn) error
31 changes: 31 additions & 0 deletions common/badtls/read_wait_utls.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//go:build go1.21 && !without_badtls && with_utls

package badtls

import (
"net"
_ "unsafe"

"github.com/sagernet/sing/common"
"github.com/sagernet/utls"
)

func init() {
tlsRegistry = append(tlsRegistry, func(conn net.Conn) (loaded bool, tlsReadRecord func() error, tlsHandlePostHandshakeMessage func() error) {
tlsConn, loaded := common.Cast[*tls.UConn](conn)
if !loaded {
return
}
return true, func() error {
return utlsReadRecord(tlsConn.Conn)
}, func() error {
return utlsHandlePostHandshakeMessage(tlsConn.Conn)
}
})
}

//go:linkname utlsReadRecord github.com/sagernet/utls.(*Conn).readRecord
func utlsReadRecord(c *tls.Conn) error

//go:linkname utlsHandlePostHandshakeMessage github.com/sagernet/utls.(*Conn).handlePostHandshakeMessage
func utlsHandlePostHandshakeMessage(c *tls.Conn) error
4 changes: 2 additions & 2 deletions common/process/searcher_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ func (s *searcher) Search(b []byte, ip netip.Addr, port uint16) (uint32, error)
}

// according to MSDN, only the lower 16 bits of dwLocalPort are used and the port number is in network endian.
// this field can be illustrated as follows depends on different machine endianess:
// this field can be illustrated as follows depends on different machine endianness:
// little endian: [ MSB LSB 0 0 ] interpret as native uint32 is ((LSB<<8)|MSB)
// big endian: [ 0 0 MSB LSB ] interpret as native uint32 is ((MSB<<8)|LSB)
// so we need an syscall.Ntohs on the lower 16 bits after read the port as native uint32
Expand Down Expand Up @@ -223,7 +223,7 @@ func getExecPathFromPID(pid uint32) (string, error) {
r1, _, err := syscall.SyscallN(
procQueryFullProcessImageNameW.Addr(),
uintptr(h),
uintptr(1),
uintptr(0),
uintptr(unsafe.Pointer(&buf[0])),
uintptr(unsafe.Pointer(&size)),
)
Expand Down
5 changes: 5 additions & 0 deletions constant/quic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build with_quic

package constant

const WithQUIC = true
5 changes: 5 additions & 0 deletions constant/quic_stub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build !with_quic

package constant

const WithQUIC = false
Loading