mirror of
https://github.com/MetaCubeX/Clash.Meta.git
synced 2025-04-20 01:00:56 +00:00
Merge branch 'Alpha' into port-hopping2
# Conflicts: # adapter/outbound/hysteria2.go
This commit is contained in:
commit
6e858ce69a
34 changed files with 242 additions and 66 deletions
6
.github/workflows/trigger-cmfa-update.yml
vendored
6
.github/workflows/trigger-cmfa-update.yml
vendored
|
@ -15,7 +15,7 @@ on:
|
|||
- Alpha
|
||||
|
||||
jobs:
|
||||
# Send "core-updated" to MetaCubeX/MihomoForAndroid to trigger update-dependencies
|
||||
# Send "core-updated" to MetaCubeX/ClashMetaForAndroid to trigger update-dependencies
|
||||
trigger-CMFA-update:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
@ -27,7 +27,7 @@ jobs:
|
|||
|
||||
- name: Trigger update-dependencies
|
||||
run: |
|
||||
curl -X POST https://api.github.com/repos/MetaCubeX/MihomoForAndroid/dispatches \
|
||||
curl -X POST https://api.github.com/repos/MetaCubeX/ClashMetaForAndroid/dispatches \
|
||||
-H "Accept: application/vnd.github.everest-preview+json" \
|
||||
-H "Authorization: token ${{ steps.generate-token.outputs.token }}" \
|
||||
-d '{"event_type": "core-updated"}'
|
||||
-d '{"event_type": "core-updated"}'
|
||||
|
|
|
@ -63,3 +63,9 @@ func WithInAddr(addr net.Addr) Addition {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WithDSCP(dscp uint8) Addition {
|
||||
return func(metadata *C.Metadata) {
|
||||
metadata.DSCP = dscp
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ func (f *Fallback) Set(name string) error {
|
|||
if !p.AliveForTestUrl(f.testUrl) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*time.Duration(5000))
|
||||
defer cancel()
|
||||
expectedStatus, _ := utils.NewIntRanges[uint16](f.expectedStatus)
|
||||
expectedStatus, _ := utils.NewUnsignedRanges[uint16](f.expectedStatus)
|
||||
_, _ = p.URLTest(ctx, f.testUrl, expectedStatus)
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ type GroupCommonOption struct {
|
|||
Use []string `group:"use,omitempty"`
|
||||
URL string `group:"url,omitempty"`
|
||||
Interval int `group:"interval,omitempty"`
|
||||
TestTimeout int `group:"timeout,omitempty"`
|
||||
Lazy bool `group:"lazy,omitempty"`
|
||||
DisableUDP bool `group:"disable-udp,omitempty"`
|
||||
Filter string `group:"filter,omitempty"`
|
||||
|
@ -80,7 +81,7 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
|
|||
return nil, fmt.Errorf("%s: %w", groupName, errMissProxy)
|
||||
}
|
||||
|
||||
expectedStatus, err := utils.NewIntRanges[uint16](groupOption.ExpectedStatus)
|
||||
expectedStatus, err := utils.NewUnsignedRanges[uint16](groupOption.ExpectedStatus)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", groupName, err)
|
||||
}
|
||||
|
@ -92,9 +93,11 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
|
|||
groupOption.ExpectedStatus = status
|
||||
testUrl := groupOption.URL
|
||||
|
||||
if groupOption.URL == "" {
|
||||
groupOption.URL = C.DefaultTestURL
|
||||
testUrl = groupOption.URL
|
||||
if groupOption.Type != "select" && groupOption.Type != "relay" {
|
||||
if groupOption.URL == "" {
|
||||
groupOption.URL = C.DefaultTestURL
|
||||
testUrl = groupOption.URL
|
||||
}
|
||||
}
|
||||
|
||||
if len(GroupProxies) != 0 {
|
||||
|
@ -114,7 +117,7 @@ func ParseProxyGroup(config map[string]any, proxyMap map[string]C.Proxy, provide
|
|||
}
|
||||
}
|
||||
|
||||
hc := provider.NewHealthCheck(ps, testUrl, uint(groupOption.Interval), groupOption.Lazy, expectedStatus)
|
||||
hc := provider.NewHealthCheck(ps, testUrl, uint(groupOption.TestTimeout), uint(groupOption.Interval), groupOption.Lazy, expectedStatus)
|
||||
|
||||
pd, err := provider.NewCompatibleProvider(groupName, ps, hc)
|
||||
if err != nil {
|
||||
|
|
|
@ -16,10 +16,6 @@ import (
|
|||
"github.com/dlclark/regexp2"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultURLTestTimeout = time.Second * 5
|
||||
)
|
||||
|
||||
type HealthCheckOption struct {
|
||||
URL string
|
||||
Interval uint
|
||||
|
@ -42,6 +38,7 @@ type HealthCheck struct {
|
|||
lastTouch atomic.TypedValue[time.Time]
|
||||
done chan struct{}
|
||||
singleDo *singledo.Single[struct{}]
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
func (hc *HealthCheck) process() {
|
||||
|
@ -198,7 +195,7 @@ func (hc *HealthCheck) execute(b *batch.Batch[bool], url, uid string, option *ex
|
|||
|
||||
p := proxy
|
||||
b.Go(p.Name(), func() (bool, error) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultURLTestTimeout)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), hc.timeout)
|
||||
defer cancel()
|
||||
log.Debugln("Health Checking, proxy: %s, url: %s, id: {%s}", p.Name(), url, uid)
|
||||
_, _ = p.URLTest(ctx, url, expectedStatus)
|
||||
|
@ -212,15 +209,19 @@ func (hc *HealthCheck) close() {
|
|||
hc.done <- struct{}{}
|
||||
}
|
||||
|
||||
func NewHealthCheck(proxies []C.Proxy, url string, interval uint, lazy bool, expectedStatus utils.IntRanges[uint16]) *HealthCheck {
|
||||
func NewHealthCheck(proxies []C.Proxy, url string, timeout uint, interval uint, lazy bool, expectedStatus utils.IntRanges[uint16]) *HealthCheck {
|
||||
if url == "" {
|
||||
// expectedStatus = nil
|
||||
url = C.DefaultTestURL
|
||||
}
|
||||
if timeout == 0 {
|
||||
timeout = 5000
|
||||
}
|
||||
|
||||
return &HealthCheck{
|
||||
proxies: proxies,
|
||||
url: url,
|
||||
timeout: time.Duration(timeout) * time.Millisecond,
|
||||
extra: map[string]*extraOption{},
|
||||
interval: time.Duration(interval) * time.Second,
|
||||
lazy: lazy,
|
||||
|
|
|
@ -22,6 +22,7 @@ type healthCheckSchema struct {
|
|||
Enable bool `provider:"enable"`
|
||||
URL string `provider:"url"`
|
||||
Interval int `provider:"interval"`
|
||||
TestTimeout int `provider:"timeout,omitempty"`
|
||||
Lazy bool `provider:"lazy,omitempty"`
|
||||
ExpectedStatus string `provider:"expected-status,omitempty"`
|
||||
}
|
||||
|
@ -63,7 +64,7 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide
|
|||
return nil, err
|
||||
}
|
||||
|
||||
expectedStatus, err := utils.NewIntRanges[uint16](schema.HealthCheck.ExpectedStatus)
|
||||
expectedStatus, err := utils.NewUnsignedRanges[uint16](schema.HealthCheck.ExpectedStatus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -75,7 +76,7 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide
|
|||
}
|
||||
hcInterval = uint(schema.HealthCheck.Interval)
|
||||
}
|
||||
hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, hcInterval, schema.HealthCheck.Lazy, expectedStatus)
|
||||
hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, uint(schema.HealthCheck.TestTimeout), hcInterval, schema.HealthCheck.Lazy, expectedStatus)
|
||||
|
||||
var vehicle types.Vehicle
|
||||
switch schema.Type {
|
||||
|
|
|
@ -68,7 +68,8 @@ func ConvertsV2Ray(buf []byte) ([]map[string]any, error) {
|
|||
hysteria["skip-cert-verify"], _ = strconv.ParseBool(query.Get("insecure"))
|
||||
|
||||
proxies = append(proxies, hysteria)
|
||||
case "hysteria2":
|
||||
|
||||
case "hysteria2", "hy2":
|
||||
urlHysteria2, err := url.Parse(line)
|
||||
if err != nil {
|
||||
continue
|
||||
|
@ -79,7 +80,7 @@ func ConvertsV2Ray(buf []byte) ([]map[string]any, error) {
|
|||
hysteria2 := make(map[string]any, 20)
|
||||
|
||||
hysteria2["name"] = name
|
||||
hysteria2["type"] = scheme
|
||||
hysteria2["type"] = "hysteria2"
|
||||
hysteria2["server"] = urlHysteria2.Hostname()
|
||||
if port := urlHysteria2.Port(); port != "" {
|
||||
hysteria2["port"] = port
|
||||
|
@ -101,6 +102,7 @@ func ConvertsV2Ray(buf []byte) ([]map[string]any, error) {
|
|||
hysteria2["up"] = query.Get("up")
|
||||
|
||||
proxies = append(proxies, hysteria2)
|
||||
|
||||
case "tuic":
|
||||
// A temporary unofficial TUIC share link standard
|
||||
// Modified from https://github.com/daeuniverse/dae/discussions/182
|
||||
|
@ -143,7 +145,7 @@ func ConvertsV2Ray(buf []byte) ([]map[string]any, error) {
|
|||
}
|
||||
|
||||
proxies = append(proxies, tuic)
|
||||
|
||||
|
||||
case "trojan":
|
||||
urlTrojan, err := url.Parse(line)
|
||||
if err != nil {
|
||||
|
@ -405,14 +407,27 @@ func ConvertsV2Ray(buf []byte) ([]map[string]any, error) {
|
|||
if query.Get("udp-over-tcp") == "true" || query.Get("uot") == "1" {
|
||||
ss["udp-over-tcp"] = true
|
||||
}
|
||||
if strings.Contains(query.Get("plugin"), "obfs") {
|
||||
obfsParams := strings.Split(query.Get("plugin"), ";")
|
||||
ss["plugin"] = "obfs"
|
||||
ss["plugin-opts"] = map[string]any{
|
||||
"host": obfsParams[2][10:],
|
||||
"mode": obfsParams[1][5:],
|
||||
plugin := query.Get("plugin")
|
||||
if strings.Contains(plugin, ";") {
|
||||
pluginInfo, _ := url.ParseQuery("pluginName=" + strings.ReplaceAll(plugin, ";", "&"))
|
||||
pluginName := pluginInfo.Get("pluginName")
|
||||
if strings.Contains(pluginName, "obfs") {
|
||||
ss["plugin"] = "obfs"
|
||||
ss["plugin-opts"] = map[string]any{
|
||||
"mode": pluginInfo.Get("obfs"),
|
||||
"host": pluginInfo.Get("obfs-host"),
|
||||
}
|
||||
} else if strings.Contains(pluginName, "v2ray-plugin") {
|
||||
ss["plugin"] = "v2ray-plugin"
|
||||
ss["plugin-opts"] = map[string]any{
|
||||
"mode": pluginInfo.Get("mode"),
|
||||
"host": pluginInfo.Get("host"),
|
||||
"path": pluginInfo.Get("path"),
|
||||
"tls": strings.Contains(plugin, "tls"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proxies = append(proxies, ss)
|
||||
|
||||
case "ssr":
|
||||
|
|
|
@ -13,7 +13,7 @@ type IntRanges[T constraints.Integer] []Range[T]
|
|||
|
||||
var errIntRanges = errors.New("intRanges error")
|
||||
|
||||
func NewIntRanges[T constraints.Integer](expected string) (IntRanges[T], error) {
|
||||
func newIntRanges[T constraints.Integer](expected string, parseFn func(string) (T, error)) (IntRanges[T], error) {
|
||||
// example: 200 or 200/302 or 200-400 or 200/204/401-429/501-503
|
||||
expected = strings.TrimSpace(expected)
|
||||
if len(expected) == 0 || expected == "*" {
|
||||
|
@ -25,10 +25,10 @@ func NewIntRanges[T constraints.Integer](expected string) (IntRanges[T], error)
|
|||
return nil, fmt.Errorf("%w, too many ranges to use, maximum support 28 ranges", errIntRanges)
|
||||
}
|
||||
|
||||
return NewIntRangesFromList[T](list)
|
||||
return newIntRangesFromList[T](list, parseFn)
|
||||
}
|
||||
|
||||
func NewIntRangesFromList[T constraints.Integer](list []string) (IntRanges[T], error) {
|
||||
func newIntRangesFromList[T constraints.Integer](list []string, parseFn func(string) (T, error)) (IntRanges[T], error) {
|
||||
var ranges IntRanges[T]
|
||||
for _, s := range list {
|
||||
if s == "" {
|
||||
|
@ -41,7 +41,7 @@ func NewIntRangesFromList[T constraints.Integer](list []string) (IntRanges[T], e
|
|||
return nil, errIntRanges
|
||||
}
|
||||
|
||||
start, err := strconv.ParseInt(strings.Trim(status[0], "[ ]"), 10, 64)
|
||||
start, err := parseFn(strings.Trim(status[0], "[ ]"))
|
||||
if err != nil {
|
||||
return nil, errIntRanges
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ func NewIntRangesFromList[T constraints.Integer](list []string) (IntRanges[T], e
|
|||
case 1:
|
||||
ranges = append(ranges, NewRange(T(start), T(start)))
|
||||
case 2:
|
||||
end, err := strconv.ParseUint(strings.Trim(status[1], "[ ]"), 10, 64)
|
||||
end, err := parseFn(strings.Trim(status[1], "[ ]"))
|
||||
if err != nil {
|
||||
return nil, errIntRanges
|
||||
}
|
||||
|
@ -62,6 +62,38 @@ func NewIntRangesFromList[T constraints.Integer](list []string) (IntRanges[T], e
|
|||
return ranges, nil
|
||||
}
|
||||
|
||||
func parseUnsigned[T constraints.Unsigned](s string) (T, error) {
|
||||
if val, err := strconv.ParseUint(s, 10, 64); err == nil {
|
||||
return T(val), nil
|
||||
} else {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
func NewUnsignedRanges[T constraints.Unsigned](expected string) (IntRanges[T], error) {
|
||||
return newIntRanges(expected, parseUnsigned[T])
|
||||
}
|
||||
|
||||
func NewUnsignedRangesFromList[T constraints.Unsigned](list []string) (IntRanges[T], error) {
|
||||
return newIntRangesFromList(list, parseUnsigned[T])
|
||||
}
|
||||
|
||||
func parseSigned[T constraints.Signed](s string) (T, error) {
|
||||
if val, err := strconv.ParseInt(s, 10, 64); err == nil {
|
||||
return T(val), nil
|
||||
} else {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
func NewSignedRanges[T constraints.Signed](expected string) (IntRanges[T], error) {
|
||||
return newIntRanges(expected, parseSigned[T])
|
||||
}
|
||||
|
||||
func NewSignedRangesFromList[T constraints.Signed](list []string) (IntRanges[T], error) {
|
||||
return newIntRangesFromList(list, parseSigned[T])
|
||||
}
|
||||
|
||||
func (ranges IntRanges[T]) Check(status T) bool {
|
||||
if len(ranges) == 0 {
|
||||
return true
|
||||
|
|
|
@ -15,6 +15,11 @@ import (
|
|||
"github.com/metacubex/mihomo/constant/features"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultTCPTimeout = 5 * time.Second
|
||||
DefaultUDPTimeout = DefaultTCPTimeout
|
||||
)
|
||||
|
||||
type dialFunc func(ctx context.Context, network string, ips []netip.Addr, port string, opt *option) (net.Conn, error)
|
||||
|
||||
var (
|
||||
|
|
|
@ -2,6 +2,7 @@ package dialer
|
|||
|
||||
import (
|
||||
"context"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
"github.com/sagernet/tfo-go"
|
||||
"io"
|
||||
"net"
|
||||
|
@ -66,14 +67,14 @@ func (c *tfoConn) Close() error {
|
|||
|
||||
func (c *tfoConn) LocalAddr() net.Addr {
|
||||
if c.Conn == nil {
|
||||
return nil
|
||||
return &net.TCPAddr{}
|
||||
}
|
||||
return c.Conn.LocalAddr()
|
||||
}
|
||||
|
||||
func (c *tfoConn) RemoteAddr() net.Addr {
|
||||
if c.Conn == nil {
|
||||
return nil
|
||||
return &net.TCPAddr{}
|
||||
}
|
||||
return c.Conn.RemoteAddr()
|
||||
}
|
||||
|
@ -123,7 +124,7 @@ func (c *tfoConn) WriterReplaceable() bool {
|
|||
}
|
||||
|
||||
func dialTFO(ctx context.Context, netDialer net.Dialer, network, address string) (net.Conn, error) {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), DefaultTCPTimeout)
|
||||
dialer := tfo.Dialer{Dialer: netDialer, DisableTFO: false}
|
||||
return &tfoConn{
|
||||
dialed: make(chan bool, 1),
|
||||
|
|
|
@ -13,10 +13,6 @@ import (
|
|||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
const (
|
||||
minInterval = time.Minute * 5
|
||||
)
|
||||
|
||||
var (
|
||||
fileMode os.FileMode = 0o666
|
||||
dirMode os.FileMode = 0o755
|
||||
|
@ -164,8 +160,8 @@ func (f *Fetcher[V]) Destroy() error {
|
|||
|
||||
func (f *Fetcher[V]) pullLoop() {
|
||||
initialInterval := f.interval - time.Since(f.UpdatedAt)
|
||||
if initialInterval < minInterval {
|
||||
initialInterval = minInterval
|
||||
if initialInterval > f.interval {
|
||||
initialInterval = f.interval
|
||||
}
|
||||
|
||||
timer := time.NewTimer(initialInterval)
|
||||
|
|
|
@ -775,7 +775,7 @@ func parseProxies(cfg *RawConfig) (proxies map[string]C.Proxy, providersMap map[
|
|||
}
|
||||
ps = append(ps, proxies[v])
|
||||
}
|
||||
hc := provider.NewHealthCheck(ps, "", 0, true, nil)
|
||||
hc := provider.NewHealthCheck(ps, "", 5000, 0, true, nil)
|
||||
pd, _ := provider.NewCompatibleProvider(provider.ReservedName, ps, hc)
|
||||
providersMap[provider.ReservedName] = pd
|
||||
|
||||
|
@ -1473,7 +1473,7 @@ func parseSniffer(snifferRaw RawSniffer) (*Sniffer, error) {
|
|||
if len(snifferRaw.Sniff) != 0 {
|
||||
for sniffType, sniffConfig := range snifferRaw.Sniff {
|
||||
find := false
|
||||
ports, err := utils.NewIntRangesFromList[uint16](sniffConfig.Ports)
|
||||
ports, err := utils.NewUnsignedRangesFromList[uint16](sniffConfig.Ports)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1500,7 +1500,7 @@ func parseSniffer(snifferRaw RawSniffer) (*Sniffer, error) {
|
|||
// Deprecated: Use Sniff instead
|
||||
log.Warnln("Deprecated: Use Sniff instead")
|
||||
}
|
||||
globalPorts, err := utils.NewIntRangesFromList[uint16](snifferRaw.Ports)
|
||||
globalPorts, err := utils.NewUnsignedRangesFromList[uint16](snifferRaw.Ports)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -43,9 +43,9 @@ const (
|
|||
)
|
||||
|
||||
const (
|
||||
DefaultTCPTimeout = 5 * time.Second
|
||||
DefaultTCPTimeout = dialer.DefaultTCPTimeout
|
||||
DefaultUDPTimeout = dialer.DefaultUDPTimeout
|
||||
DefaultDropTime = 12 * DefaultTCPTimeout
|
||||
DefaultUDPTimeout = DefaultTCPTimeout
|
||||
DefaultTLSTimeout = DefaultTCPTimeout
|
||||
DefaultTestURL = "https://www.gstatic.com/generate_204"
|
||||
)
|
||||
|
|
|
@ -147,6 +147,7 @@ type Metadata struct {
|
|||
SpecialProxy string `json:"specialProxy"`
|
||||
SpecialRules string `json:"specialRules"`
|
||||
RemoteDst string `json:"remoteDestination"`
|
||||
DSCP uint8 `json:"dscp"`
|
||||
|
||||
RawSrcAddr net.Addr `json:"-"`
|
||||
RawDstAddr net.Addr `json:"-"`
|
||||
|
|
|
@ -14,6 +14,7 @@ const (
|
|||
SrcPort
|
||||
DstPort
|
||||
InPort
|
||||
DSCP
|
||||
InUser
|
||||
InName
|
||||
InType
|
||||
|
@ -73,6 +74,8 @@ func (rt RuleType) String() string {
|
|||
return "RuleSet"
|
||||
case Network:
|
||||
return "Network"
|
||||
case DSCP:
|
||||
return "DSCP"
|
||||
case Uid:
|
||||
return "Uid"
|
||||
case SubRules:
|
||||
|
|
6
go.mod
6
go.mod
|
@ -20,8 +20,8 @@ require (
|
|||
github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40
|
||||
github.com/mdlayher/netlink v1.7.2
|
||||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759
|
||||
github.com/metacubex/quic-go v0.40.1-0.20231130135418-0c1b47cf9394
|
||||
github.com/metacubex/sing-quic v0.0.0-20231220152840-85620b446796
|
||||
github.com/metacubex/quic-go v0.41.1-0.20240120014142-a02f4a533d4a
|
||||
github.com/metacubex/sing-quic v0.0.0-20240122125415-d6eb83bc6ec4
|
||||
github.com/metacubex/sing-shadowsocks v0.2.6
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.0
|
||||
github.com/metacubex/sing-tun v0.2.0
|
||||
|
@ -35,7 +35,7 @@ require (
|
|||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97
|
||||
github.com/sagernet/sing v0.3.0
|
||||
github.com/sagernet/sing-mux v0.2.0
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6
|
||||
github.com/sagernet/sing-shadowtls v0.1.4
|
||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6
|
||||
github.com/sagernet/utls v1.5.4
|
||||
|
|
18
go.sum
18
go.sum
|
@ -37,6 +37,7 @@ github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIF
|
|||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g=
|
||||
github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391/go.mod h1:K2R7GhgxrlJzHw2qiPWsCZXf/kXEJN9PLnQK73Ll0po=
|
||||
github.com/ericlagergren/saferand v0.0.0-20220206064634-960a4dd2bc5c h1:RUzBDdZ+e/HEe2Nh8lYsduiPAZygUfVXJn0Ncj5sHMg=
|
||||
github.com/ericlagergren/saferand v0.0.0-20220206064634-960a4dd2bc5c/go.mod h1:ETASDWf/FmEb6Ysrtd1QhjNedUU/ZQxBCRLh60bQ/UI=
|
||||
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 h1:tlDMEdcPRQKBEz5nGDMvswiajqh7k8ogWRlhRwKy5mY=
|
||||
github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1/go.mod h1:4RfsapbGx2j/vU5xC/5/9qB3kn9Awp1YDiEnN43QrJ4=
|
||||
github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA=
|
||||
|
@ -54,6 +55,7 @@ github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vz
|
|||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
|
@ -69,6 +71,7 @@ github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M=
|
|||
github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
|
||||
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
|
@ -78,6 +81,7 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
|||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I=
|
||||
github.com/google/tink/go v1.6.1/go.mod h1:IGW53kTgag+st5yPhKKwJ6u2l+SSp5/v9XF7spovjlY=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
|
@ -111,12 +115,12 @@ github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvO
|
|||
github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88=
|
||||
github.com/metacubex/gvisor v0.0.0-20231209122014-3e43224c7bbc h1:+yTZ6q2EeQCAJNpKNEu5j32Pm23ShD38ElIa635wTrk=
|
||||
github.com/metacubex/gvisor v0.0.0-20231209122014-3e43224c7bbc/go.mod h1:rhBU9tD5ktoGPBtXUquhWuGJ4u+8ZZzBMi2cAdv9q8Y=
|
||||
github.com/metacubex/quic-go v0.40.1-0.20231130135418-0c1b47cf9394 h1:dIT+KB2hknBCrwVAXPeY9tpzzkOZP5m40yqUteRT6/Y=
|
||||
github.com/metacubex/quic-go v0.40.1-0.20231130135418-0c1b47cf9394/go.mod h1:F/t8VnA47xoia8ABlNA4InkZjssvFJ5p6E6jKdbkgAs=
|
||||
github.com/metacubex/quic-go v0.41.1-0.20240120014142-a02f4a533d4a h1:IMr75VdMnDUhkANZemUWqmOPLfwnemiIaCHRnGCdAsY=
|
||||
github.com/metacubex/quic-go v0.41.1-0.20240120014142-a02f4a533d4a/go.mod h1:F/t8VnA47xoia8ABlNA4InkZjssvFJ5p6E6jKdbkgAs=
|
||||
github.com/metacubex/sing v0.0.0-20240111014253-f1818b6a82b2 h1:upEO8dt9WDBavhgcgkXB3hRcwVNbkTbnd+xyzy6ZQZo=
|
||||
github.com/metacubex/sing v0.0.0-20240111014253-f1818b6a82b2/go.mod h1:9pfuAH6mZfgnz/YjP6xu5sxx882rfyjpcrTdUpd6w3g=
|
||||
github.com/metacubex/sing-quic v0.0.0-20231220152840-85620b446796 h1:xiCPttMGAaIh4Ad6t85VxUoUv+Sg88eXzzUvYN8gT5w=
|
||||
github.com/metacubex/sing-quic v0.0.0-20231220152840-85620b446796/go.mod h1:E1e1Uu6YaJddD+c0DtJlSOkfMI0NLdOVhM60KAlcssY=
|
||||
github.com/metacubex/sing-quic v0.0.0-20240122125415-d6eb83bc6ec4 h1:4EukI/UdbuaXov7VDDZf4vaP0ZmkUu827DOeQqzVysw=
|
||||
github.com/metacubex/sing-quic v0.0.0-20240122125415-d6eb83bc6ec4/go.mod h1:bdHqEysJclB9BzIa5jcKKSZ1qua+YEPjR8fOzzE3vZU=
|
||||
github.com/metacubex/sing-shadowsocks v0.2.6 h1:6oEB3QcsFYnNiFeoevcXrCwJ3sAablwVSgtE9R3QeFQ=
|
||||
github.com/metacubex/sing-shadowsocks v0.2.6/go.mod h1:zIkMeSnb8Mbf4hdqhw0pjzkn1d99YJ3JQm/VBg5WMTg=
|
||||
github.com/metacubex/sing-shadowsocks2 v0.2.0 h1:hqwT/AfI5d5UdPefIzR6onGHJfDXs5zgOM5QSgaM/9A=
|
||||
|
@ -136,6 +140,7 @@ github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7/go.mod h1:U
|
|||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5/go.mod h1:tvAoo1QUJwNEU2ITftXTpR7R1RbCzoZUOs3RonqW57k=
|
||||
github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
|
||||
github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg=
|
||||
github.com/openacid/errors v0.8.1/go.mod h1:GUQEJJOJE3W9skHm8E8Y4phdl2LLEN8iD7c5gcGgdx0=
|
||||
github.com/openacid/low v0.1.21 h1:Tr2GNu4N/+rGRYdOsEHOE89cxUIaDViZbVmKz29uKGo=
|
||||
github.com/openacid/low v0.1.21/go.mod h1:q+MsKI6Pz2xsCkzV4BLj7NR5M4EX0sGz5AqotpZDVh0=
|
||||
|
@ -153,6 +158,7 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH
|
|||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.0.2 h1:3yESHrRFYr6xzkz61LLkvNiPFXxJEAABanTQpKbAaew=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.0.2/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
|
@ -165,8 +171,8 @@ github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkk
|
|||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||
github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
|
||||
github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6 h1:5bCAkvDDzSMITiHFjolBwpdqYsvycdTu71FsMEFXQ14=
|
||||
github.com/sagernet/sing-mux v0.2.1-0.20240124034317-9bfb33698bb6/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
|
||||
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||
|
|
|
@ -78,7 +78,7 @@ func getGroupDelay(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
expectedStatus, err := utils.NewIntRanges[uint16](query.Get("expected"))
|
||||
expectedStatus, err := utils.NewUnsignedRanges[uint16](query.Get("expected"))
|
||||
if err != nil {
|
||||
render.Status(r, http.StatusBadRequest)
|
||||
render.JSON(w, r, ErrBadRequest)
|
||||
|
|
|
@ -113,7 +113,7 @@ func getProxyDelay(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
expectedStatus, err := utils.NewIntRanges[uint16](query.Get("expected"))
|
||||
expectedStatus, err := utils.NewUnsignedRanges[uint16](query.Get("expected"))
|
||||
if err != nil {
|
||||
render.Status(r, http.StatusBadRequest)
|
||||
render.JSON(w, r, ErrBadRequest)
|
||||
|
|
|
@ -21,6 +21,7 @@ type Hysteria2Server struct {
|
|||
IgnoreClientBandwidth bool `yaml:"ignore-client-bandwidth" json:"ignore-client-bandwidth,omitempty"`
|
||||
Masquerade string `yaml:"masquerade" json:"masquerade,omitempty"`
|
||||
CWND int `yaml:"cwnd" json:"cwnd,omitempty"`
|
||||
UdpMTU int `yaml:"udp-mtu" json:"udp-mtu,omitempty"`
|
||||
MuxOption sing.MuxOption `yaml:"mux-option" json:"mux-option,omitempty"`
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ type Hysteria2Option struct {
|
|||
IgnoreClientBandwidth bool `inbound:"ignore-client-bandwidth,omitempty"`
|
||||
Masquerade string `inbound:"masquerade,omitempty"`
|
||||
CWND int `inbound:"cwnd,omitempty"`
|
||||
UdpMTU int `inbound:"udp-mtu,omitempty"`
|
||||
MuxOption MuxOption `inbound:"mux-option,omitempty"`
|
||||
}
|
||||
|
||||
|
@ -58,6 +59,7 @@ func NewHysteria2(options *Hysteria2Option) (*Hysteria2, error) {
|
|||
IgnoreClientBandwidth: options.IgnoreClientBandwidth,
|
||||
Masquerade: options.Masquerade,
|
||||
CWND: options.CWND,
|
||||
UdpMTU: options.UdpMTU,
|
||||
MuxOption: options.MuxOption.Build(),
|
||||
},
|
||||
}, nil
|
||||
|
|
|
@ -104,6 +104,12 @@ func New(config LC.Hysteria2Server, tunnel C.Tunnel, additions ...inbound.Additi
|
|||
}
|
||||
}
|
||||
|
||||
if config.UdpMTU == 0 {
|
||||
// "1200" from quic-go's MaxDatagramSize
|
||||
// "-3" from quic-go's DatagramFrame.MaxDataLen
|
||||
config.UdpMTU = 1200 - 3
|
||||
}
|
||||
|
||||
service, err := hysteria2.NewService[string](hysteria2.ServiceOptions{
|
||||
Context: context.Background(),
|
||||
Logger: log.SingLogger,
|
||||
|
@ -115,6 +121,7 @@ func New(config LC.Hysteria2Server, tunnel C.Tunnel, additions ...inbound.Additi
|
|||
Handler: h,
|
||||
MasqueradeHandler: masqueradeHandler,
|
||||
CWND: config.CWND,
|
||||
UdpMTU: config.UdpMTU,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -34,6 +34,14 @@ func setsockopt(rc syscall.RawConn, addr string) error {
|
|||
if err == nil && isIPv6 {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, IPV6_RECVORIGDSTADDR, 1)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVTOS, 1)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, syscall.IPV6_RECVTCLASS, 1)
|
||||
}
|
||||
})
|
||||
|
||||
return err
|
||||
|
|
|
@ -79,6 +79,9 @@ func NewUDP(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*UDPLi
|
|||
continue
|
||||
}
|
||||
|
||||
dscp, _ := getDSCP(oob[:oobn])
|
||||
additions = append(additions, inbound.WithDSCP(dscp))
|
||||
|
||||
if rAddr.Addr().Is4() {
|
||||
// try to unmap 4in6 address
|
||||
lAddr = netip.AddrPortFrom(lAddr.Addr().Unmap(), lAddr.Port())
|
||||
|
|
|
@ -104,7 +104,7 @@ func getOrigDst(oob []byte) (netip.AddrPort, error) {
|
|||
}
|
||||
|
||||
// retrieve the destination address from the SCM.
|
||||
sa, err := unix.ParseOrigDstAddr(&scms[0])
|
||||
sa, err := unix.ParseOrigDstAddr(&scms[1])
|
||||
if err != nil {
|
||||
return netip.AddrPort{}, fmt.Errorf("retrieve destination: %w", err)
|
||||
}
|
||||
|
@ -122,3 +122,30 @@ func getOrigDst(oob []byte) (netip.AddrPort, error) {
|
|||
|
||||
return rAddr, nil
|
||||
}
|
||||
|
||||
func getDSCP (oob []byte) (uint8, error) {
|
||||
scms, err := unix.ParseSocketControlMessage(oob)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("parse control message: %w", err)
|
||||
}
|
||||
dscp, err := parseDSCP(&scms[0])
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("retrieve DSCP: %w", err)
|
||||
}
|
||||
return dscp, nil
|
||||
}
|
||||
|
||||
func parseDSCP(m *unix.SocketControlMessage) (uint8, error) {
|
||||
switch {
|
||||
case m.Header.Level == unix.SOL_IP && m.Header.Type == unix.IP_TOS:
|
||||
dscp := uint8(m.Data[0] >> 2)
|
||||
return dscp, nil
|
||||
|
||||
case m.Header.Level == unix.SOL_IPV6 && m.Header.Type == unix.IPV6_TCLASS:
|
||||
dscp := uint8(m.Data[0] >> 2)
|
||||
return dscp, nil
|
||||
|
||||
default:
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,10 @@ func getOrigDst(oob []byte) (netip.AddrPort, error) {
|
|||
return netip.AddrPort{}, errors.New("UDP redir not supported on current platform")
|
||||
}
|
||||
|
||||
func getDSCP(oob []byte) (uint8, error) {
|
||||
return 0, errors.New("UDP redir not supported on current platform")
|
||||
}
|
||||
|
||||
func dialUDP(network string, lAddr, rAddr netip.AddrPort) (*net.UDPConn, error) {
|
||||
return nil, errors.New("UDP redir not supported on current platform")
|
||||
}
|
||||
|
|
49
rules/common/dscp.go
Normal file
49
rules/common/dscp.go
Normal file
|
@ -0,0 +1,49 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/metacubex/mihomo/common/utils"
|
||||
C "github.com/metacubex/mihomo/constant"
|
||||
)
|
||||
|
||||
type DSCP struct {
|
||||
*Base
|
||||
ranges utils.IntRanges[uint8]
|
||||
payload string
|
||||
adapter string
|
||||
}
|
||||
|
||||
func (d *DSCP) RuleType() C.RuleType {
|
||||
return C.DSCP
|
||||
}
|
||||
|
||||
func (d *DSCP) Match(metadata *C.Metadata) (bool, string) {
|
||||
return d.ranges.Check(metadata.DSCP), d.adapter
|
||||
}
|
||||
|
||||
func (d *DSCP) Adapter() string {
|
||||
return d.adapter
|
||||
}
|
||||
|
||||
func (d *DSCP) Payload() string {
|
||||
return d.payload
|
||||
}
|
||||
|
||||
func NewDSCP(dscp string, adapter string) (*DSCP, error) {
|
||||
ranges, err := utils.NewUnsignedRanges[uint8](dscp)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parse DSCP rule fail: %w", err)
|
||||
}
|
||||
for _, r := range ranges {
|
||||
if r.End() > 63 {
|
||||
return nil, fmt.Errorf("DSCP couldn't be negative or exceed 63")
|
||||
}
|
||||
}
|
||||
return &DSCP{
|
||||
Base: &Base{},
|
||||
payload: dscp,
|
||||
ranges: ranges,
|
||||
adapter: adapter,
|
||||
}, nil
|
||||
}
|
|
@ -39,7 +39,7 @@ func (p *Port) Payload() string {
|
|||
}
|
||||
|
||||
func NewPort(port string, adapter string, ruleType C.RuleType) (*Port, error) {
|
||||
portRanges, err := utils.NewIntRanges[uint16](port)
|
||||
portRanges, err := utils.NewUnsignedRanges[uint16](port)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w, %w", errPayload, err)
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ func NewUid(oUid, adapter string) (*Uid, error) {
|
|||
return nil, fmt.Errorf("uid rule not support this platform")
|
||||
}
|
||||
|
||||
uidRange, err := utils.NewIntRanges[uint32](oUid)
|
||||
uidRange, err := utils.NewUnsignedRanges[uint32](oUid)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w, %w", errPayload, err)
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ func ParseRule(tp, payload, target string, params []string, subRules map[string]
|
|||
parsed, parseErr = RC.NewPort(payload, target, C.DstPort)
|
||||
case "IN-PORT":
|
||||
parsed, parseErr = RC.NewPort(payload, target, C.InPort)
|
||||
case "DSCP":
|
||||
parsed, parseErr = RC.NewDSCP(payload, target)
|
||||
case "PROCESS-NAME":
|
||||
parsed, parseErr = RC.NewProcess(payload, target, true)
|
||||
case "PROCESS-PATH":
|
||||
|
|
|
@ -402,10 +402,11 @@ func (c *quicPktConn) WriteTo(p []byte, addr string) error {
|
|||
_ = struc.Pack(&msgBuf, &msg)
|
||||
err = c.Session.SendDatagram(msgBuf.Bytes())
|
||||
if err != nil {
|
||||
if errSize, ok := err.(quic.ErrMessageTooLarge); ok {
|
||||
var errSize *quic.DatagramTooLargeError
|
||||
if errors.As(err, &errSize) {
|
||||
// need to frag
|
||||
msg.MsgID = uint16(fastrand.Intn(0xFFFF)) + 1 // msgID must be > 0 when fragCount > 1
|
||||
fragMsgs := fragUDPMessage(msg, int(errSize))
|
||||
fragMsgs := fragUDPMessage(msg, int(errSize.PeerMaxDatagramFrameSize))
|
||||
for _, fragMsg := range fragMsgs {
|
||||
msgBuf.Reset()
|
||||
_ = struc.Pack(&msgBuf, &fragMsg)
|
||||
|
|
|
@ -123,7 +123,7 @@ func (q *quicStreamPacketConn) WaitReadFrom() (data []byte, put func(), addr net
|
|||
|
||||
func (q *quicStreamPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
if q.udpRelayMode != common.QUIC && len(p) > q.maxUdpRelayPacketSize {
|
||||
return 0, quic.ErrMessageTooLarge(q.maxUdpRelayPacketSize)
|
||||
return 0, &quic.DatagramTooLargeError{PeerMaxDatagramFrameSize: int64(q.maxUdpRelayPacketSize)}
|
||||
}
|
||||
if q.closed {
|
||||
return 0, net.ErrClosed
|
||||
|
|
|
@ -12,7 +12,9 @@ import (
|
|||
// MaxFragSize is a safe udp relay packet size
|
||||
// because tuicv5 support udp fragment so we unneeded to do a magic modify for quic-go to increase MaxDatagramFrameSize
|
||||
// it may not work fine in some platform
|
||||
var MaxFragSize = 1200 - PacketOverHead
|
||||
// "1200" from quic-go's MaxDatagramSize
|
||||
// "-3" from quic-go's DatagramFrame.MaxDataLen
|
||||
var MaxFragSize = 1200 - PacketOverHead - 3
|
||||
|
||||
func fragWriteNative(quicConn quic.Connection, packet Packet, buf *bytes.Buffer, fragSize int) (err error) {
|
||||
fullPayload := packet.DATA
|
||||
|
|
|
@ -137,7 +137,7 @@ func (q *quicStreamPacketConn) WaitReadFrom() (data []byte, put func(), addr net
|
|||
|
||||
func (q *quicStreamPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) {
|
||||
if len(p) > 0xffff { // uint16 max
|
||||
return 0, quic.ErrMessageTooLarge(0xffff)
|
||||
return 0, &quic.DatagramTooLargeError{PeerMaxDatagramFrameSize: 0xffff}
|
||||
}
|
||||
if q.closed {
|
||||
return 0, net.ErrClosed
|
||||
|
@ -187,9 +187,9 @@ func (q *quicStreamPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err erro
|
|||
err = q.quicConn.SendDatagram(data)
|
||||
}
|
||||
|
||||
var tooLarge quic.ErrMessageTooLarge
|
||||
var tooLarge *quic.DatagramTooLargeError
|
||||
if errors.As(err, &tooLarge) {
|
||||
err = fragWriteNative(q.quicConn, packet, buf, int(tooLarge)-PacketOverHead)
|
||||
err = fragWriteNative(q.quicConn, packet, buf, int(tooLarge.PeerMaxDatagramFrameSize)-PacketOverHead)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
|
|
Loading…
Add table
Reference in a new issue