mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-12 01:57:18 +10:00
Compare commits
25 Commits
v1.1.2
...
v1.2-beta1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19d08b55c8 | ||
|
|
39514b3ca0 | ||
|
|
7ea9d48987 | ||
|
|
df3a982141 | ||
|
|
687b4509df | ||
|
|
41ec2e7944 | ||
|
|
1bd3a9144d | ||
|
|
6e852cc99b | ||
|
|
8320dd0b51 | ||
|
|
960d04d172 | ||
|
|
86ea035bdd | ||
|
|
9b6449dcf4 | ||
|
|
4e22ac1a35 | ||
|
|
8a779f6e94 | ||
|
|
d461768ffb | ||
|
|
5d41e328d4 | ||
|
|
fe492904e9 | ||
|
|
168253b851 | ||
|
|
05620a369e | ||
|
|
8e0fe55363 | ||
|
|
59e521c1db | ||
|
|
f32c149738 | ||
|
|
23a35b3c06 | ||
|
|
044f9c5d4f | ||
|
|
54f9625bdc |
@@ -9,6 +9,8 @@ linters:
|
||||
|
||||
run:
|
||||
skip-dirs:
|
||||
- transport/simple-obfs
|
||||
- transport/clashssr
|
||||
- transport/cloudflaretls
|
||||
|
||||
linters-settings:
|
||||
|
||||
@@ -45,6 +45,6 @@ type V2RayServer interface {
|
||||
}
|
||||
|
||||
type V2RayStatsService interface {
|
||||
RoutedConnection(inbound string, outbound string, conn net.Conn) net.Conn
|
||||
RoutedPacketConnection(inbound string, outbound string, conn N.PacketConn) N.PacketConn
|
||||
RoutedConnection(inbound string, outbound string, user string, conn net.Conn) net.Conn
|
||||
RoutedPacketConnection(inbound string, outbound string, user string, conn N.PacketConn) N.PacketConn
|
||||
}
|
||||
|
||||
@@ -46,6 +46,10 @@ type InboundContext struct {
|
||||
SourceGeoIPCode string
|
||||
GeoIPCode string
|
||||
ProcessInfo *process.Info
|
||||
|
||||
// dns cache
|
||||
|
||||
QueryType uint16
|
||||
}
|
||||
|
||||
type inboundContextKey struct{}
|
||||
|
||||
@@ -47,6 +47,20 @@ type Router interface {
|
||||
SetV2RayServer(server V2RayServer)
|
||||
}
|
||||
|
||||
type routerContextKey struct{}
|
||||
|
||||
func ContextWithRouter(ctx context.Context, router Router) context.Context {
|
||||
return context.WithValue(ctx, (*routerContextKey)(nil), router)
|
||||
}
|
||||
|
||||
func RouterFromContext(ctx context.Context) Router {
|
||||
metadata := ctx.Value((*routerContextKey)(nil))
|
||||
if metadata == nil {
|
||||
return nil
|
||||
}
|
||||
return metadata.(Router)
|
||||
}
|
||||
|
||||
type Rule interface {
|
||||
Service
|
||||
Type() string
|
||||
|
||||
@@ -3,6 +3,7 @@ package main
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -42,7 +43,7 @@ func findSDK() {
|
||||
os.Setenv("ANDROID_SDK_HOME", androidSDKPath)
|
||||
os.Setenv("ANDROID_NDK_HOME", androidNDKPath)
|
||||
os.Setenv("NDK", androidNDKPath)
|
||||
os.Setenv("PATH", os.Getenv("PATH")+":"+filepath.Join(androidNDKPath, "toolchains", "llvm", "prebuilt", "linux-x86_64", "bin"))
|
||||
os.Setenv("PATH", os.Getenv("PATH")+":"+filepath.Join(androidNDKPath, "toolchains", "llvm", "prebuilt", runtime.GOOS+"-x86_64", "bin"))
|
||||
}
|
||||
|
||||
func findNDK() bool {
|
||||
|
||||
@@ -13,8 +13,7 @@ import (
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
"github.com/database64128/tfo-go/v2"
|
||||
"github.com/sagernet/tfo-go"
|
||||
)
|
||||
|
||||
var warnBindInterfaceOnUnsupportedPlatform = warning.New(
|
||||
|
||||
@@ -12,8 +12,7 @@ import (
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
"github.com/database64128/tfo-go/v2"
|
||||
"github.com/sagernet/tfo-go"
|
||||
)
|
||||
|
||||
type slowOpenConn struct {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"net/netip"
|
||||
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
"github.com/oschwald/maxminddb-golang"
|
||||
)
|
||||
@@ -31,8 +30,5 @@ func (r *Reader) Lookup(addr netip.Addr) string {
|
||||
if code != "" {
|
||||
return code
|
||||
}
|
||||
if !N.IsPublicAddr(addr) {
|
||||
return "private"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package redir
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
@@ -29,7 +30,9 @@ func GetOriginalDestination(conn net.Conn) (destination netip.AddrPort, err erro
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
destination = netip.AddrPortFrom(M.AddrFromIP(raw.Addr.Addr[:]), raw.Addr.Port)
|
||||
var port [2]byte
|
||||
binary.BigEndian.PutUint16(port[:], raw.Addr.Port)
|
||||
destination = netip.AddrPortFrom(M.AddrFromIP(raw.Addr.Addr[:]), binary.LittleEndian.Uint16(port[:]))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
8
constant/dhcp.go
Normal file
8
constant/dhcp.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package constant
|
||||
|
||||
import "time"
|
||||
|
||||
const (
|
||||
DHCPTTL = time.Hour
|
||||
DHCPTimeout = time.Minute
|
||||
)
|
||||
@@ -1,3 +1,3 @@
|
||||
package constant
|
||||
|
||||
var Version = "1.1.2"
|
||||
var Version = "1.1.5"
|
||||
|
||||
@@ -1,3 +1,28 @@
|
||||
#### 1.2-beta1
|
||||
|
||||
* Add [DHCP DNS server](/configuration/dns/server) support
|
||||
* Add SSH [host key validation](/configuration/outbound/ssh) support
|
||||
* Add [query_type](/configuration/dns/rule) DNS rule item
|
||||
* Add v2ray [user stats](/configuration/experimental#statsusers) api
|
||||
* Add new clash DNS query api
|
||||
* Improve vmess request
|
||||
* Fix ipv6 redirect on Linux
|
||||
* Fix match geoip private
|
||||
|
||||
#### 1.1.5
|
||||
|
||||
* Add Go 1.20 support
|
||||
* Fix inbound default DF value
|
||||
* Fix auth_user route for naive inbound
|
||||
* Fix gRPC lite header
|
||||
* Ignore domain case in route rules
|
||||
|
||||
#### 1.1.4
|
||||
|
||||
* Fix DNS log
|
||||
* Fix write to h2 conn after closed
|
||||
* Fix create UDP DNS transport from plain IPv6 address
|
||||
|
||||
#### 1.1.2
|
||||
|
||||
* Fix http proxy auth
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
"mixed-in"
|
||||
],
|
||||
"ip_version": 6,
|
||||
"query_type": [
|
||||
"A",
|
||||
"HTTPS",
|
||||
32768
|
||||
],
|
||||
"network": "tcp",
|
||||
"auth_user": [
|
||||
"usera",
|
||||
@@ -119,6 +124,10 @@ Tags of [Inbound](/configuration/inbound).
|
||||
|
||||
Not limited if empty.
|
||||
|
||||
#### query_type
|
||||
|
||||
DNS query type. Values can be integers or type name strings.
|
||||
|
||||
#### network
|
||||
|
||||
`tcp` or `udp`.
|
||||
|
||||
@@ -9,6 +9,11 @@
|
||||
"mixed-in"
|
||||
],
|
||||
"ip_version": 6,
|
||||
"query_type": [
|
||||
"A",
|
||||
"HTTPS",
|
||||
32768
|
||||
],
|
||||
"network": "tcp",
|
||||
"auth_user": [
|
||||
"usera",
|
||||
@@ -118,6 +123,10 @@
|
||||
|
||||
默认不限制。
|
||||
|
||||
#### query_type
|
||||
|
||||
DNS 查询类型。值可以为整数或者类型名称字符串。
|
||||
|
||||
#### network
|
||||
|
||||
`tcp` 或 `udp`。
|
||||
|
||||
@@ -30,16 +30,17 @@ The tag of the dns server.
|
||||
|
||||
The address of the dns server.
|
||||
|
||||
| Protocol | Format |
|
||||
|----------|-----------------------------|
|
||||
| `System` | `local` |
|
||||
| `TCP` | `tcp://1.0.0.1` |
|
||||
| `UDP` | `8.8.8.8` `udp://8.8.4.4` |
|
||||
| `TLS` | `tls://dns.google` |
|
||||
| `HTTPS` | `https://1.1.1.1/dns-query` |
|
||||
| `QUIC` | `quic://dns.adguard.com` |
|
||||
| `HTTP3` | `h3://8.8.8.8/dns-query` |
|
||||
| `RCode` | `rcode://refused` |
|
||||
| Protocol | Format |
|
||||
|----------|-------------------------------|
|
||||
| `System` | `local` |
|
||||
| `TCP` | `tcp://1.0.0.1` |
|
||||
| `UDP` | `8.8.8.8` `udp://8.8.4.4` |
|
||||
| `TLS` | `tls://dns.google` |
|
||||
| `HTTPS` | `https://1.1.1.1/dns-query` |
|
||||
| `QUIC` | `quic://dns.adguard.com` |
|
||||
| `HTTP3` | `h3://8.8.8.8/dns-query` |
|
||||
| `RCode` | `rcode://refused` |
|
||||
| `DHCP` | `dhcp://auto` or `dhcp://en0` |
|
||||
|
||||
!!! warning ""
|
||||
|
||||
@@ -53,6 +54,10 @@ The address of the dns server.
|
||||
|
||||
the RCode transport is often used to block queries. Use with rules and the `disable_cache` rule option.
|
||||
|
||||
!!! warning ""
|
||||
|
||||
DHCP transport is not included by default, see [Installation](/#installation).
|
||||
|
||||
| RCode | Description |
|
||||
|-------------------|-----------------------|
|
||||
| `success` | `No error` |
|
||||
|
||||
@@ -30,16 +30,17 @@ DNS 服务器的标签。
|
||||
|
||||
DNS 服务器的地址。
|
||||
|
||||
| 协议 | 格式 |
|
||||
|----------|-----------------------------|
|
||||
| `System` | `local` |
|
||||
| `TCP` | `tcp://1.0.0.1` |
|
||||
| `UDP` | `8.8.8.8` `udp://8.8.4.4` |
|
||||
| `TLS` | `tls://dns.google` |
|
||||
| `HTTPS` | `https://1.1.1.1/dns-query` |
|
||||
| `QUIC` | `quic://dns.adguard.com` |
|
||||
| `HTTP3` | `h3://8.8.8.8/dns-query` |
|
||||
| `RCode` | `rcode://refused` |
|
||||
| 协议 | 格式 |
|
||||
|----------|------------------------------|
|
||||
| `System` | `local` |
|
||||
| `TCP` | `tcp://1.0.0.1` |
|
||||
| `UDP` | `8.8.8.8` `udp://8.8.4.4` |
|
||||
| `TLS` | `tls://dns.google` |
|
||||
| `HTTPS` | `https://1.1.1.1/dns-query` |
|
||||
| `QUIC` | `quic://dns.adguard.com` |
|
||||
| `HTTP3` | `h3://8.8.8.8/dns-query` |
|
||||
| `RCode` | `rcode://refused` |
|
||||
| `DHCP` | `dhcp://auto` 或 `dhcp://en0` |
|
||||
|
||||
!!! warning ""
|
||||
|
||||
@@ -53,6 +54,10 @@ DNS 服务器的地址。
|
||||
|
||||
RCode 传输层传输层常用于屏蔽请求. 与 DNS 规则和 `disable_cache` 规则选项一起使用。
|
||||
|
||||
!!! warning ""
|
||||
|
||||
默认安装不包含 DHCP 传输层,请参阅 [安装](/zh/#_2)。
|
||||
|
||||
| RCode | 描述 |
|
||||
|-------------------|----------|
|
||||
| `success` | `无错误` |
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
"external_controller": "127.0.0.1:9090",
|
||||
"external_ui": "folder",
|
||||
"secret": "",
|
||||
"direct_io": false,
|
||||
"default_mode": "rule",
|
||||
"store_selected": false,
|
||||
"cache_file": "cache.db"
|
||||
@@ -18,13 +17,15 @@
|
||||
"listen": "127.0.0.1:8080",
|
||||
"stats": {
|
||||
"enabled": true,
|
||||
"direct_io": false,
|
||||
"inbounds": [
|
||||
"socks-in"
|
||||
],
|
||||
"outbounds": [
|
||||
"proxy",
|
||||
"direct"
|
||||
],
|
||||
"users": [
|
||||
"sekai"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -58,10 +59,6 @@ Secret for the RESTful API (optional)
|
||||
Authenticate by spedifying HTTP header `Authorization: Bearer ${secret}`
|
||||
ALWAYS set a secret if RESTful API is listening on 0.0.0.0
|
||||
|
||||
#### direct_io
|
||||
|
||||
Allows lossless relays like splice without real-time traffic reporting.
|
||||
|
||||
#### default_mode
|
||||
|
||||
Default mode in clash, `rule` will be used if empty.
|
||||
@@ -98,10 +95,6 @@ Traffic statistics service settings.
|
||||
|
||||
Enable statistics service.
|
||||
|
||||
#### stats.direct_io
|
||||
|
||||
Allows lossless relays like splice without real-time traffic reporting.
|
||||
|
||||
#### stats.inbounds
|
||||
|
||||
Inbound list to count traffic.
|
||||
@@ -109,3 +102,7 @@ Inbound list to count traffic.
|
||||
#### stats.outbounds
|
||||
|
||||
Outbound list to count traffic.
|
||||
|
||||
#### stats.users
|
||||
|
||||
User list to count traffic.
|
||||
@@ -9,7 +9,6 @@
|
||||
"external_controller": "127.0.0.1:9090",
|
||||
"external_ui": "folder",
|
||||
"secret": "",
|
||||
"direct_io": false,
|
||||
"default_mode": "rule",
|
||||
"store_selected": false,
|
||||
"cache_file": "cache.db"
|
||||
@@ -18,13 +17,15 @@
|
||||
"listen": "127.0.0.1:8080",
|
||||
"stats": {
|
||||
"enabled": true,
|
||||
"direct_io": false,
|
||||
"inbounds": [
|
||||
"socks-in"
|
||||
],
|
||||
"outbounds": [
|
||||
"proxy",
|
||||
"direct"
|
||||
],
|
||||
"users": [
|
||||
"sekai"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -56,10 +57,6 @@ RESTful API 的密钥(可选)
|
||||
通过指定 HTTP 标头 `Authorization: Bearer ${secret}` 进行身份验证
|
||||
如果 RESTful API 正在监听 0.0.0.0,请始终设置一个密钥。
|
||||
|
||||
#### direct_io
|
||||
|
||||
允许像 splice 这样的没有实时流量报告的无损中继。
|
||||
|
||||
#### default_mode
|
||||
|
||||
Clash 中的默认模式,默认使用 `rule`。
|
||||
@@ -96,10 +93,6 @@ gRPC API 监听地址。如果为空,则禁用 V2Ray API。
|
||||
|
||||
启用统计服务。
|
||||
|
||||
#### stats.direct_io
|
||||
|
||||
允许像 splice 这样的没有实时流量报告的无损中继。
|
||||
|
||||
#### stats.inbounds
|
||||
|
||||
统计流量的入站列表。
|
||||
@@ -107,3 +100,7 @@ gRPC API 监听地址。如果为空,则禁用 V2Ray API。
|
||||
#### stats.outbounds
|
||||
|
||||
统计流量的出站列表。
|
||||
|
||||
#### stats.users
|
||||
|
||||
统计流量的用户列表。
|
||||
@@ -12,6 +12,9 @@
|
||||
"private_key": "",
|
||||
"private_key_path": "$HOME/.ssh/id_rsa",
|
||||
"private_key_passphrase": "",
|
||||
"host_key": [
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdH..."
|
||||
],
|
||||
"host_key_algorithms": [],
|
||||
"client_version": "SSH-2.0-OpenSSH_7.4p1",
|
||||
|
||||
@@ -51,6 +54,10 @@ Private key path.
|
||||
|
||||
Private key passphrase.
|
||||
|
||||
#### host_key
|
||||
|
||||
Host key. Accept any if empty.
|
||||
|
||||
#### host_key_algorithms
|
||||
|
||||
Host key algorithms.
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
"private_key": "",
|
||||
"private_key_path": "$HOME/.ssh/id_rsa",
|
||||
"private_key_passphrase": "",
|
||||
"host_key": [
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdH..."
|
||||
],
|
||||
"host_key_algorithms": [],
|
||||
"client_version": "SSH-2.0-OpenSSH_7.4p1",
|
||||
|
||||
@@ -51,6 +54,10 @@ SSH 用户, 默认使用 root。
|
||||
|
||||
密钥密码。
|
||||
|
||||
#### host_key
|
||||
|
||||
主机密钥,留空接受所有。
|
||||
|
||||
#### host_key_algorithms
|
||||
|
||||
主机密钥算法。
|
||||
|
||||
@@ -24,8 +24,9 @@ go install -v -tags with_clash_api github.com/sagernet/sing-box/cmd/sing-box@lat
|
||||
|
||||
| Build Tag | Description |
|
||||
|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `with_quic` | Build with QUIC support, see [QUIC and HTTP3 dns transports](./configuration/dns/server), [Naive inbound](./configuration/inbound/naive), [Hysteria Inbound](./configuration/inbound/hysteria), [Hysteria Outbound](./configuration/outbound/hysteria) and [V2Ray Transport#QUIC](./configuration/shared/v2ray-transport#quic). |
|
||||
| `with_quic` | Build with QUIC support, see [QUIC and HTTP3 DNS transports](./configuration/dns/server), [Naive inbound](./configuration/inbound/naive), [Hysteria Inbound](./configuration/inbound/hysteria), [Hysteria Outbound](./configuration/outbound/hysteria) and [V2Ray Transport#QUIC](./configuration/shared/v2ray-transport#quic). |
|
||||
| `with_grpc` | Build with standard gRPC support, see [V2Ray Transport#gRPC](./configuration/shared/v2ray-transport#grpc). |
|
||||
| `with_dhcp` | Build with DHCP support, see [DHCP DNS transport](./configuration/dns/server). |
|
||||
| `with_wireguard` | Build with WireGuard support, see [WireGuard outbound](./configuration/outbound/wireguard). |
|
||||
| `with_shadowsocksr` | Build with ShadowsocksR support, see [ShadowsocksR outbound](./configuration/outbound/shadowsocksr). |
|
||||
| `with_ech` | Build with TLS ECH extension support for TLS outbound, see [TLS](./configuration/shared/tls#ech). |
|
||||
|
||||
@@ -26,6 +26,7 @@ go install -v -tags with_clash_api github.com/sagernet/sing-box/cmd/sing-box@lat
|
||||
|------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| `with_quic` | 启用 QUIC 支持,参阅 [QUIC 和 HTTP3 DNS 传输层](./configuration/dns/server),[Naive 入站](./configuration/inbound/naive),[Hysteria 入站](./configuration/inbound/hysteria),[Hysteria 出站](./configuration/outbound/hysteria) 和 [V2Ray 传输层#QUIC](./configuration/shared/v2ray-transport#quic)。 |
|
||||
| `with_grpc` | 启用标准 gRPC 支持,参阅 [V2Ray 传输层#gRPC](./configuration/shared/v2ray-transport#grpc)。 |
|
||||
| `with_dhcp` | 启用 DHCP 支持,参阅 [DHCP DNS 传输层](./configuration/dns/server)。 |
|
||||
| `with_wireguard` | 启用 WireGuard 支持,参阅 [WireGuard 出站](./configuration/outbound/wireguard)。 |
|
||||
| `with_shadowsocksr` | 启用 ShadowsocksR 支持,参阅 [ShadowsocksR 出站](./configuration/outbound/shadowsocksr)。 |
|
||||
| `with_ech` | 启用 TLS ECH 扩展支持,参阅 [TLS](./configuration/shared/tls#ech)。 |
|
||||
|
||||
82
experimental/clashapi/dns.go
Normal file
82
experimental/clashapi/dns.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package clashapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing/common"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/render"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
func dnsRouter(router adapter.Router) http.Handler {
|
||||
r := chi.NewRouter()
|
||||
r.Get("/query", queryDNS(router))
|
||||
return r
|
||||
}
|
||||
|
||||
func queryDNS(router adapter.Router) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
name := r.URL.Query().Get("name")
|
||||
qTypeStr := r.URL.Query().Get("type")
|
||||
if qTypeStr == "" {
|
||||
qTypeStr = "A"
|
||||
}
|
||||
|
||||
qType, exist := dns.StringToType[qTypeStr]
|
||||
if !exist {
|
||||
render.Status(r, http.StatusBadRequest)
|
||||
render.JSON(w, r, newError("invalid query type"))
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), C.DNSTimeout)
|
||||
defer cancel()
|
||||
|
||||
msg := dns.Msg{}
|
||||
msg.SetQuestion(dns.Fqdn(name), qType)
|
||||
resp, err := router.Exchange(ctx, &msg)
|
||||
if err != nil {
|
||||
render.Status(r, http.StatusInternalServerError)
|
||||
render.JSON(w, r, newError(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
responseData := render.M{
|
||||
"Status": resp.Rcode,
|
||||
"Question": resp.Question,
|
||||
"Server": "internal",
|
||||
"TC": resp.Truncated,
|
||||
"RD": resp.RecursionDesired,
|
||||
"RA": resp.RecursionAvailable,
|
||||
"AD": resp.AuthenticatedData,
|
||||
"CD": resp.CheckingDisabled,
|
||||
}
|
||||
|
||||
rr2Json := func(rr dns.RR) render.M {
|
||||
header := rr.Header()
|
||||
return render.M{
|
||||
"name": header.Name,
|
||||
"type": header.Rrtype,
|
||||
"TTL": header.Ttl,
|
||||
"data": rr.String()[len(header.String()):],
|
||||
}
|
||||
}
|
||||
|
||||
if len(resp.Answer) > 0 {
|
||||
responseData["Answer"] = common.Map(resp.Answer, rr2Json)
|
||||
}
|
||||
if len(resp.Ns) > 0 {
|
||||
responseData["Authority"] = common.Map(resp.Ns, rr2Json)
|
||||
}
|
||||
if len(resp.Extra) > 0 {
|
||||
responseData["Additional"] = common.Map(resp.Extra, rr2Json)
|
||||
}
|
||||
|
||||
render.JSON(w, r, responseData)
|
||||
}
|
||||
}
|
||||
@@ -99,6 +99,7 @@ func NewServer(router adapter.Router, logFactory log.ObservableFactory, options
|
||||
r.Mount("/script", scriptRouter())
|
||||
r.Mount("/profile", profileRouter())
|
||||
r.Mount("/cache", cacheRouter())
|
||||
r.Mount("/dns", dnsRouter(router))
|
||||
})
|
||||
if options.ExternalUI != "" {
|
||||
chiRouter.Group(func(r chi.Router) {
|
||||
|
||||
@@ -31,6 +31,7 @@ type StatsService struct {
|
||||
createdAt time.Time
|
||||
inbounds map[string]bool
|
||||
outbounds map[string]bool
|
||||
users map[string]bool
|
||||
access sync.Mutex
|
||||
counters map[string]*atomic.Int64
|
||||
}
|
||||
@@ -41,26 +42,32 @@ func NewStatsService(options option.V2RayStatsServiceOptions) *StatsService {
|
||||
}
|
||||
inbounds := make(map[string]bool)
|
||||
outbounds := make(map[string]bool)
|
||||
users := make(map[string]bool)
|
||||
for _, inbound := range options.Inbounds {
|
||||
inbounds[inbound] = true
|
||||
}
|
||||
for _, outbound := range options.Outbounds {
|
||||
outbounds[outbound] = true
|
||||
}
|
||||
for _, user := range options.Users {
|
||||
users[user] = true
|
||||
}
|
||||
return &StatsService{
|
||||
createdAt: time.Now(),
|
||||
inbounds: inbounds,
|
||||
outbounds: outbounds,
|
||||
users: users,
|
||||
counters: make(map[string]*atomic.Int64),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *StatsService) RoutedConnection(inbound string, outbound string, conn net.Conn) net.Conn {
|
||||
func (s *StatsService) RoutedConnection(inbound string, outbound string, user string, conn net.Conn) net.Conn {
|
||||
var readCounter []*atomic.Int64
|
||||
var writeCounter []*atomic.Int64
|
||||
countInbound := inbound != "" && s.inbounds[inbound]
|
||||
countOutbound := outbound != "" && s.outbounds[outbound]
|
||||
if !countInbound && !countOutbound {
|
||||
countUser := user != "" && s.users[user]
|
||||
if !countInbound && !countOutbound && !countUser {
|
||||
return conn
|
||||
}
|
||||
s.access.Lock()
|
||||
@@ -72,16 +79,21 @@ func (s *StatsService) RoutedConnection(inbound string, outbound string, conn ne
|
||||
readCounter = append(readCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>uplink"))
|
||||
writeCounter = append(writeCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>downlink"))
|
||||
}
|
||||
if countUser {
|
||||
readCounter = append(readCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>uplink"))
|
||||
writeCounter = append(writeCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>downlink"))
|
||||
}
|
||||
s.access.Unlock()
|
||||
return trackerconn.New(conn, readCounter, writeCounter)
|
||||
}
|
||||
|
||||
func (s *StatsService) RoutedPacketConnection(inbound string, outbound string, conn N.PacketConn) N.PacketConn {
|
||||
func (s *StatsService) RoutedPacketConnection(inbound string, outbound string, user string, conn N.PacketConn) N.PacketConn {
|
||||
var readCounter []*atomic.Int64
|
||||
var writeCounter []*atomic.Int64
|
||||
countInbound := inbound != "" && s.inbounds[inbound]
|
||||
countOutbound := outbound != "" && s.outbounds[outbound]
|
||||
if !countInbound && !countOutbound {
|
||||
countUser := user != "" && s.users[user]
|
||||
if !countInbound && !countOutbound && !countUser {
|
||||
return conn
|
||||
}
|
||||
s.access.Lock()
|
||||
@@ -93,6 +105,10 @@ func (s *StatsService) RoutedPacketConnection(inbound string, outbound string, c
|
||||
readCounter = append(readCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>uplink"))
|
||||
writeCounter = append(writeCounter, s.loadOrCreateCounter("outbound>>>"+outbound+">>>traffic>>>downlink"))
|
||||
}
|
||||
if countUser {
|
||||
readCounter = append(readCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>uplink"))
|
||||
writeCounter = append(writeCounter, s.loadOrCreateCounter("user>>>"+user+">>>traffic>>>downlink"))
|
||||
}
|
||||
s.access.Unlock()
|
||||
return trackerconn.NewPacket(conn, readCounter, writeCounter)
|
||||
}
|
||||
|
||||
56
go.mod
56
go.mod
@@ -4,44 +4,45 @@ go 1.18
|
||||
|
||||
require (
|
||||
berty.tech/go-libtor v1.0.385
|
||||
github.com/Dreamacro/clash v1.12.0
|
||||
github.com/Dreamacro/clash v1.13.0
|
||||
github.com/caddyserver/certmagic v0.17.2
|
||||
github.com/cretz/bine v0.2.0
|
||||
github.com/database64128/tfo-go/v2 v2.0.2
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/go-chi/chi/v5 v5.0.8
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-chi/render v1.0.2
|
||||
github.com/gofrs/uuid v4.3.1+incompatible
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
github.com/hashicorp/yamux v0.1.1
|
||||
github.com/insomniacslk/dhcp v0.0.0-20221215072855-de60144f33f8
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/mholt/acmez v1.0.4
|
||||
github.com/miekg/dns v1.1.50
|
||||
github.com/oschwald/maxminddb-golang v1.10.0
|
||||
github.com/pires/go-proxyproto v0.6.2
|
||||
github.com/refraction-networking/utls v1.2.0
|
||||
github.com/refraction-networking/utls v1.2.1
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0
|
||||
github.com/sagernet/quic-go v0.0.0-20221206044826-d15273f58d82
|
||||
github.com/sagernet/sing v0.1.2
|
||||
github.com/sagernet/sing-dns v0.1.1
|
||||
github.com/sagernet/sing-shadowsocks v0.1.0
|
||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
||||
github.com/sagernet/sing v0.1.7-0.20230207063819-27d2950cdbe9
|
||||
github.com/sagernet/sing-dns v0.1.3
|
||||
github.com/sagernet/sing-shadowsocks v0.1.1-0.20230202035033-e3123545f2f7
|
||||
github.com/sagernet/sing-tun v0.1.1
|
||||
github.com/sagernet/sing-vmess v0.1.1
|
||||
github.com/sagernet/sing-vmess v0.1.1-0.20230207064843-983dde690564
|
||||
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195
|
||||
github.com/sagernet/tfo-go v0.0.0-20230207095944-549363a7327d
|
||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e
|
||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c
|
||||
github.com/spf13/cobra v1.6.1
|
||||
github.com/stretchr/testify v1.8.1
|
||||
go.etcd.io/bbolt v1.3.6
|
||||
go.etcd.io/bbolt v1.3.7
|
||||
go.uber.org/atomic v1.10.0
|
||||
go.uber.org/zap v1.24.0
|
||||
go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab
|
||||
golang.org/x/crypto v0.4.0
|
||||
golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15
|
||||
golang.org/x/net v0.4.0
|
||||
golang.org/x/sys v0.3.0
|
||||
google.golang.org/grpc v1.51.0
|
||||
go4.org/netipx v0.0.0-20230125063823-8449b0a6169f
|
||||
golang.org/x/crypto v0.5.0
|
||||
golang.org/x/exp v0.0.0-20230105202349-8879d0199aa3
|
||||
golang.org/x/net v0.5.0
|
||||
golang.org/x/sys v0.5.0
|
||||
google.golang.org/grpc v1.53.0
|
||||
google.golang.org/protobuf v1.28.1
|
||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c
|
||||
)
|
||||
@@ -57,30 +58,31 @@ require (
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/klauspost/compress v1.15.12 // indirect
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/klauspost/compress v1.15.15 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.1.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/libdns/libdns v0.2.1 // indirect
|
||||
github.com/marten-seemann/qpack v0.3.0 // indirect
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.4.0 // indirect
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
|
||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect
|
||||
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/u-root/uio v0.0.0-20221213070652-c3537552635f // indirect
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
golang.org/x/mod v0.6.0 // indirect
|
||||
golang.org/x/text v0.5.0 // indirect
|
||||
golang.org/x/text v0.6.0 // indirect
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||
golang.org/x/tools v0.2.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
lukechampine.com/blake3 v1.1.7 // indirect
|
||||
)
|
||||
|
||||
264
go.sum
264
go.sum
@@ -1,49 +1,32 @@
|
||||
berty.tech/go-libtor v1.0.385 h1:RWK94C3hZj6Z2GdvePpHJLnWYobFr3bY/OdUJ5aoEXw=
|
||||
berty.tech/go-libtor v1.0.385/go.mod h1:9swOOQVb+kmvuAlsgWUK/4c52pm69AdbJsxLzk+fJEw=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Dreamacro/clash v1.12.0 h1:Fv10zwTtEo4jN1V+fLK+WEOulFAxlZFPfFQGWmbMDrk=
|
||||
github.com/Dreamacro/clash v1.12.0/go.mod h1:KXZNe2ZS9Z7zZYCFENEW8J9OgyrYrwlr/Gj9ZpzcDVU=
|
||||
github.com/Dreamacro/clash v1.13.0 h1:gF0E0TluE1LCmuhhg0/bjqABYDmSnXkUjXjRhZxyrm8=
|
||||
github.com/Dreamacro/clash v1.13.0/go.mod h1:hf0RkWPsQ0e8oS8WVJBIRocY/1ILYzQQg9zeMwd8LsM=
|
||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/caddyserver/certmagic v0.17.2 h1:o30seC1T/dBqBCNNGNHWwj2i5/I/FMjBbTAhjADP3nE=
|
||||
github.com/caddyserver/certmagic v0.17.2/go.mod h1:ouWUuC490GOLJzkyN35eXfV8bSbwMwSf4bdhkIxtdQE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c h1:K1VdSnBZiGapczwcUKnE1qcsMBclA84DUOD2NG/78VY=
|
||||
github.com/cloudflare/circl v1.2.1-0.20221019164342-6ab4dfed8f3c/go.mod h1:+CauBF6R70Jqcyl8N2hC8pAXYbWkGIezuSbuGLtRhnw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
|
||||
github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
|
||||
github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI=
|
||||
github.com/database64128/tfo-go/v2 v2.0.2 h1:5rGgkJeLEKlNaqredfrPQNLnctn1b+1fq/8tdKdOzJg=
|
||||
github.com/database64128/tfo-go/v2 v2.0.2/go.mod h1:FDdt4JaAsRU66wsYHxSVytYimPkKIHupVsxM+5DhvjY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0=
|
||||
github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
@@ -52,23 +35,10 @@ github.com/go-chi/render v1.0.2 h1:4ER/udB0+fMWB2Jlf15RV3F4A2FDuYi/9f+lFttR/Lg=
|
||||
github.com/go-chi/render v1.0.2/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI=
|
||||
github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
@@ -78,18 +48,30 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
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/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE=
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/klauspost/compress v1.15.12 h1:YClS/PImqYbn+UILDnqxQCZ3RehC9N318SU3kElDUEM=
|
||||
github.com/klauspost/compress v1.15.12/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20221215072855-de60144f33f8 h1:Z72DOke2yOK0Ms4Z2LK1E1OrRJXOxSj5DllTz2FYTRg=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20221215072855-de60144f33f8/go.mod h1:m5WMe03WCvWcXjRnhvaAbAAXdCnu20J5P+mmH44ZzpE=
|
||||
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok=
|
||||
github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
|
||||
github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0=
|
||||
github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
@@ -97,33 +79,25 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
|
||||
github.com/libdns/libdns v0.2.1/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6ki6hE=
|
||||
github.com/marten-seemann/qpack v0.3.0/go.mod h1:cGfKPBiP4a9EQdxCwEwI/GEeWAsjSekBvx/X8mh58+g=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
|
||||
github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
|
||||
github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y=
|
||||
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
|
||||
github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o=
|
||||
github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg=
|
||||
github.com/mholt/acmez v1.0.4 h1:N3cE4Pek+dSolbsofIkAYz6H1d3pE+2G0os7QHslf80=
|
||||
github.com/mholt/acmez v1.0.4/go.mod h1:qFGLZ4u+ehWINeJZjzPlsnjJBCPAADWTcIqE/7DAYQY=
|
||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
||||
github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg=
|
||||
github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0=
|
||||
@@ -133,10 +107,16 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/refraction-networking/utls v1.2.0 h1:U5f8wkij2NVinfLuJdFP3gCMwIHs+EzvhxmYdXgiapo=
|
||||
github.com/refraction-networking/utls v1.2.0/go.mod h1:NPq+cVqzH7D1BeOkmOcb5O/8iVewAsiVt2x1/eO0hgQ=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0 h1:5ViXqBZ90wpUcZS0ge79rf029yx0dYB0McyPJwqqj7U=
|
||||
github.com/quic-go/qtls-go1-18 v0.2.0/go.mod h1:moGulGHK7o6O8lSPSZNoOwcLvJKJ85vVNc7oJFD65bc=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0 h1:Cvn2WdhyViFUHoOqK52i51k4nDX8EwIh5VJiVM4nttk=
|
||||
github.com/quic-go/qtls-go1-19 v0.2.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0 h1:d1PK3ErFy9t7zxKsG3NXBJXZjp/kMLoIb3y/kV54oAI=
|
||||
github.com/quic-go/qtls-go1-20 v0.1.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
|
||||
github.com/refraction-networking/utls v1.2.1 h1:BvjkQ5ar/45MuDZzqJlOU4a6JuwVH3AXcR8WqtRZ340=
|
||||
github.com/refraction-networking/utls v1.2.1/go.mod h1:L1goe44KvhnTfctUffM2isnJpSjPlYShrhXDeZaoYKw=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0 h1:KyhtFFt1Jtp5vW2ohNvstvQffTOQ/s5vENuGXzdA+TM=
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20221031050923-d70792f4c3a0/go.mod h1:D4SFEOkJK+4W1v86ZhX0jPM0rAL498fyQAChqMtes/I=
|
||||
@@ -144,26 +124,30 @@ github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c
|
||||
github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms=
|
||||
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/quic-go v0.0.0-20221206044826-d15273f58d82 h1:Mr4UIyvmyhybR0DdRZ2CI66s0vT6G6z2gOBByDZBuV8=
|
||||
github.com/sagernet/quic-go v0.0.0-20221206044826-d15273f58d82/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4=
|
||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32 h1:tztuJB+giOWNRKQEBVY2oI3PsheTooMdh+/yxemYQYY=
|
||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32/go.mod h1:QMCkxXAC3CvBgDZVIJp43NWTuwGBScCzMLVLynjERL8=
|
||||
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||
github.com/sagernet/sing v0.1.2 h1:rp5AqY23P0klk2IaLEI0/WJsD8FTVlv9TaI2QSL6TDA=
|
||||
github.com/sagernet/sing v0.1.2/go.mod h1:bvmen56QnVbMrWy+nr5nsbz7U5MUPuY0L0S/XfhCsTs=
|
||||
github.com/sagernet/sing-dns v0.1.1 h1:0POQ4YgUc9EjUrW7SFj2Odl73Xtkbqq85fiB97ccVTU=
|
||||
github.com/sagernet/sing-dns v0.1.1/go.mod h1:IXw6t1F25YvzmgCgV2kKySf4XCEKkUJnmLvKCd7jFEc=
|
||||
github.com/sagernet/sing-shadowsocks v0.1.0 h1:cDmmOkA11fzVdhyCZQEeI3ozQz+59rj8+rqPb91xux4=
|
||||
github.com/sagernet/sing-shadowsocks v0.1.0/go.mod h1:O5LtOs8Ivw686FqLpO0Zu+A0ROVE15VeqEK3yDRRAms=
|
||||
github.com/sagernet/sing v0.1.7-0.20230207063819-27d2950cdbe9 h1:qnXh4RjHsNjdZXkfbqwVqAzYUfc160gfkS5gepmsA+A=
|
||||
github.com/sagernet/sing v0.1.7-0.20230207063819-27d2950cdbe9/go.mod h1:JLSXsPTGRJFo/3X7EcAOCUgJH2/gAoxSJgBsnCZRp/w=
|
||||
github.com/sagernet/sing-dns v0.1.3 h1:PbBK7wqkvnwGguhWtTV88fKvSUUr62+ENWs234Ddvns=
|
||||
github.com/sagernet/sing-dns v0.1.3/go.mod h1:+lFb7GBtFcuyt/mbf9M4Eal8xbycIhjBepGB+rckmBk=
|
||||
github.com/sagernet/sing-shadowsocks v0.1.1-0.20230202035033-e3123545f2f7 h1:Plup6oEiyLzY3HDqQ+QsUBzgBGdVmcsgf3t8h940z9U=
|
||||
github.com/sagernet/sing-shadowsocks v0.1.1-0.20230202035033-e3123545f2f7/go.mod h1:O5LtOs8Ivw686FqLpO0Zu+A0ROVE15VeqEK3yDRRAms=
|
||||
github.com/sagernet/sing-tun v0.1.1 h1:2Hg3GAyJWzQ7Ua1j74dE+mI06vaqSBO9yD4tkTjggn4=
|
||||
github.com/sagernet/sing-tun v0.1.1/go.mod h1:WzW/SkT+Nh9uJn/FIYUE2YJHYuPwfbh8sATOzU9QDGw=
|
||||
github.com/sagernet/sing-vmess v0.1.1 h1:WMdkJcc3icIqpDQZGQ7X+jfLilooIZ0zAaC0qeQTWFU=
|
||||
github.com/sagernet/sing-vmess v0.1.1/go.mod h1:COSSEmy19vMWOTEKIUSDiTEyx6yBfTYIzekDlCMow+Q=
|
||||
github.com/sagernet/sing-vmess v0.1.1-0.20230207064843-983dde690564 h1:+CFee8wEc79nFDBV8tDm2yKPrAXb5Mrf2Q5kM2Bb/xo=
|
||||
github.com/sagernet/sing-vmess v0.1.1-0.20230207064843-983dde690564/go.mod h1:9KkmnQzTL4Gvv8U2TRAH2BOITCGsGPpHtUPP5sxn5sY=
|
||||
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 h1:5VBIbVw9q7aKbrFdT83mjkyvQ+VaRsQ6yflTepfln38=
|
||||
github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8=
|
||||
github.com/sagernet/tfo-go v0.0.0-20230207095944-549363a7327d h1:trP/l6ZPWvQ/5Gv99Z7/t/v8iYy06akDMejxW1sznUk=
|
||||
github.com/sagernet/tfo-go v0.0.0-20230207095944-549363a7327d/go.mod h1:jk6Ii8Y3En+j2KQDLgdgQGwb3M6y7EL567jFnGYhN9g=
|
||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e h1:7uw2njHFGE+VpWamge6o56j2RWk4omF6uLKKxMmcWvs=
|
||||
github.com/sagernet/websocket v0.0.0-20220913015213-615516348b4e/go.mod h1:45TUl8+gH4SIKr4ykREbxKWTxkDlSzFENzctB1dVRRY=
|
||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c h1:vK2wyt9aWYHHvNLWniwijBu/n4pySypiKRhN32u/JGo=
|
||||
github.com/sagernet/wireguard-go v0.0.0-20221116151939-c99467f53f2c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
|
||||
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
@@ -173,18 +157,19 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/u-root/uio v0.0.0-20221213070652-c3537552635f h1:dpx1PHxYqAnXzbryJrWP1NQLzEjwcVgFLhkknuFQ7ww=
|
||||
github.com/u-root/uio v0.0.0-20221213070652-c3537552635f/go.mod h1:IogEAUBXDEwX7oR/BMmCctShYs80ql4hF0ySdzGxf7E=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg=
|
||||
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
@@ -195,100 +180,84 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i
|
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||
go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab h1:+yW1yrZ09EYNu1spCUOHBBNRbrLnfmutwyhbhCv3b6Q=
|
||||
go4.org/netipx v0.0.0-20220925034521-797b0c90d8ab/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc=
|
||||
go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s=
|
||||
go4.org/netipx v0.0.0-20230125063823-8449b0a6169f/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.4.0 h1:UVQgzMY87xqpKNgb+kDsll2Igd33HszWHFLmpaRMq/8=
|
||||
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15 h1:5oN1Pz/eDhCpbMbLstvIPa0b/BEQo6g6nwV3pLjfM6w=
|
||||
golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
||||
golang.org/x/exp v0.0.0-20230105202349-8879d0199aa3 h1:fJwx88sMf5RXwDwziL0/Mn9Wqs+efMSo/RYcL+37W9c=
|
||||
golang.org/x/exp v0.0.0-20230105202349-8879d0199aa3/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI=
|
||||
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
@@ -298,56 +267,25 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f h1:YORWxaStkWBnWgELOHTmDrqNlFXuVGEbhwbB5iK94bQ=
|
||||
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
|
||||
google.golang.org/grpc v1.51.0 h1:E1eGv1FTqoLIdnBCZufiSHgKjlqG6fKFf6pPWtMTh8U=
|
||||
google.golang.org/grpc v1.51.0/go.mod h1:wgNDFcnuBGmxLKI/qn4T+m5BtEBYXJPvibbUPsAIPww=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w=
|
||||
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM=
|
||||
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
|
||||
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4=
|
||||
gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
||||
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
||||
|
||||
@@ -11,8 +11,7 @@ import (
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
"github.com/database64128/tfo-go/v2"
|
||||
"github.com/sagernet/tfo-go"
|
||||
)
|
||||
|
||||
func (a *myInboundAdapter) ListenTCP() (net.Listener, error) {
|
||||
|
||||
@@ -18,7 +18,13 @@ import (
|
||||
func (a *myInboundAdapter) ListenUDP() (net.PacketConn, error) {
|
||||
bindAddr := M.SocksaddrFrom(netip.Addr(a.listenOptions.Listen), a.listenOptions.ListenPort)
|
||||
var lc net.ListenConfig
|
||||
if !a.listenOptions.UDPFragment {
|
||||
var udpFragment bool
|
||||
if a.listenOptions.UDPFragment != nil {
|
||||
udpFragment = *a.listenOptions.UDPFragment
|
||||
} else {
|
||||
udpFragment = a.listenOptions.UDPFragmentDefault
|
||||
}
|
||||
if !udpFragment {
|
||||
lc.Control = control.Append(lc.Control, control.DisableUDPFragment())
|
||||
}
|
||||
udpConn, err := lc.ListenPacket(a.ctx, M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.String())
|
||||
|
||||
@@ -25,6 +25,7 @@ type Direct struct {
|
||||
}
|
||||
|
||||
func NewDirect(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.DirectInboundOptions) *Direct {
|
||||
options.UDPFragmentDefault = true
|
||||
inbound := &Direct{
|
||||
myInboundAdapter: myInboundAdapter{
|
||||
protocol: C.TypeDirect,
|
||||
|
||||
@@ -43,6 +43,7 @@ type Hysteria struct {
|
||||
}
|
||||
|
||||
func NewHysteria(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.HysteriaInboundOptions) (*Hysteria, error) {
|
||||
options.UDPFragmentDefault = true
|
||||
quicConfig := &quic.Config{
|
||||
InitialStreamReceiveWindow: options.ReceiveWindowConn,
|
||||
MaxStreamReceiveWindow: options.ReceiveWindowConn,
|
||||
|
||||
@@ -137,14 +137,13 @@ func (n *Naive) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
return
|
||||
}
|
||||
var authOk bool
|
||||
var userName string
|
||||
authorization := request.Header.Get("Proxy-Authorization")
|
||||
if strings.HasPrefix(authorization, "BASIC ") || strings.HasPrefix(authorization, "Basic ") {
|
||||
userPassword, _ := base64.URLEncoding.DecodeString(authorization[6:])
|
||||
userPswdArr := strings.SplitN(string(userPassword), ":", 2)
|
||||
userName = userPswdArr[0]
|
||||
authOk = n.authenticator.Verify(userPswdArr[0], userPswdArr[1])
|
||||
if authOk {
|
||||
ctx = auth.ContextWithUser(ctx, userPswdArr[0])
|
||||
}
|
||||
}
|
||||
if !authOk {
|
||||
rejectHTTP(writer, http.StatusProxyAuthRequired)
|
||||
@@ -168,17 +167,29 @@ func (n *Naive) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
n.badRequest(ctx, request, E.New("hijack failed"))
|
||||
return
|
||||
}
|
||||
n.newConnection(ctx, &naiveH1Conn{Conn: conn}, source, destination)
|
||||
n.newConnection(ctx, &naiveH1Conn{Conn: conn}, userName, source, destination)
|
||||
} else {
|
||||
n.newConnection(ctx, &naiveH2Conn{reader: request.Body, writer: writer, flusher: writer.(http.Flusher)}, source, destination)
|
||||
n.newConnection(ctx, &naiveH2Conn{reader: request.Body, writer: writer, flusher: writer.(http.Flusher)}, userName, source, destination)
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Naive) newConnection(ctx context.Context, conn net.Conn, source, destination M.Socksaddr) {
|
||||
n.routeTCP(ctx, conn, n.createMetadata(conn, adapter.InboundContext{
|
||||
func (n *Naive) newConnection(ctx context.Context, conn net.Conn, userName string, source, destination M.Socksaddr) {
|
||||
if userName != "" {
|
||||
n.logger.InfoContext(ctx, "[", userName, "] inbound connection from ", source)
|
||||
n.logger.InfoContext(ctx, "[", userName, "] inbound connection to ", destination)
|
||||
} else {
|
||||
n.logger.InfoContext(ctx, "inbound connection from ", source)
|
||||
n.logger.InfoContext(ctx, "inbound connection to ", destination)
|
||||
}
|
||||
hErr := n.router.RouteConnection(ctx, conn, n.createMetadata(conn, adapter.InboundContext{
|
||||
Source: source,
|
||||
Destination: destination,
|
||||
User: userName,
|
||||
}))
|
||||
if hErr != nil {
|
||||
conn.Close()
|
||||
n.NewError(ctx, E.Cause(hErr, "process connection from ", source))
|
||||
}
|
||||
}
|
||||
|
||||
func (n *Naive) badRequest(ctx context.Context, request *http.Request, err error) {
|
||||
|
||||
5
include/dhcp.go
Normal file
5
include/dhcp.go
Normal file
@@ -0,0 +1,5 @@
|
||||
//go:build with_dhcp
|
||||
|
||||
package include
|
||||
|
||||
import _ "github.com/sagernet/sing-box/transport/dhcp"
|
||||
18
include/dhcp_stub.go
Normal file
18
include/dhcp_stub.go
Normal file
@@ -0,0 +1,18 @@
|
||||
//go:build !with_dhcp
|
||||
|
||||
package include
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sagernet/sing-dns"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dns.RegisterTransport([]string{"dhcp"}, func(ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
|
||||
return nil, E.New(`DHCP is not included in this build, rebuild with -tags with_dhcp`)
|
||||
})
|
||||
}
|
||||
@@ -77,32 +77,33 @@ func (r *DNSRule) UnmarshalJSON(bytes []byte) error {
|
||||
}
|
||||
|
||||
type DefaultDNSRule struct {
|
||||
Inbound Listable[string] `json:"inbound,omitempty"`
|
||||
IPVersion int `json:"ip_version,omitempty"`
|
||||
Network string `json:"network,omitempty"`
|
||||
AuthUser Listable[string] `json:"auth_user,omitempty"`
|
||||
Protocol Listable[string] `json:"protocol,omitempty"`
|
||||
Domain Listable[string] `json:"domain,omitempty"`
|
||||
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
||||
DomainKeyword Listable[string] `json:"domain_keyword,omitempty"`
|
||||
DomainRegex Listable[string] `json:"domain_regex,omitempty"`
|
||||
Geosite Listable[string] `json:"geosite,omitempty"`
|
||||
SourceGeoIP Listable[string] `json:"source_geoip,omitempty"`
|
||||
SourceIPCIDR Listable[string] `json:"source_ip_cidr,omitempty"`
|
||||
SourcePort Listable[uint16] `json:"source_port,omitempty"`
|
||||
SourcePortRange Listable[string] `json:"source_port_range,omitempty"`
|
||||
Port Listable[uint16] `json:"port,omitempty"`
|
||||
PortRange Listable[string] `json:"port_range,omitempty"`
|
||||
ProcessName Listable[string] `json:"process_name,omitempty"`
|
||||
ProcessPath Listable[string] `json:"process_path,omitempty"`
|
||||
PackageName Listable[string] `json:"package_name,omitempty"`
|
||||
User Listable[string] `json:"user,omitempty"`
|
||||
UserID Listable[int32] `json:"user_id,omitempty"`
|
||||
Outbound Listable[string] `json:"outbound,omitempty"`
|
||||
ClashMode string `json:"clash_mode,omitempty"`
|
||||
Invert bool `json:"invert,omitempty"`
|
||||
Server string `json:"server,omitempty"`
|
||||
DisableCache bool `json:"disable_cache,omitempty"`
|
||||
Inbound Listable[string] `json:"inbound,omitempty"`
|
||||
IPVersion int `json:"ip_version,omitempty"`
|
||||
QueryType Listable[DNSQueryType] `json:"query_type,omitempty"`
|
||||
Network string `json:"network,omitempty"`
|
||||
AuthUser Listable[string] `json:"auth_user,omitempty"`
|
||||
Protocol Listable[string] `json:"protocol,omitempty"`
|
||||
Domain Listable[string] `json:"domain,omitempty"`
|
||||
DomainSuffix Listable[string] `json:"domain_suffix,omitempty"`
|
||||
DomainKeyword Listable[string] `json:"domain_keyword,omitempty"`
|
||||
DomainRegex Listable[string] `json:"domain_regex,omitempty"`
|
||||
Geosite Listable[string] `json:"geosite,omitempty"`
|
||||
SourceGeoIP Listable[string] `json:"source_geoip,omitempty"`
|
||||
SourceIPCIDR Listable[string] `json:"source_ip_cidr,omitempty"`
|
||||
SourcePort Listable[uint16] `json:"source_port,omitempty"`
|
||||
SourcePortRange Listable[string] `json:"source_port_range,omitempty"`
|
||||
Port Listable[uint16] `json:"port,omitempty"`
|
||||
PortRange Listable[string] `json:"port_range,omitempty"`
|
||||
ProcessName Listable[string] `json:"process_name,omitempty"`
|
||||
ProcessPath Listable[string] `json:"process_path,omitempty"`
|
||||
PackageName Listable[string] `json:"package_name,omitempty"`
|
||||
User Listable[string] `json:"user,omitempty"`
|
||||
UserID Listable[int32] `json:"user_id,omitempty"`
|
||||
Outbound Listable[string] `json:"outbound,omitempty"`
|
||||
ClashMode string `json:"clash_mode,omitempty"`
|
||||
Invert bool `json:"invert,omitempty"`
|
||||
Server string `json:"server,omitempty"`
|
||||
DisableCache bool `json:"disable_cache,omitempty"`
|
||||
}
|
||||
|
||||
func (r DefaultDNSRule) IsValid() bool {
|
||||
|
||||
@@ -115,7 +115,8 @@ type ListenOptions struct {
|
||||
Listen ListenAddress `json:"listen"`
|
||||
ListenPort uint16 `json:"listen_port,omitempty"`
|
||||
TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
|
||||
UDPFragment bool `json:"udp_fragment,omitempty"`
|
||||
UDPFragment *bool `json:"udp_fragment,omitempty"`
|
||||
UDPFragmentDefault bool `json:"-"`
|
||||
UDPTimeout int64 `json:"udp_timeout,omitempty"`
|
||||
ProxyProtocol bool `json:"proxy_protocol,omitempty"`
|
||||
ProxyProtocolAcceptNoHeader bool `json:"proxy_protocol_accept_no_header,omitempty"`
|
||||
|
||||
@@ -8,6 +8,7 @@ type SSHOutboundOptions struct {
|
||||
PrivateKey string `json:"private_key,omitempty"`
|
||||
PrivateKeyPath string `json:"private_key_path,omitempty"`
|
||||
PrivateKeyPassphrase string `json:"private_key_passphrase,omitempty"`
|
||||
HostKey Listable[string] `json:"host_key,omitempty"`
|
||||
HostKeyAlgorithms Listable[string] `json:"host_key_algorithms,omitempty"`
|
||||
ClientVersion string `json:"client_version,omitempty"`
|
||||
}
|
||||
|
||||
@@ -8,7 +8,10 @@ import (
|
||||
"github.com/sagernet/sing-box/common/json"
|
||||
"github.com/sagernet/sing-dns"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
F "github.com/sagernet/sing/common/format"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
|
||||
mDNS "github.com/miekg/dns"
|
||||
)
|
||||
|
||||
type ListenAddress netip.Addr
|
||||
@@ -187,3 +190,40 @@ func (p *ListenPrefix) UnmarshalJSON(bytes []byte) error {
|
||||
func (p ListenPrefix) Build() netip.Prefix {
|
||||
return netip.Prefix(p)
|
||||
}
|
||||
|
||||
type DNSQueryType uint16
|
||||
|
||||
func (t DNSQueryType) MarshalJSON() ([]byte, error) {
|
||||
typeName, loaded := mDNS.TypeToString[uint16(t)]
|
||||
if loaded {
|
||||
return json.Marshal(typeName)
|
||||
}
|
||||
return json.Marshal(uint16(t))
|
||||
}
|
||||
|
||||
func (t *DNSQueryType) UnmarshalJSON(bytes []byte) error {
|
||||
var valueNumber uint16
|
||||
err := json.Unmarshal(bytes, &valueNumber)
|
||||
if err == nil {
|
||||
*t = DNSQueryType(valueNumber)
|
||||
return nil
|
||||
}
|
||||
var valueString string
|
||||
err = json.Unmarshal(bytes, &valueString)
|
||||
if err == nil {
|
||||
queryType, loaded := mDNS.StringToType[valueString]
|
||||
if loaded {
|
||||
*t = DNSQueryType(queryType)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return E.New("unknown DNS query type: ", string(bytes))
|
||||
}
|
||||
|
||||
func DNSQueryTypeToString(queryType uint16) string {
|
||||
typeName, loaded := mDNS.TypeToString[queryType]
|
||||
if loaded {
|
||||
return typeName
|
||||
}
|
||||
return F.ToString(queryType)
|
||||
}
|
||||
|
||||
@@ -9,4 +9,5 @@ type V2RayStatsServiceOptions struct {
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Inbounds []string `json:"inbounds,omitempty"`
|
||||
Outbounds []string `json:"outbounds,omitempty"`
|
||||
Users []string `json:"users,omitempty"`
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package outbound
|
||||
import (
|
||||
std_bufio "bufio"
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"math/rand"
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package outbound
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"math/rand"
|
||||
"net"
|
||||
"os"
|
||||
@@ -32,6 +34,7 @@ type SSH struct {
|
||||
dialer N.Dialer
|
||||
serverAddr M.Socksaddr
|
||||
user string
|
||||
hostKey []ssh.PublicKey
|
||||
hostKeyAlgorithms []string
|
||||
clientVersion string
|
||||
authMethod []ssh.AuthMethod
|
||||
@@ -91,6 +94,15 @@ func NewSSH(ctx context.Context, router adapter.Router, logger log.ContextLogger
|
||||
}
|
||||
outbound.authMethod = append(outbound.authMethod, ssh.PublicKeys(signer))
|
||||
}
|
||||
if len(options.HostKey) > 0 {
|
||||
for _, hostKey := range options.HostKey {
|
||||
key, _, _, _, err := ssh.ParseAuthorizedKey([]byte(hostKey))
|
||||
if err != nil {
|
||||
return nil, E.New("parse host key ", key)
|
||||
}
|
||||
outbound.hostKey = append(outbound.hostKey, key)
|
||||
}
|
||||
}
|
||||
return outbound, nil
|
||||
}
|
||||
|
||||
@@ -126,7 +138,16 @@ func (s *SSH) connect() (*ssh.Client, error) {
|
||||
ClientVersion: s.clientVersion,
|
||||
HostKeyAlgorithms: s.hostKeyAlgorithms,
|
||||
HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
|
||||
return nil
|
||||
if len(s.hostKey) == 0 {
|
||||
return nil
|
||||
}
|
||||
serverKey := key.Marshal()
|
||||
for _, hostKey := range s.hostKey {
|
||||
if bytes.Equal(serverKey, hostKey.Marshal()) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return E.New("host key mismatch, server send ", key.Type(), " ", base64.StdEncoding.EncodeToString(serverKey))
|
||||
},
|
||||
}
|
||||
clientConn, chans, reqs, err := ssh.NewClientConn(conn, s.serverAddr.Addr.String(), config)
|
||||
|
||||
@@ -159,6 +159,7 @@ func NewRouter(ctx context.Context, logFactory log.Factory, options option.Route
|
||||
transportTags[i] = tag
|
||||
transportTagMap[tag] = true
|
||||
}
|
||||
ctx = adapter.ContextWithRouter(ctx, router)
|
||||
for {
|
||||
lastLen := len(dummyTransportMap)
|
||||
for i, server := range dnsOptions.Servers {
|
||||
@@ -173,13 +174,13 @@ func NewRouter(ctx context.Context, logFactory log.Factory, options option.Route
|
||||
detour = dialer.NewDetour(router, server.Detour)
|
||||
}
|
||||
switch server.Address {
|
||||
case "local", "rcode":
|
||||
case "local":
|
||||
default:
|
||||
serverURL, err := url.Parse(server.Address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
serverURL, _ := url.Parse(server.Address)
|
||||
var serverAddress string
|
||||
if serverURL != nil {
|
||||
serverAddress = serverURL.Hostname()
|
||||
}
|
||||
serverAddress := serverURL.Hostname()
|
||||
if serverAddress == "" {
|
||||
serverAddress = server.Address
|
||||
}
|
||||
@@ -193,11 +194,15 @@ func NewRouter(ctx context.Context, logFactory log.Factory, options option.Route
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
} else if notIpAddress != nil && (serverURL == nil || serverURL.Scheme != "rcode") {
|
||||
return nil, E.New("parse dns server[", tag, "]: missing address_resolver")
|
||||
} else if notIpAddress != nil {
|
||||
switch serverURL.Scheme {
|
||||
case "rcode", "dhcp":
|
||||
default:
|
||||
return nil, E.New("parse dns server[", tag, "]: missing address_resolver")
|
||||
}
|
||||
}
|
||||
}
|
||||
transport, err := dns.CreateTransport(ctx, logFactory.NewLogger(F.ToString("dns/transport[", i, "]")), detour, server.Address)
|
||||
transport, err := dns.CreateTransport(ctx, logFactory.NewLogger(F.ToString("dns/transport[", tag, "]")), detour, server.Address)
|
||||
if err != nil {
|
||||
return nil, E.Cause(err, "parse dns server[", tag, "]")
|
||||
}
|
||||
@@ -392,14 +397,20 @@ func (r *Router) Start() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, rule := range r.rules {
|
||||
err := rule.Start()
|
||||
if r.interfaceMonitor != nil {
|
||||
err := r.interfaceMonitor.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, rule := range r.dnsRules {
|
||||
err := rule.Start()
|
||||
if r.networkMonitor != nil {
|
||||
err := r.networkMonitor.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if r.packageManager != nil {
|
||||
err := r.packageManager.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -424,22 +435,22 @@ func (r *Router) Start() error {
|
||||
r.geositeCache = nil
|
||||
r.geositeReader = nil
|
||||
}
|
||||
if r.interfaceMonitor != nil {
|
||||
err := r.interfaceMonitor.Start()
|
||||
for i, rule := range r.rules {
|
||||
err := rule.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
return E.Cause(err, "initialize rule[", i, "]")
|
||||
}
|
||||
}
|
||||
if r.networkMonitor != nil {
|
||||
err := r.networkMonitor.Start()
|
||||
for i, rule := range r.dnsRules {
|
||||
err := rule.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
return E.Cause(err, "initialize DNS rule[", i, "]")
|
||||
}
|
||||
}
|
||||
if r.packageManager != nil {
|
||||
err := r.packageManager.Start()
|
||||
for i, transport := range r.transports {
|
||||
err := transport.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
return E.Cause(err, "initialize DNS server[", i, "]")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -458,6 +469,12 @@ func (r *Router) Close() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, transport := range r.transports {
|
||||
err := transport.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return common.Close(
|
||||
common.PtrOrNil(r.geoIPReader),
|
||||
r.interfaceMonitor,
|
||||
@@ -583,7 +600,7 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||
}
|
||||
if r.v2rayServer != nil {
|
||||
if statsService := r.v2rayServer.StatsService(); statsService != nil {
|
||||
conn = statsService.RoutedConnection(metadata.Inbound, detour.Tag(), conn)
|
||||
conn = statsService.RoutedConnection(metadata.Inbound, detour.Tag(), metadata.User, conn)
|
||||
}
|
||||
}
|
||||
return detour.NewConnection(ctx, conn, metadata)
|
||||
@@ -661,7 +678,7 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||
}
|
||||
if r.v2rayServer != nil {
|
||||
if statsService := r.v2rayServer.StatsService(); statsService != nil {
|
||||
conn = statsService.RoutedPacketConnection(metadata.Inbound, detour.Tag(), conn)
|
||||
conn = statsService.RoutedPacketConnection(metadata.Inbound, detour.Tag(), metadata.User, conn)
|
||||
}
|
||||
}
|
||||
return detour.NewPacketConnection(ctx, conn, metadata)
|
||||
|
||||
@@ -50,7 +50,8 @@ func (r *Router) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, er
|
||||
}
|
||||
ctx, metadata := adapter.AppendContext(ctx)
|
||||
if len(message.Question) > 0 {
|
||||
switch message.Question[0].Qtype {
|
||||
metadata.QueryType = message.Question[0].Qtype
|
||||
switch metadata.QueryType {
|
||||
case mDNS.TypeA:
|
||||
metadata.IPVersion = 4
|
||||
case mDNS.TypeAAAA:
|
||||
|
||||
@@ -71,6 +71,11 @@ func NewDefaultDNSRule(router adapter.Router, logger log.ContextLogger, options
|
||||
return nil, E.New("invalid ip version: ", options.IPVersion)
|
||||
}
|
||||
}
|
||||
if len(options.QueryType) > 0 {
|
||||
item := NewQueryTypeItem(options.QueryType)
|
||||
rule.items = append(rule.items, item)
|
||||
rule.allItems = append(rule.allItems, item)
|
||||
}
|
||||
if options.Network != "" {
|
||||
switch options.Network {
|
||||
case N.NetworkTCP, N.NetworkUDP:
|
||||
|
||||
@@ -53,7 +53,7 @@ func (r *DomainItem) Match(metadata *adapter.InboundContext) bool {
|
||||
if domainHost == "" {
|
||||
return false
|
||||
}
|
||||
return r.matcher.Match(domainHost)
|
||||
return r.matcher.Match(strings.ToLower(domainHost))
|
||||
}
|
||||
|
||||
func (r *DomainItem) String() string {
|
||||
|
||||
@@ -26,6 +26,7 @@ func (r *DomainKeywordItem) Match(metadata *adapter.InboundContext) bool {
|
||||
if domainHost == "" {
|
||||
return false
|
||||
}
|
||||
domainHost = strings.ToLower(domainHost)
|
||||
for _, keyword := range r.keywords {
|
||||
if strings.Contains(domainHost, keyword) {
|
||||
return true
|
||||
|
||||
@@ -47,6 +47,7 @@ func (r *DomainRegexItem) Match(metadata *adapter.InboundContext) bool {
|
||||
if domainHost == "" {
|
||||
return false
|
||||
}
|
||||
domainHost = strings.ToLower(domainHost)
|
||||
for _, matcher := range r.matchers {
|
||||
if matcher.MatchString(domainHost) {
|
||||
return true
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
var _ RuleItem = (*GeoIPItem)(nil)
|
||||
@@ -32,29 +34,50 @@ func NewGeoIPItem(router adapter.Router, logger log.ContextLogger, isSource bool
|
||||
}
|
||||
|
||||
func (r *GeoIPItem) Match(metadata *adapter.InboundContext) bool {
|
||||
var geoipCode string
|
||||
if r.isSource && metadata.SourceGeoIPCode != "" {
|
||||
geoipCode = metadata.SourceGeoIPCode
|
||||
} else if !r.isSource && metadata.GeoIPCode != "" {
|
||||
geoipCode = metadata.GeoIPCode
|
||||
}
|
||||
if geoipCode != "" {
|
||||
return r.codeMap[geoipCode]
|
||||
}
|
||||
var destination netip.Addr
|
||||
if r.isSource {
|
||||
destination = metadata.Source.Addr
|
||||
} else {
|
||||
destination = metadata.Destination.Addr
|
||||
}
|
||||
if destination.IsValid() {
|
||||
return r.match(metadata, destination)
|
||||
}
|
||||
for _, destinationAddress := range metadata.DestinationAddresses {
|
||||
if r.match(metadata, destinationAddress) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *GeoIPItem) match(metadata *adapter.InboundContext, destination netip.Addr) bool {
|
||||
var geoipCode string
|
||||
geoReader := r.router.GeoIPReader()
|
||||
if geoReader == nil {
|
||||
if geoReader != nil {
|
||||
geoipCode = geoReader.Lookup(destination)
|
||||
}
|
||||
if geoipCode == "" && !N.IsPublicAddr(destination) {
|
||||
geoipCode = "private"
|
||||
}
|
||||
if geoipCode == "" {
|
||||
return false
|
||||
}
|
||||
if r.isSource {
|
||||
if metadata.SourceGeoIPCode == "" {
|
||||
metadata.SourceGeoIPCode = geoReader.Lookup(metadata.Source.Addr)
|
||||
}
|
||||
return r.codeMap[metadata.SourceGeoIPCode]
|
||||
metadata.SourceGeoIPCode = geoipCode
|
||||
} else {
|
||||
if metadata.Destination.IsIP() {
|
||||
if metadata.GeoIPCode == "" {
|
||||
metadata.GeoIPCode = geoReader.Lookup(metadata.Destination.Addr)
|
||||
}
|
||||
return r.codeMap[metadata.GeoIPCode]
|
||||
}
|
||||
for _, address := range metadata.DestinationAddresses {
|
||||
if r.codeMap[geoReader.Lookup(address)] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
metadata.GeoIPCode = geoipCode
|
||||
}
|
||||
return r.codeMap[geoipCode]
|
||||
}
|
||||
|
||||
func (r *GeoIPItem) String() string {
|
||||
|
||||
47
route/rule_query_type.go
Normal file
47
route/rule_query_type.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package route
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common"
|
||||
)
|
||||
|
||||
var _ RuleItem = (*QueryTypeItem)(nil)
|
||||
|
||||
type QueryTypeItem struct {
|
||||
typeList []uint16
|
||||
typeMap map[uint16]bool
|
||||
}
|
||||
|
||||
func NewQueryTypeItem(typeList []option.DNSQueryType) *QueryTypeItem {
|
||||
rule := &QueryTypeItem{
|
||||
typeList: common.Map(typeList, func(it option.DNSQueryType) uint16 {
|
||||
return uint16(it)
|
||||
}),
|
||||
typeMap: make(map[uint16]bool),
|
||||
}
|
||||
for _, userId := range rule.typeList {
|
||||
rule.typeMap[userId] = true
|
||||
}
|
||||
return rule
|
||||
}
|
||||
|
||||
func (r *QueryTypeItem) Match(metadata *adapter.InboundContext) bool {
|
||||
if metadata.QueryType == 0 {
|
||||
return false
|
||||
}
|
||||
return r.typeMap[metadata.QueryType]
|
||||
}
|
||||
|
||||
func (r *QueryTypeItem) String() string {
|
||||
var description string
|
||||
pLen := len(r.typeList)
|
||||
if pLen == 1 {
|
||||
description = "query_type=" + option.DNSQueryTypeToString(r.typeList[0])
|
||||
} else {
|
||||
description = "query_type=[" + strings.Join(common.Map(r.typeList, option.DNSQueryTypeToString), " ") + "]"
|
||||
}
|
||||
return description
|
||||
}
|
||||
262
transport/dhcp/server.go
Normal file
262
transport/dhcp/server.go
Normal file
@@ -0,0 +1,262 @@
|
||||
package dhcp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/dialer"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-dns"
|
||||
"github.com/sagernet/sing-tun"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/control"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/sing/common/task"
|
||||
"github.com/sagernet/sing/common/x/list"
|
||||
|
||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||
mDNS "github.com/miekg/dns"
|
||||
)
|
||||
|
||||
func init() {
|
||||
dns.RegisterTransport([]string{"dhcp"}, NewTransport)
|
||||
}
|
||||
|
||||
type Transport struct {
|
||||
ctx context.Context
|
||||
router adapter.Router
|
||||
logger logger.Logger
|
||||
interfaceName string
|
||||
autoInterface bool
|
||||
interfaceCallback *list.Element[tun.DefaultInterfaceUpdateCallback]
|
||||
transports []dns.Transport
|
||||
updateAccess sync.Mutex
|
||||
updatedAt time.Time
|
||||
}
|
||||
|
||||
func NewTransport(ctx context.Context, logger logger.ContextLogger, dialer N.Dialer, link string) (dns.Transport, error) {
|
||||
linkURL, err := url.Parse(link)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if linkURL.Host == "" {
|
||||
return nil, E.New("missing interface name for DHCP")
|
||||
}
|
||||
router := adapter.RouterFromContext(ctx)
|
||||
if router == nil {
|
||||
return nil, E.New("missing router in context")
|
||||
}
|
||||
transport := &Transport{
|
||||
ctx: ctx,
|
||||
router: router,
|
||||
logger: logger,
|
||||
interfaceName: linkURL.Host,
|
||||
autoInterface: linkURL.Host == "auto",
|
||||
}
|
||||
return transport, nil
|
||||
}
|
||||
|
||||
func (t *Transport) Start() error {
|
||||
err := t.fetchServers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if t.autoInterface {
|
||||
t.interfaceCallback = t.router.InterfaceMonitor().RegisterCallback(t.interfaceUpdated)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Transport) Close() error {
|
||||
if t.interfaceCallback != nil {
|
||||
t.router.InterfaceMonitor().UnregisterCallback(t.interfaceCallback)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Transport) Raw() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||
err := t.fetchServers()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(t.transports) == 0 {
|
||||
return nil, E.New("dhcp: empty DNS servers from response")
|
||||
}
|
||||
|
||||
var response *mDNS.Msg
|
||||
for _, transport := range t.transports {
|
||||
response, err = transport.Exchange(ctx, message)
|
||||
if err == nil {
|
||||
return response, nil
|
||||
}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (t *Transport) fetchInterface() (*net.Interface, error) {
|
||||
interfaceName := t.interfaceName
|
||||
if t.autoInterface {
|
||||
if t.router.NetworkMonitor() == nil {
|
||||
return nil, E.New("missing monitor for auto DHCP, set route.auto_detect_interface")
|
||||
}
|
||||
interfaceName = t.router.InterfaceMonitor().DefaultInterfaceName(netip.Addr{})
|
||||
}
|
||||
if interfaceName == "" {
|
||||
return nil, E.New("missing default interface")
|
||||
}
|
||||
return net.InterfaceByName(interfaceName)
|
||||
}
|
||||
|
||||
func (t *Transport) fetchServers() error {
|
||||
if time.Since(t.updatedAt) < C.DHCPTTL {
|
||||
return nil
|
||||
}
|
||||
t.updateAccess.Lock()
|
||||
defer t.updateAccess.Unlock()
|
||||
if time.Since(t.updatedAt) < C.DHCPTTL {
|
||||
return nil
|
||||
}
|
||||
return t.updateServers()
|
||||
}
|
||||
|
||||
func (t *Transport) updateServers() error {
|
||||
iface, err := t.fetchInterface()
|
||||
if err != nil {
|
||||
return E.Cause(err, "dhcp: prepare interface")
|
||||
}
|
||||
|
||||
t.logger.Info("dhcp: query DNS servers on ", iface.Name)
|
||||
fetchCtx, cancel := context.WithTimeout(t.ctx, C.DHCPTimeout)
|
||||
err = t.fetchServers0(fetchCtx, iface)
|
||||
cancel()
|
||||
if err != nil {
|
||||
return err
|
||||
} else if len(t.transports) == 0 {
|
||||
return E.New("dhcp: empty DNS servers response")
|
||||
} else {
|
||||
t.updatedAt = time.Now()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Transport) interfaceUpdated(int) error {
|
||||
return t.updateServers()
|
||||
}
|
||||
|
||||
func (t *Transport) fetchServers0(ctx context.Context, iface *net.Interface) error {
|
||||
var listener net.ListenConfig
|
||||
listener.Control = control.Append(listener.Control, control.BindToInterfaceFunc(t.router.InterfaceFinder(), func(network string, address string) (interfaceName string, interfaceIndex int) {
|
||||
return iface.Name, iface.Index
|
||||
}))
|
||||
listener.Control = control.Append(listener.Control, control.ReuseAddr())
|
||||
packetConn, err := listener.ListenPacket(t.ctx, "udp4", "0.0.0.0:68")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer packetConn.Close()
|
||||
|
||||
discovery, err := dhcpv4.NewDiscovery(iface.HardwareAddr, dhcpv4.WithBroadcast(true), dhcpv4.WithRequestedOptions(dhcpv4.OptionDomainNameServer))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = packetConn.WriteTo(discovery.ToBytes(), &net.UDPAddr{IP: net.IPv4bcast, Port: 67})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var group task.Group
|
||||
group.Append0(func(ctx context.Context) error {
|
||||
return t.fetchServersResponse(iface, packetConn, discovery.TransactionID)
|
||||
})
|
||||
group.Cleanup(func() {
|
||||
packetConn.Close()
|
||||
})
|
||||
return group.Run(ctx)
|
||||
}
|
||||
|
||||
func (t *Transport) fetchServersResponse(iface *net.Interface, packetConn net.PacketConn, transactionID dhcpv4.TransactionID) error {
|
||||
_buffer := buf.StackNewSize(dhcpv4.MaxMessageSize)
|
||||
defer common.KeepAlive(_buffer)
|
||||
buffer := common.Dup(_buffer)
|
||||
defer buffer.Release()
|
||||
|
||||
for {
|
||||
_, _, err := buffer.ReadPacketFrom(packetConn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dhcpPacket, err := dhcpv4.FromBytes(buffer.Bytes())
|
||||
if err != nil {
|
||||
t.logger.Trace("dhcp: parse DHCP response: ", err)
|
||||
return err
|
||||
}
|
||||
|
||||
if dhcpPacket.MessageType() != dhcpv4.MessageTypeOffer {
|
||||
t.logger.Trace("dhcp: expected OFFER response, but got ", dhcpPacket.MessageType())
|
||||
continue
|
||||
}
|
||||
|
||||
if dhcpPacket.TransactionID != transactionID {
|
||||
t.logger.Trace("dhcp: expected transaction ID ", transactionID, ", but got ", dhcpPacket.TransactionID)
|
||||
continue
|
||||
}
|
||||
|
||||
dns := dhcpPacket.DNS()
|
||||
if len(dns) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var addrs []netip.Addr
|
||||
for _, ip := range dns {
|
||||
addr, _ := netip.AddrFromSlice(ip)
|
||||
addrs = append(addrs, addr.Unmap())
|
||||
}
|
||||
return t.recreateServers(iface, addrs)
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Transport) recreateServers(iface *net.Interface, serverAddrs []netip.Addr) error {
|
||||
if len(serverAddrs) > 0 {
|
||||
t.logger.Info("dhcp: updated DNS servers from ", iface.Name, ": [", strings.Join(common.Map(serverAddrs, func(it netip.Addr) string {
|
||||
return it.String()
|
||||
}), ","), "]")
|
||||
}
|
||||
|
||||
serverDialer := dialer.NewDefault(t.router, option.DialerOptions{
|
||||
BindInterface: iface.Name,
|
||||
UDPFragmentDefault: true,
|
||||
})
|
||||
var transports []dns.Transport
|
||||
for _, serverAddr := range serverAddrs {
|
||||
serverTransport, err := dns.NewUDPTransport(t.ctx, serverDialer, M.Socksaddr{Addr: serverAddr, Port: 53})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
transports = append(transports, serverTransport)
|
||||
}
|
||||
t.transports = transports
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *Transport) Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error) {
|
||||
return nil, os.ErrInvalid
|
||||
}
|
||||
@@ -117,6 +117,7 @@ func (c *GunConn) WriteBuffer(buffer *buf.Buffer) error {
|
||||
dataLen := buffer.Len()
|
||||
varLen := rw.UVariantLen(uint64(dataLen))
|
||||
header := buffer.ExtendHeader(6 + varLen)
|
||||
header[0] = 0x00
|
||||
binary.BigEndian.PutUint32(header[1:5], uint32(1+varLen+dataLen))
|
||||
header[5] = 0x0A
|
||||
binary.PutUvarint(header[6:], uint64(dataLen))
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/tls"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing-box/transport/v2rayhttp"
|
||||
"github.com/sagernet/sing/common"
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
@@ -87,8 +88,9 @@ func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
writer.WriteHeader(http.StatusOK)
|
||||
var metadata M.Metadata
|
||||
metadata.Source = sHttp.SourceAddress(request)
|
||||
conn := newGunConn(request.Body, writer, writer.(http.Flusher))
|
||||
conn := v2rayhttp.NewHTTP2Wrapper(newGunConn(request.Body, writer, writer.(http.Flusher)))
|
||||
s.handler.NewConnection(request.Context(), conn, metadata)
|
||||
conn.CloseWrapper()
|
||||
}
|
||||
|
||||
func (s *Server) badRequest(request *http.Request, err error) {
|
||||
|
||||
@@ -5,10 +5,14 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/sing-box/common/baderror"
|
||||
"github.com/sagernet/sing/common"
|
||||
"github.com/sagernet/sing/common/buf"
|
||||
"github.com/sagernet/sing/common/bufio"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
)
|
||||
|
||||
type HTTPConn struct {
|
||||
@@ -105,3 +109,43 @@ func (c *ServerHTTPConn) Write(b []byte) (n int, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type HTTP2ConnWrapper struct {
|
||||
N.ExtendedConn
|
||||
access sync.Mutex
|
||||
closed bool
|
||||
}
|
||||
|
||||
func NewHTTP2Wrapper(conn net.Conn) *HTTP2ConnWrapper {
|
||||
return &HTTP2ConnWrapper{
|
||||
ExtendedConn: bufio.NewExtendedConn(conn),
|
||||
}
|
||||
}
|
||||
|
||||
func (w *HTTP2ConnWrapper) Write(p []byte) (n int, err error) {
|
||||
w.access.Lock()
|
||||
defer w.access.Unlock()
|
||||
if w.closed {
|
||||
return 0, net.ErrClosed
|
||||
}
|
||||
return w.ExtendedConn.Write(p)
|
||||
}
|
||||
|
||||
func (w *HTTP2ConnWrapper) WriteBuffer(buffer *buf.Buffer) error {
|
||||
w.access.Lock()
|
||||
defer w.access.Unlock()
|
||||
if w.closed {
|
||||
return net.ErrClosed
|
||||
}
|
||||
return w.ExtendedConn.WriteBuffer(buffer)
|
||||
}
|
||||
|
||||
func (w *HTTP2ConnWrapper) CloseWrapper() {
|
||||
w.access.Lock()
|
||||
defer w.access.Unlock()
|
||||
w.closed = true
|
||||
}
|
||||
|
||||
func (w *HTTP2ConnWrapper) Upstream() any {
|
||||
return w.ExtendedConn
|
||||
}
|
||||
|
||||
@@ -120,11 +120,12 @@ func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
||||
}
|
||||
s.handler.NewConnection(request.Context(), conn, metadata)
|
||||
} else {
|
||||
conn := &ServerHTTPConn{
|
||||
conn := NewHTTP2Wrapper(&ServerHTTPConn{
|
||||
newHTTPConn(request.Body, writer),
|
||||
writer.(http.Flusher),
|
||||
}
|
||||
})
|
||||
s.handler.NewConnection(request.Context(), conn, metadata)
|
||||
conn.CloseWrapper()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -197,10 +197,9 @@ func (w *StackDevice) Events() chan tun.Event {
|
||||
|
||||
func (w *StackDevice) Close() error {
|
||||
select {
|
||||
case <-w.events:
|
||||
case <-w.done:
|
||||
return os.ErrClosed
|
||||
default:
|
||||
close(w.events)
|
||||
}
|
||||
w.stack.Close()
|
||||
for _, endpoint := range w.stack.CleanupEndpoints() {
|
||||
|
||||
@@ -105,11 +105,5 @@ func (w *SystemDevice) Events() chan wgTun.Event {
|
||||
}
|
||||
|
||||
func (w *SystemDevice) Close() error {
|
||||
select {
|
||||
case <-w.events:
|
||||
return os.ErrClosed
|
||||
default:
|
||||
close(w.events)
|
||||
}
|
||||
return w.device.Close()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user