From 36fa23f28f53457f6d21a9125b34f88fc0f5c6a0 Mon Sep 17 00:00:00 2001 From: "github-action[bot]" Date: Sat, 23 Mar 2024 19:27:35 +0100 Subject: [PATCH] Update On Sat Mar 23 19:27:34 CET 2024 --- .github/update.log | 1 + clash-meta/dns/client.go | 13 +- clash-nyanpasu/backend/Cargo.lock | 39 +-- clash-nyanpasu/package.json | 4 +- clash-nyanpasu/pnpm-lock.yaml | 160 ++++++------ hysteria/app/cmd/client.go | 158 +++++++++++- hysteria/app/cmd/client_test.go | 22 ++ hysteria/app/cmd/client_test.yaml | 14 ++ hysteria/app/cmd/server.go | 4 +- hysteria/app/go.mod | 15 +- hysteria/app/go.sum | 33 ++- hysteria/app/internal/tun/log.go | 77 ++++++ hysteria/app/internal/tun/server.go | 230 ++++++++++++++++++ hysteria/core/go.mod | 6 +- hysteria/core/go.sum | 12 +- hysteria/extras/go.mod | 6 +- hysteria/extras/go.sum | 12 +- hysteria/go.work.sum | 17 +- mieru/.github/workflows/ci.yaml | 2 - mieru/README.md | 2 +- mieru/README.zh_CN.md | 2 +- mieru/docs/server-install.md | 4 +- mieru/docs/server-install.zh_CN.md | 4 +- mihomo/dns/client.go | 13 +- openwrt-packages/alist/Makefile | 2 +- .../luci-app-alist/root/etc/init.d/alist | 8 +- sing-box/clients/android/build.gradle | 4 +- sing-box/clients/android/version.properties | 2 +- sing-box/go.mod | 2 +- sing-box/go.sum | 4 +- small/gn/Makefile | 6 +- small/gn/src/out/last_commit_position.h | 4 +- small/sing-box/Makefile | 4 +- suyu/.forgejo/workflows/ci.yml | 42 ++-- suyu/.forgejo/workflows/codespell.yml | 9 +- suyu/.forgejo/workflows/verify.yml | 208 ++++++++-------- suyu/.gitmodules | 10 +- suyu/README.md | 10 +- suyu/src/suyu/main.cpp | 30 ++- .../video_core/vulkan_common/vulkan_device.h | 2 +- .../v2rayN/v2rayN/Common/DownloaderHelper.cs | 8 +- .../v2rayN/v2rayN/Common/HttpClientHelper.cs | 6 +- v2rayn/v2rayN/v2rayN/Common/JsonUtile.cs | 4 +- v2rayn/v2rayN/v2rayN/Common/Utile.cs | 20 +- .../v2rayN/Converters/MaterialDesignFonts.cs | 2 +- v2rayn/v2rayN/v2rayN/Handler/ConfigHandler.cs | 42 +++- .../v2rayN/Handler/CoreConfigSingbox.cs | 15 +- .../v2rayN/v2rayN/Handler/CoreConfigV2ray.cs | 23 +- v2rayn/v2rayN/v2rayN/Handler/CoreHandler.cs | 4 +- v2rayn/v2rayN/v2rayN/Handler/ShareHandler.cs | 4 +- .../v2rayN/Handler/StatisticsSingbox.cs | 2 +- v2rayn/v2rayN/v2rayN/Handler/UpdateHandle.cs | 2 +- v2rayn/v2rayN/v2rayN/Model/V2rayConfig.cs | 8 +- v2rayn/v2rayN/v2rayN/Resx/ResUI.Designer.cs | 9 + v2rayn/v2rayN/v2rayN/Resx/ResUI.resx | 3 + v2rayn/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx | 3 + v2rayn/v2rayN/v2rayN/Resx/ResUI.zh-Hant.resx | 3 + .../v2rayN/ViewModels/SubEditViewModel.cs | 2 +- .../v2rayN/Views/AddServerWindow.xaml.cs | 1 + v2rayn/v2rayN/v2rayN/Views/MsgView.xaml.cs | 2 +- xray-core/app/proxyman/config.pb.go | 54 ++-- xray-core/app/proxyman/config.proto | 1 + xray-core/app/proxyman/outbound/handler.go | 22 +- xray-core/infra/conf/transport_internet.go | 2 + xray-core/infra/conf/xray.go | 47 ++-- .../main/commands/all/api/balancer_info.go | 15 +- .../internet/httpupgrade/config.pb.go | 79 +++--- .../internet/httpupgrade/config.proto | 1 + .../internet/httpupgrade/connection.go | 19 ++ .../transport/internet/httpupgrade/dialer.go | 3 + .../transport/internet/httpupgrade/hub.go | 15 ++ youtube-dl/youtube_dl/extractor/youtube.py | 6 +- yt-dlp/yt_dlp/networking/_websockets.py | 32 ++- 73 files changed, 1208 insertions(+), 448 deletions(-) create mode 100644 hysteria/app/internal/tun/log.go create mode 100644 hysteria/app/internal/tun/server.go create mode 100644 xray-core/transport/internet/httpupgrade/connection.go diff --git a/.github/update.log b/.github/update.log index 6465c61d63..ebb24e5c4c 100644 --- a/.github/update.log +++ b/.github/update.log @@ -595,3 +595,4 @@ Update On Wed Mar 20 14:51:04 CET 2024 Update On Wed Mar 20 15:20:33 CET 2024 Update On Fri Mar 22 14:55:10 CET 2024 Update On Fri Mar 22 19:26:11 CET 2024 +Update On Sat Mar 23 19:27:23 CET 2024 diff --git a/clash-meta/dns/client.go b/clash-meta/dns/client.go index fc76c1241f..3b4efed105 100644 --- a/clash-meta/dns/client.go +++ b/clash-meta/dns/client.go @@ -78,7 +78,9 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) options = append(options, dialer.WithInterface(c.iface)) } - conn, err := getDialHandler(c.r, c.proxyAdapter, c.proxyName, options...)(ctx, network, net.JoinHostPort(ip.String(), c.port)) + dialHandler := getDialHandler(c.r, c.proxyAdapter, c.proxyName, options...) + addr := net.JoinHostPort(ip.String(), c.port) + conn, err := dialHandler(ctx, network, addr) if err != nil { return nil, err } @@ -111,7 +113,16 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) if msg != nil && msg.Truncated && c.Client.Net == "" { tcpClient := *c.Client // copy a client tcpClient.Net = "tcp" + network = "tcp" log.Debugln("[DNS] Truncated reply from %s:%s for %s over UDP, retrying over TCP", c.host, c.port, m.Question[0].String()) + dConn.Conn, err = dialHandler(ctx, network, addr) + if err != nil { + ch <- result{msg, err} + return + } + defer func() { + _ = conn.Close() + }() msg, _, err = tcpClient.ExchangeWithConn(m, dConn) } diff --git a/clash-nyanpasu/backend/Cargo.lock b/clash-nyanpasu/backend/Cargo.lock index 82b4d08324..eb6303ebfa 100644 --- a/clash-nyanpasu/backend/Cargo.lock +++ b/clash-nyanpasu/backend/Cargo.lock @@ -781,7 +781,7 @@ dependencies = [ "glob", "gunzip", "image 0.25.0", - "indexmap 2.2.5", + "indexmap 2.2.6", "log", "nanoid", "once_cell", @@ -819,7 +819,7 @@ dependencies = [ "uuid", "warp", "webview2-com", - "which 6.0.0", + "which 6.0.1", "window-shadows", "window-vibrancy", "windows 0.39.0", @@ -2173,7 +2173,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -2536,9 +2536,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -2921,7 +2921,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.4", + "windows-targets 0.48.5", ] [[package]] @@ -3871,7 +3871,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.2.5", + "indexmap 2.2.6", ] [[package]] @@ -4074,7 +4074,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" dependencies = [ "base64 0.21.7", - "indexmap 2.2.5", + "indexmap 2.2.6", "line-wrap", "quick-xml 0.31.0", "serde", @@ -4962,7 +4962,7 @@ version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "itoa 1.0.10", "ryu", "serde", @@ -5010,7 +5010,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_derive", "serde_json", @@ -5048,7 +5048,7 @@ version = "0.9.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "itoa 1.0.10", "ryu", "serde", @@ -6143,7 +6143,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -6156,7 +6156,7 @@ version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -6872,15 +6872,14 @@ dependencies = [ [[package]] name = "which" -version = "6.0.0" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fa5e0c10bf77f44aac573e498d1a82d5fbd5e91f6fc0a99e7be4b38e85e101c" +checksum = "8211e4f58a2b2805adfbefbc07bab82958fc91e3836339b1ab7ae32465dce0d7" dependencies = [ "either", "home", - "once_cell", "rustix 0.38.31", - "windows-sys 0.52.0", + "winsafe", ] [[package]] @@ -7415,6 +7414,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winsafe" +version = "0.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" + [[package]] name = "wry" version = "0.24.7" diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index 7cee1be5ab..6d105e287a 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -103,7 +103,7 @@ "@types/js-cookie": "3.0.6", "@types/lodash-es": "4.17.12", "@types/node": "20.11.30", - "@types/react": "18.2.67", + "@types/react": "18.2.69", "@types/react-dom": "18.2.22", "@types/react-transition-group": "4.4.10", "@typescript-eslint/eslint-plugin": "7.3.1", @@ -151,7 +151,7 @@ "telegraf": "4.16.3", "tsx": "4.7.1", "typescript": "5.4.3", - "vite": "5.2.3", + "vite": "5.2.4", "vite-plugin-monaco-editor": "1.1.0", "vite-plugin-svgr": "4.2.0" } diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index bdd5b4324e..734ccdb03d 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -19,25 +19,25 @@ dependencies: version: 3.2.2(react@18.2.0) '@emotion/react': specifier: 11.11.4 - version: 11.11.4(@types/react@18.2.67)(react@18.2.0) + version: 11.11.4(@types/react@18.2.69)(react@18.2.0) '@emotion/styled': specifier: 11.11.0 - version: 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.67)(react@18.2.0) + version: 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.69)(react@18.2.0) '@juggle/resize-observer': specifier: 3.4.0 version: 3.4.0 '@mui/icons-material': specifier: 5.15.14 - version: 5.15.14(@mui/material@5.15.14)(@types/react@18.2.67)(react@18.2.0) + version: 5.15.14(@mui/material@5.15.14)(@types/react@18.2.69)(react@18.2.0) '@mui/lab': specifier: 5.0.0-alpha.169 - version: 5.0.0-alpha.169(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + version: 5.0.0-alpha.169(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0) '@mui/material': specifier: 5.15.14 - version: 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + version: 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0) '@mui/x-data-grid': specifier: 7.0.0 - version: 7.0.0(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + version: 7.0.0(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0) '@tauri-apps/api': specifier: 1.5.3 version: 1.5.3 @@ -64,7 +64,7 @@ dependencies: version: 0.47.0 mui-color-input: specifier: 2.0.3 - version: 2.0.3(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + version: 2.0.3(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0) react: specifier: 18.2.0 version: 18.2.0 @@ -82,7 +82,7 @@ dependencies: version: 14.1.0(i18next@23.10.1)(react-dom@18.2.0)(react@18.2.0) react-markdown: specifier: 9.0.1 - version: 9.0.1(@types/react@18.2.67)(react@18.2.0) + version: 9.0.1(@types/react@18.2.69)(react@18.2.0) react-router-dom: specifier: 6.22.3 version: 6.22.3(react-dom@18.2.0)(react@18.2.0) @@ -125,8 +125,8 @@ devDependencies: specifier: 20.11.30 version: 20.11.30 '@types/react': - specifier: 18.2.67 - version: 18.2.67 + specifier: 18.2.69 + version: 18.2.69 '@types/react-dom': specifier: 18.2.22 version: 18.2.22 @@ -141,7 +141,7 @@ devDependencies: version: 7.3.1(eslint@8.57.0)(typescript@5.4.3) '@vitejs/plugin-react': specifier: 4.2.1 - version: 4.2.1(vite@5.2.3) + version: 4.2.1(vite@5.2.4) adm-zip: specifier: 0.5.12 version: 0.5.12 @@ -269,14 +269,14 @@ devDependencies: specifier: 5.4.3 version: 5.4.3 vite: - specifier: 5.2.3 - version: 5.2.3(@types/node@20.11.30)(sass@1.72.0) + specifier: 5.2.4 + version: 5.2.4(@types/node@20.11.30)(sass@1.72.0) vite-plugin-monaco-editor: specifier: npm:vite-plugin-monaco-editor-new@1.1.3 version: /vite-plugin-monaco-editor-new@1.1.3(monaco-editor@0.47.0) vite-plugin-svgr: specifier: 4.2.0 - version: 4.2.0(typescript@5.4.3)(vite@5.2.3) + version: 4.2.0(typescript@5.4.3)(vite@5.2.4) packages: @@ -825,7 +825,7 @@ packages: resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} dev: false - /@emotion/react@11.11.4(@types/react@18.2.67)(react@18.2.0): + /@emotion/react@11.11.4(@types/react@18.2.69)(react@18.2.0): resolution: {integrity: sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==} peerDependencies: '@types/react': '*' @@ -841,7 +841,7 @@ packages: '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) '@emotion/utils': 1.2.1 '@emotion/weak-memoize': 0.3.1 - '@types/react': 18.2.67 + '@types/react': 18.2.69 hoist-non-react-statics: 3.3.2 react: 18.2.0 dev: false @@ -860,7 +860,7 @@ packages: resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} dev: false - /@emotion/styled@11.11.0(@emotion/react@11.11.4)(@types/react@18.2.67)(react@18.2.0): + /@emotion/styled@11.11.0(@emotion/react@11.11.4)(@types/react@18.2.69)(react@18.2.0): resolution: {integrity: sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==} peerDependencies: '@emotion/react': ^11.0.0-rc.0 @@ -873,11 +873,11 @@ packages: '@babel/runtime': 7.23.8 '@emotion/babel-plugin': 11.11.0 '@emotion/is-prop-valid': 1.2.1 - '@emotion/react': 11.11.4(@types/react@18.2.67)(react@18.2.0) + '@emotion/react': 11.11.4(@types/react@18.2.69)(react@18.2.0) '@emotion/serialize': 1.1.3 '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.2.0) '@emotion/utils': 1.2.1 - '@types/react': 18.2.67 + '@types/react': 18.2.69 react: 18.2.0 dev: false @@ -1451,7 +1451,7 @@ packages: resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==} dev: false - /@mui/base@5.0.0-beta.40(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): + /@mui/base@5.0.0-beta.40(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1464,10 +1464,10 @@ packages: dependencies: '@babel/runtime': 7.23.9 '@floating-ui/react-dom': 2.0.8(react-dom@18.2.0)(react@18.2.0) - '@mui/types': 7.2.14(@types/react@18.2.67) - '@mui/utils': 5.15.14(@types/react@18.2.67)(react@18.2.0) + '@mui/types': 7.2.14(@types/react@18.2.69) + '@mui/utils': 5.15.14(@types/react@18.2.69)(react@18.2.0) '@popperjs/core': 2.11.8 - '@types/react': 18.2.67 + '@types/react': 18.2.69 clsx: 2.1.0 prop-types: 15.8.1 react: 18.2.0 @@ -1478,7 +1478,7 @@ packages: resolution: {integrity: sha512-on75VMd0XqZfaQW+9pGjSNiqW+ghc5E2ZSLRBXwcXl/C4YzjfyjrLPhrEpKnR9Uym9KXBvxrhoHfPcczYHweyA==} dev: false - /@mui/icons-material@5.15.14(@mui/material@5.15.14)(@types/react@18.2.67)(react@18.2.0): + /@mui/icons-material@5.15.14(@mui/material@5.15.14)(@types/react@18.2.69)(react@18.2.0): resolution: {integrity: sha512-vj/51k7MdFmt+XVw94sl30SCvGx6+wJLsNYjZRgxhS6y3UtnWnypMOsm3Kmg8TN+P0dqwsjy4/fX7B1HufJIhw==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1490,12 +1490,12 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.9 - '@mui/material': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) - '@types/react': 18.2.67 + '@mui/material': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.69 react: 18.2.0 dev: false - /@mui/lab@5.0.0-alpha.169(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): + /@mui/lab@5.0.0-alpha.169(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-h6xe1K6ISKUbyxTDgdvql4qoDP6+q8ad5fg9nXQxGLUrIeT2jVrBuT/jRECSTufbnhzP+V5kulvYxaMfM8rEdA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1514,21 +1514,21 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.9 - '@emotion/react': 11.11.4(@types/react@18.2.67)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.67)(react@18.2.0) - '@mui/base': 5.0.0-beta.40(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) - '@mui/material': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) - '@mui/system': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.67)(react@18.2.0) - '@mui/types': 7.2.14(@types/react@18.2.67) - '@mui/utils': 5.15.14(@types/react@18.2.67)(react@18.2.0) - '@types/react': 18.2.67 + '@emotion/react': 11.11.4(@types/react@18.2.69)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.69)(react@18.2.0) + '@mui/base': 5.0.0-beta.40(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0) + '@mui/material': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0) + '@mui/system': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.69)(react@18.2.0) + '@mui/types': 7.2.14(@types/react@18.2.69) + '@mui/utils': 5.15.14(@types/react@18.2.69)(react@18.2.0) + '@types/react': 18.2.69 clsx: 2.1.0 prop-types: 15.8.1 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false - /@mui/material@5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): + /@mui/material@5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-kEbRw6fASdQ1SQ7LVdWR5OlWV3y7Y54ZxkLzd6LV5tmz+NpO3MJKZXSfgR0LHMP7meKsPiMm4AuzV0pXDpk/BQ==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1546,14 +1546,14 @@ packages: optional: true dependencies: '@babel/runtime': 7.23.9 - '@emotion/react': 11.11.4(@types/react@18.2.67)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.67)(react@18.2.0) - '@mui/base': 5.0.0-beta.40(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + '@emotion/react': 11.11.4(@types/react@18.2.69)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.69)(react@18.2.0) + '@mui/base': 5.0.0-beta.40(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0) '@mui/core-downloads-tracker': 5.15.14 - '@mui/system': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.67)(react@18.2.0) - '@mui/types': 7.2.14(@types/react@18.2.67) - '@mui/utils': 5.15.14(@types/react@18.2.67)(react@18.2.0) - '@types/react': 18.2.67 + '@mui/system': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.69)(react@18.2.0) + '@mui/types': 7.2.14(@types/react@18.2.69) + '@mui/utils': 5.15.14(@types/react@18.2.69)(react@18.2.0) + '@types/react': 18.2.69 '@types/react-transition-group': 4.4.10 clsx: 2.1.0 csstype: 3.1.3 @@ -1564,7 +1564,7 @@ packages: react-transition-group: 4.4.5(react-dom@18.2.0)(react@18.2.0) dev: false - /@mui/private-theming@5.15.14(@types/react@18.2.67)(react@18.2.0): + /@mui/private-theming@5.15.14(@types/react@18.2.69)(react@18.2.0): resolution: {integrity: sha512-UH0EiZckOWcxiXLX3Jbb0K7rC8mxTr9L9l6QhOZxYc4r8FHUkefltV9VDGLrzCaWh30SQiJvAEd7djX3XXY6Xw==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1575,8 +1575,8 @@ packages: optional: true dependencies: '@babel/runtime': 7.24.1 - '@mui/utils': 5.15.14(@types/react@18.2.67)(react@18.2.0) - '@types/react': 18.2.67 + '@mui/utils': 5.15.14(@types/react@18.2.69)(react@18.2.0) + '@types/react': 18.2.69 prop-types: 15.8.1 react: 18.2.0 dev: false @@ -1596,14 +1596,14 @@ packages: dependencies: '@babel/runtime': 7.24.1 '@emotion/cache': 11.11.0 - '@emotion/react': 11.11.4(@types/react@18.2.67)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.67)(react@18.2.0) + '@emotion/react': 11.11.4(@types/react@18.2.69)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.69)(react@18.2.0) csstype: 3.1.3 prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/system@5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.67)(react@18.2.0): + /@mui/system@5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.69)(react@18.2.0): resolution: {integrity: sha512-auXLXzUaCSSOLqJXmsAaq7P96VPRXg2Rrz6OHNV7lr+kB8lobUF+/N84Vd9C4G/wvCXYPs5TYuuGBRhcGbiBGg==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1620,20 +1620,20 @@ packages: optional: true dependencies: '@babel/runtime': 7.24.1 - '@emotion/react': 11.11.4(@types/react@18.2.67)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.67)(react@18.2.0) - '@mui/private-theming': 5.15.14(@types/react@18.2.67)(react@18.2.0) + '@emotion/react': 11.11.4(@types/react@18.2.69)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.69)(react@18.2.0) + '@mui/private-theming': 5.15.14(@types/react@18.2.69)(react@18.2.0) '@mui/styled-engine': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(react@18.2.0) - '@mui/types': 7.2.14(@types/react@18.2.67) - '@mui/utils': 5.15.14(@types/react@18.2.67)(react@18.2.0) - '@types/react': 18.2.67 + '@mui/types': 7.2.14(@types/react@18.2.69) + '@mui/utils': 5.15.14(@types/react@18.2.69)(react@18.2.0) + '@types/react': 18.2.69 clsx: 2.1.0 csstype: 3.1.3 prop-types: 15.8.1 react: 18.2.0 dev: false - /@mui/types@7.2.14(@types/react@18.2.67): + /@mui/types@7.2.14(@types/react@18.2.69): resolution: {integrity: sha512-MZsBZ4q4HfzBsywtXgM1Ksj6HDThtiwmOKUXH1pKYISI9gAVXCNHNpo7TlGoGrBaYWZTdNoirIN7JsQcQUjmQQ==} peerDependencies: '@types/react': ^17.0.0 || ^18.0.0 @@ -1641,10 +1641,10 @@ packages: '@types/react': optional: true dependencies: - '@types/react': 18.2.67 + '@types/react': 18.2.69 dev: false - /@mui/utils@5.15.14(@types/react@18.2.67)(react@18.2.0): + /@mui/utils@5.15.14(@types/react@18.2.69)(react@18.2.0): resolution: {integrity: sha512-0lF/7Hh/ezDv5X7Pry6enMsbYyGKjADzvHyo3Qrc/SSlTsQ1VkbDMbH0m2t3OR5iIVLwMoxwM7yGd+6FCMtTFA==} engines: {node: '>=12.0.0'} peerDependencies: @@ -1656,13 +1656,13 @@ packages: dependencies: '@babel/runtime': 7.24.1 '@types/prop-types': 15.7.11 - '@types/react': 18.2.67 + '@types/react': 18.2.69 prop-types: 15.8.1 react: 18.2.0 react-is: 18.2.0 dev: false - /@mui/x-data-grid@7.0.0(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): + /@mui/x-data-grid@7.0.0(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Nwwfr+ot/di0oH/pVwIxKV2QD7QyUY/MKkTWRSKzQoJw2aiFQf1Usmvq9Fu1qsCsvMmqIFaToY7972p0cczRjw==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1671,9 +1671,9 @@ packages: react-dom: ^17.0.0 || ^18.0.0 dependencies: '@babel/runtime': 7.24.1 - '@mui/material': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) - '@mui/system': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.67)(react@18.2.0) - '@mui/utils': 5.15.14(@types/react@18.2.67)(react@18.2.0) + '@mui/material': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0) + '@mui/system': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.69)(react@18.2.0) + '@mui/utils': 5.15.14(@types/react@18.2.69)(react@18.2.0) clsx: 2.1.0 prop-types: 15.8.1 react: 18.2.0 @@ -2309,16 +2309,16 @@ packages: /@types/react-dom@18.2.22: resolution: {integrity: sha512-fHkBXPeNtfvri6gdsMYyW+dW7RXFo6Ad09nLFK0VQWR7yGLai/Cyvyj696gbwYvBnhGtevUG9cET0pmUbMtoPQ==} dependencies: - '@types/react': 18.2.67 + '@types/react': 18.2.69 dev: true /@types/react-transition-group@4.4.10: resolution: {integrity: sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==} dependencies: - '@types/react': 18.2.67 + '@types/react': 18.2.69 - /@types/react@18.2.67: - resolution: {integrity: sha512-vkIE2vTIMHQ/xL0rgmuoECBCkZFZeHr49HeWSc24AptMbNRo7pwSBvj73rlJJs9fGKj0koS+V7kQB1jHS0uCgw==} + /@types/react@18.2.69: + resolution: {integrity: sha512-W1HOMUWY/1Yyw0ba5TkCV+oqynRjG7BnteBB+B7JmAK7iw3l2SW+VGOxL+akPweix6jk2NNJtyJKpn4TkpfK3Q==} dependencies: '@types/prop-types': 15.7.11 '@types/scheduler': 0.16.2 @@ -2474,7 +2474,7 @@ packages: /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - /@vitejs/plugin-react@4.2.1(vite@5.2.3): + /@vitejs/plugin-react@4.2.1(vite@5.2.4): resolution: {integrity: sha512-oojO9IDc4nCUUi8qIR11KoQm0XFFLIwsRBwHRR4d/88IWghn1y6ckz/bJ8GHDCsYEJee8mDzqtJxh15/cisJNQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -2485,7 +2485,7 @@ packages: '@babel/plugin-transform-react-jsx-source': 7.23.3(@babel/core@7.23.6) '@types/babel__core': 7.20.5 react-refresh: 0.14.0 - vite: 5.2.3(@types/node@20.11.30)(sass@1.72.0) + vite: 5.2.4(@types/node@20.11.30)(sass@1.72.0) transitivePeerDependencies: - supports-color dev: true @@ -5625,7 +5625,7 @@ packages: /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - /mui-color-input@2.0.3(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): + /mui-color-input@2.0.3(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@mui/material@5.15.14)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-rAd040qQ0Y+8dk4gE8kkCiJ/vCgA0j4vv1quJ43BfORTFE3uHarHj0xY1Vo9CPbojtx1f5vW+CjckYPRIZPIRg==} peerDependencies: '@emotion/react': ^11.5.0 @@ -5639,10 +5639,10 @@ packages: optional: true dependencies: '@ctrl/tinycolor': 4.0.3 - '@emotion/react': 11.11.4(@types/react@18.2.67)(react@18.2.0) - '@emotion/styled': 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.67)(react@18.2.0) - '@mui/material': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) - '@types/react': 18.2.67 + '@emotion/react': 11.11.4(@types/react@18.2.69)(react@18.2.0) + '@emotion/styled': 11.11.0(@emotion/react@11.11.4)(@types/react@18.2.69)(react@18.2.0) + '@mui/material': 5.15.14(@emotion/react@11.11.4)(@emotion/styled@11.11.0)(@types/react@18.2.69)(react-dom@18.2.0)(react@18.2.0) + '@types/react': 18.2.69 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -6164,14 +6164,14 @@ packages: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: false - /react-markdown@9.0.1(@types/react@18.2.67)(react@18.2.0): + /react-markdown@9.0.1(@types/react@18.2.69)(react@18.2.0): resolution: {integrity: sha512-186Gw/vF1uRkydbsOIkcGXw7aHq0sZOCRFFjGrr7b9+nVZg4UfA4enXCaxm4fUzecU38sWfrNDitGhshuU7rdg==} peerDependencies: '@types/react': '>=18' react: '>=18' dependencies: '@types/hast': 3.0.4 - '@types/react': 18.2.67 + '@types/react': 18.2.69 devlop: 1.1.0 hast-util-to-jsx-runtime: 2.3.0 html-url-attributes: 3.0.0 @@ -7334,7 +7334,7 @@ packages: monaco-editor: 0.47.0 dev: true - /vite-plugin-svgr@4.2.0(typescript@5.4.3)(vite@5.2.3): + /vite-plugin-svgr@4.2.0(typescript@5.4.3)(vite@5.2.4): resolution: {integrity: sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA==} peerDependencies: vite: ^2.6.0 || 3 || 4 || 5 @@ -7342,15 +7342,15 @@ packages: '@rollup/pluginutils': 5.0.5 '@svgr/core': 8.1.0(typescript@5.4.3) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0) - vite: 5.2.3(@types/node@20.11.30)(sass@1.72.0) + vite: 5.2.4(@types/node@20.11.30)(sass@1.72.0) transitivePeerDependencies: - rollup - supports-color - typescript dev: true - /vite@5.2.3(@types/node@20.11.30)(sass@1.72.0): - resolution: {integrity: sha512-+i1oagbvkVIhEy9TnEV+fgXsng13nZM90JQbrcPrf6DvW2mXARlz+DK7DLiDP+qeKoD1FCVx/1SpFL1CLq9Mhw==} + /vite@5.2.4(@types/node@20.11.30)(sass@1.72.0): + resolution: {integrity: sha512-vjFghvHWidBTinu5TCymJk/lRHlR5ljqB83yugr0HA1xspUPdOZHqbqDLnZ8f9/jINrtFHTCYYyIUi+o+Q5iyg==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: diff --git a/hysteria/app/cmd/client.go b/hysteria/app/cmd/client.go index 9a785d26bb..c1d04bd786 100644 --- a/hysteria/app/cmd/client.go +++ b/hysteria/app/cmd/client.go @@ -5,8 +5,12 @@ import ( "crypto/x509" "encoding/hex" "errors" + "fmt" "net" + "net/netip" "os" + "runtime" + "slices" "strconv" "strings" "time" @@ -20,6 +24,7 @@ import ( "github.com/apernet/hysteria/app/internal/redirect" "github.com/apernet/hysteria/app/internal/socks5" "github.com/apernet/hysteria/app/internal/tproxy" + "github.com/apernet/hysteria/app/internal/tun" "github.com/apernet/hysteria/app/internal/url" "github.com/apernet/hysteria/app/internal/utils" "github.com/apernet/hysteria/core/client" @@ -65,6 +70,7 @@ type clientConfig struct { TCPTProxy *tcpTProxyConfig `mapstructure:"tcpTProxy"` UDPTProxy *udpTProxyConfig `mapstructure:"udpTProxy"` TCPRedirect *tcpRedirectConfig `mapstructure:"tcpRedirect"` + TUN *tunConfig `mapstructure:"tun"` } type clientConfigTransportUDP struct { @@ -145,6 +151,23 @@ type tcpRedirectConfig struct { Listen string `mapstructure:"listen"` } +type tunConfig struct { + Name string `mapstructure:"name"` + MTU uint32 `mapstructure:"mtu"` + Timeout time.Duration `mapstructure:"timeout"` + Address struct { + IPv4 string `mapstructure:"ipv4"` + IPv6 string `mapstructure:"ipv6"` + } `mapstructure:"address"` + Route *struct { + Strict bool `mapstructure:"strict"` + IPv4 []string `mapstructure:"ipv4"` + IPv6 []string `mapstructure:"ipv6"` + IPv4Exclude []string `mapstructure:"ipv4Exclude"` + IPv6Exclude []string `mapstructure:"ipv6Exclude"` + } `mapstructure:"route"` +} + func (c *clientConfig) fillServerAddr(hyConfig *client.Config) error { if c.Server == "" { return configError{Field: "server", Err: errors.New("server address is empty")} @@ -459,6 +482,11 @@ func runClient(cmd *cobra.Command, args []string) { return clientTCPRedirect(*config.TCPRedirect, c) }) } + if config.TUN != nil { + runner.Add("TUN", func() error { + return clientTUN(*config.TUN, c) + }) + } runner.Run() } @@ -656,6 +684,92 @@ func clientTCPRedirect(config tcpRedirectConfig, c client.Client) error { return p.ListenAndServe(laddr) } +func clientTUN(config tunConfig, c client.Client) error { + supportedPlatforms := []string{"linux", "darwin", "windows", "android"} + if !slices.Contains(supportedPlatforms, runtime.GOOS) { + logger.Error("TUN is not supported on this platform", zap.String("platform", runtime.GOOS)) + } + if config.Name == "" { + return configError{Field: "name", Err: errors.New("name is empty")} + } + if config.MTU == 0 { + config.MTU = 1500 + } + timeout := int64(config.Timeout.Seconds()) + if timeout == 0 { + timeout = 300 + } + if config.Address.IPv4 == "" { + config.Address.IPv4 = "100.100.100.101/30" + } + prefix4, err := netip.ParsePrefix(config.Address.IPv4) + if err != nil { + return configError{Field: "address.ipv4", Err: err} + } + if config.Address.IPv6 == "" { + config.Address.IPv6 = "2001::ffff:ffff:ffff:fff1/126" + } + prefix6, err := netip.ParsePrefix(config.Address.IPv6) + if err != nil { + return configError{Field: "address.ipv6", Err: err} + } + server := &tun.Server{ + HyClient: c, + EventLogger: &tunLogger{}, + Logger: logger, + IfName: config.Name, + MTU: config.MTU, + Timeout: timeout, + Inet4Address: []netip.Prefix{prefix4}, + Inet6Address: []netip.Prefix{prefix6}, + } + if config.Route != nil { + server.AutoRoute = true + server.StructRoute = config.Route.Strict + + parsePrefixes := func(field string, ss []string) ([]netip.Prefix, error) { + var prefixes []netip.Prefix + for i, s := range ss { + var p netip.Prefix + if strings.Contains(s, "/") { + var err error + p, err = netip.ParsePrefix(s) + if err != nil { + return nil, configError{Field: fmt.Sprintf("%s[%d]", field, i), Err: err} + } + } else { + pa, err := netip.ParseAddr(s) + if err != nil { + return nil, configError{Field: fmt.Sprintf("%s[%d]", field, i), Err: err} + } + p = netip.PrefixFrom(pa, pa.BitLen()) + } + prefixes = append(prefixes, p) + } + return prefixes, nil + } + + server.Inet4RouteAddress, err = parsePrefixes("route.ipv4", config.Route.IPv4) + if err != nil { + return err + } + server.Inet6RouteAddress, err = parsePrefixes("route.ipv6", config.Route.IPv6) + if err != nil { + return err + } + server.Inet4RouteExcludeAddress, err = parsePrefixes("route.ipv4Exclude", config.Route.IPv4Exclude) + if err != nil { + return err + } + server.Inet6RouteExcludeAddress, err = parsePrefixes("route.ipv6Exclude", config.Route.IPv6Exclude) + if err != nil { + return err + } + } + logger.Info("TUN listening", zap.String("interface", config.Name)) + return server.Serve() +} + // parseServerAddrString parses server address string. // Server address can be in either "host:port" or "host" format (in which case we assume port 443). func parseServerAddrString(addrStr string) (host, port, hostPort string) { @@ -715,7 +829,7 @@ func (l *socks5Logger) TCPError(addr net.Addr, reqAddr string, err error) { if err == nil { logger.Debug("SOCKS5 TCP closed", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr)) } else { - logger.Error("SOCKS5 TCP error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr), zap.Error(err)) + logger.Warn("SOCKS5 TCP error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr), zap.Error(err)) } } @@ -727,7 +841,7 @@ func (l *socks5Logger) UDPError(addr net.Addr, err error) { if err == nil { logger.Debug("SOCKS5 UDP closed", zap.String("addr", addr.String())) } else { - logger.Error("SOCKS5 UDP error", zap.String("addr", addr.String()), zap.Error(err)) + logger.Warn("SOCKS5 UDP error", zap.String("addr", addr.String()), zap.Error(err)) } } @@ -741,7 +855,7 @@ func (l *httpLogger) ConnectError(addr net.Addr, reqAddr string, err error) { if err == nil { logger.Debug("HTTP CONNECT closed", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr)) } else { - logger.Error("HTTP CONNECT error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr), zap.Error(err)) + logger.Warn("HTTP CONNECT error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr), zap.Error(err)) } } @@ -753,7 +867,7 @@ func (l *httpLogger) HTTPError(addr net.Addr, reqURL string, err error) { if err == nil { logger.Debug("HTTP closed", zap.String("addr", addr.String()), zap.String("reqURL", reqURL)) } else { - logger.Error("HTTP error", zap.String("addr", addr.String()), zap.String("reqURL", reqURL), zap.Error(err)) + logger.Warn("HTTP error", zap.String("addr", addr.String()), zap.String("reqURL", reqURL), zap.Error(err)) } } @@ -767,7 +881,7 @@ func (l *tcpLogger) Error(addr net.Addr, err error) { if err == nil { logger.Debug("TCP forwarding closed", zap.String("addr", addr.String())) } else { - logger.Error("TCP forwarding error", zap.String("addr", addr.String()), zap.Error(err)) + logger.Warn("TCP forwarding error", zap.String("addr", addr.String()), zap.Error(err)) } } @@ -781,7 +895,7 @@ func (l *udpLogger) Error(addr net.Addr, err error) { if err == nil { logger.Debug("UDP forwarding closed", zap.String("addr", addr.String())) } else { - logger.Error("UDP forwarding error", zap.String("addr", addr.String()), zap.Error(err)) + logger.Warn("UDP forwarding error", zap.String("addr", addr.String()), zap.Error(err)) } } @@ -795,7 +909,7 @@ func (l *tcpTProxyLogger) Error(addr, reqAddr net.Addr, err error) { if err == nil { logger.Debug("TCP transparent proxy closed", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String())) } else { - logger.Error("TCP transparent proxy error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()), zap.Error(err)) + logger.Warn("TCP transparent proxy error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()), zap.Error(err)) } } @@ -809,7 +923,7 @@ func (l *udpTProxyLogger) Error(addr, reqAddr net.Addr, err error) { if err == nil { logger.Debug("UDP transparent proxy closed", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String())) } else { - logger.Error("UDP transparent proxy error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()), zap.Error(err)) + logger.Warn("UDP transparent proxy error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()), zap.Error(err)) } } @@ -823,6 +937,32 @@ func (l *tcpRedirectLogger) Error(addr, reqAddr net.Addr, err error) { if err == nil { logger.Debug("TCP redirect closed", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String())) } else { - logger.Error("TCP redirect error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()), zap.Error(err)) + logger.Warn("TCP redirect error", zap.String("addr", addr.String()), zap.String("reqAddr", reqAddr.String()), zap.Error(err)) + } +} + +type tunLogger struct{} + +func (l *tunLogger) TCPRequest(addr, reqAddr string) { + logger.Debug("TUN TCP request", zap.String("addr", addr), zap.String("reqAddr", reqAddr)) +} + +func (l *tunLogger) TCPError(addr, reqAddr string, err error) { + if err == nil { + logger.Debug("TUN TCP closed", zap.String("addr", addr), zap.String("reqAddr", reqAddr)) + } else { + logger.Warn("TUN TCP error", zap.String("addr", addr), zap.String("reqAddr", reqAddr), zap.Error(err)) + } +} + +func (l *tunLogger) UDPRequest(addr string) { + logger.Debug("TUN UDP request", zap.String("addr", addr)) +} + +func (l *tunLogger) UDPError(addr string, err error) { + if err == nil { + logger.Debug("TUN UDP closed", zap.String("addr", addr)) + } else { + logger.Warn("TUN UDP error", zap.String("addr", addr), zap.Error(err)) } } diff --git a/hysteria/app/cmd/client_test.go b/hysteria/app/cmd/client_test.go index faee251db9..c586949e9e 100644 --- a/hysteria/app/cmd/client_test.go +++ b/hysteria/app/cmd/client_test.go @@ -88,6 +88,28 @@ func TestClientConfig(t *testing.T) { TCPRedirect: &tcpRedirectConfig{ Listen: "127.0.0.1:3500", }, + TUN: &tunConfig{ + Name: "hytun", + MTU: 1500, + Timeout: 60 * time.Second, + Address: struct { + IPv4 string `mapstructure:"ipv4"` + IPv6 string `mapstructure:"ipv6"` + }{IPv4: "100.100.100.101/30", IPv6: "2001::ffff:ffff:ffff:fff1/126"}, + Route: &struct { + Strict bool `mapstructure:"strict"` + IPv4 []string `mapstructure:"ipv4"` + IPv6 []string `mapstructure:"ipv6"` + IPv4Exclude []string `mapstructure:"ipv4Exclude"` + IPv6Exclude []string `mapstructure:"ipv6Exclude"` + }{ + Strict: true, + IPv4: []string{"0.0.0.0/0"}, + IPv6: []string{"2000::/3"}, + IPv4Exclude: []string{"192.0.2.1/32"}, + IPv6Exclude: []string{"2001:db8::1/128"}, + }, + }, }) } diff --git a/hysteria/app/cmd/client_test.yaml b/hysteria/app/cmd/client_test.yaml index 3e2f4aaa4d..4f919df0b9 100644 --- a/hysteria/app/cmd/client_test.yaml +++ b/hysteria/app/cmd/client_test.yaml @@ -65,3 +65,17 @@ udpTProxy: tcpRedirect: listen: 127.0.0.1:3500 + +tun: + name: "hytun" + mtu: 1500 + timeout: 1m + address: + ipv4: 100.100.100.101/30 + ipv6: 2001::ffff:ffff:ffff:fff1/126 + route: + strict: true + ipv4: [0.0.0.0/0] + ipv6: ["2000::/3"] + ipv4Exclude: [192.0.2.1/32] + ipv6Exclude: ["2001:db8::1/128"] diff --git a/hysteria/app/cmd/server.go b/hysteria/app/cmd/server.go index 5a770cc43d..9b6665e7d8 100644 --- a/hysteria/app/cmd/server.go +++ b/hysteria/app/cmd/server.go @@ -815,7 +815,7 @@ func (l *serverLogger) TCPError(addr net.Addr, id, reqAddr string, err error) { if err == nil { logger.Debug("TCP closed", zap.String("addr", addr.String()), zap.String("id", id), zap.String("reqAddr", reqAddr)) } else { - logger.Error("TCP error", zap.String("addr", addr.String()), zap.String("id", id), zap.String("reqAddr", reqAddr), zap.Error(err)) + logger.Warn("TCP error", zap.String("addr", addr.String()), zap.String("id", id), zap.String("reqAddr", reqAddr), zap.Error(err)) } } @@ -827,7 +827,7 @@ func (l *serverLogger) UDPError(addr net.Addr, id string, sessionID uint32, err if err == nil { logger.Debug("UDP closed", zap.String("addr", addr.String()), zap.String("id", id), zap.Uint32("sessionID", sessionID)) } else { - logger.Error("UDP error", zap.String("addr", addr.String()), zap.String("id", id), zap.Uint32("sessionID", sessionID), zap.Error(err)) + logger.Warn("UDP error", zap.String("addr", addr.String()), zap.String("id", id), zap.Uint32("sessionID", sessionID), zap.Error(err)) } } diff --git a/hysteria/app/go.mod b/hysteria/app/go.mod index b2449d1d09..6b5d2c3d4a 100644 --- a/hysteria/app/go.mod +++ b/hysteria/app/go.mod @@ -6,9 +6,11 @@ require ( github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f github.com/apernet/hysteria/core v0.0.0-00010101000000-000000000000 github.com/apernet/hysteria/extras v0.0.0-00010101000000-000000000000 + github.com/apernet/sing-tun v0.2.6-0.20240323130332-b9f6511036ad github.com/caddyserver/certmagic v0.17.2 github.com/mdp/qrterminal/v3 v3.1.1 github.com/mholt/acmez v1.0.4 + github.com/sagernet/sing v0.3.2 github.com/spf13/cobra v1.7.0 github.com/spf13/viper v1.15.0 github.com/stretchr/testify v1.8.4 @@ -20,7 +22,8 @@ require ( github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d // indirect github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/hashicorp/golang-lru/v2 v2.0.5 // indirect @@ -36,6 +39,8 @@ require ( github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/quic-go/qpack v0.4.0 // indirect + github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect + github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect github.com/spf13/afero v1.9.3 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect @@ -43,14 +48,16 @@ require ( github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.4.2 // indirect github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect + github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/mock v0.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.17.0 // indirect + go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.11.1 // indirect google.golang.org/protobuf v1.33.0 // indirect diff --git a/hysteria/app/go.sum b/hysteria/app/go.sum index cd4f24f6a2..152e338712 100644 --- a/hysteria/app/go.sum +++ b/hysteria/app/go.sum @@ -42,6 +42,8 @@ github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f h1:uVh0qpEslrWjg github.com/apernet/go-tproxy v0.0.0-20230809025308-8f4723fd742f/go.mod h1:xkkq9D4ygcldQQhKS/w9CadiCKwCngU7K9E3DaKahpM= github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d h1:K1DMSNtPcaZ/lihYmOHnjThNfUX7cD6SNuVRFnVLVmI= github.com/apernet/quic-go v0.41.1-0.20240301003057-e18162de481d/go.mod h1:4GInxO6ypy63J2NaO5rQx1wRp6K8YHI6zqLG+VswU6I= +github.com/apernet/sing-tun v0.2.6-0.20240323130332-b9f6511036ad h1:QzQ2sKpc9o42HNRR8ukM5uMC/RzR2HgZd/Nvaqol2C0= +github.com/apernet/sing-tun v0.2.6-0.20240323130332-b9f6511036ad/go.mod h1:S5IydyLSN/QAfvY+r2GoomPJ6hidtXWm/Ad18sJVssk= github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0= github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= @@ -68,13 +70,15 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -196,6 +200,12 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE= +github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= +github.com/sagernet/sing v0.3.2 h1:CwWcxUBPkMvwgfe2/zUgY5oHG9qOL8Aob/evIFYK9jo= +github.com/sagernet/sing v0.3.2/go.mod h1:qHySJ7u8po9DABtMYEkNBcOumx7ZZJf/fbv2sfTkNHE= +github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg= +github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s= github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= @@ -229,6 +239,8 @@ github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf h1:7PflaKRt github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf/go.mod h1:CLUSJbazqETbaR+i0YAhXBICV9TrKH93pziccMhmhpM= github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301 h1:d/Wr/Vl/wiJHc3AHYbYs5I3PucJvRuw3SvbmlIRf+oM= github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301/go.mod h1:ntmMHL/xPq1WLeKiw8p/eRATaae6PiVRNipHFJxI8PM= +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.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -255,6 +267,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 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-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= +go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -263,8 +277,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -340,8 +354,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -382,6 +396,7 @@ golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -405,10 +420,10 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= diff --git a/hysteria/app/internal/tun/log.go b/hysteria/app/internal/tun/log.go new file mode 100644 index 0000000000..b30309d28d --- /dev/null +++ b/hysteria/app/internal/tun/log.go @@ -0,0 +1,77 @@ +package tun + +import ( + "github.com/sagernet/sing/common/logger" + "go.uber.org/zap" +) + +var _ logger.Logger = (*singLogger)(nil) + +type singLogger struct { + tag string + zapLogger *zap.Logger +} + +func extractSingExceptions(args []any) { + for i, arg := range args { + if err, ok := arg.(error); ok { + args[i] = err.Error() + } + } +} + +func (l *singLogger) Trace(args ...any) { + if l.zapLogger == nil { + return + } + extractSingExceptions(args) + l.zapLogger.Debug(l.tag, zap.Any("args", args)) +} + +func (l *singLogger) Debug(args ...any) { + if l.zapLogger == nil { + return + } + extractSingExceptions(args) + l.zapLogger.Debug(l.tag, zap.Any("args", args)) +} + +func (l *singLogger) Info(args ...any) { + if l.zapLogger == nil { + return + } + extractSingExceptions(args) + l.zapLogger.Info(l.tag, zap.Any("args", args)) +} + +func (l *singLogger) Warn(args ...any) { + if l.zapLogger == nil { + return + } + extractSingExceptions(args) + l.zapLogger.Warn(l.tag, zap.Any("args", args)) +} + +func (l *singLogger) Error(args ...any) { + if l.zapLogger == nil { + return + } + extractSingExceptions(args) + l.zapLogger.Error(l.tag, zap.Any("args", args)) +} + +func (l *singLogger) Fatal(args ...any) { + if l.zapLogger == nil { + return + } + extractSingExceptions(args) + l.zapLogger.Fatal(l.tag, zap.Any("args", args)) +} + +func (l *singLogger) Panic(args ...any) { + if l.zapLogger == nil { + return + } + extractSingExceptions(args) + l.zapLogger.Panic(l.tag, zap.Any("args", args)) +} diff --git a/hysteria/app/internal/tun/server.go b/hysteria/app/internal/tun/server.go new file mode 100644 index 0000000000..4ae53938eb --- /dev/null +++ b/hysteria/app/internal/tun/server.go @@ -0,0 +1,230 @@ +package tun + +import ( + "context" + "fmt" + "io" + "net" + "net/netip" + + tun "github.com/apernet/sing-tun" + "github.com/sagernet/sing/common/buf" + "github.com/sagernet/sing/common/control" + "github.com/sagernet/sing/common/metadata" + "github.com/sagernet/sing/common/network" + "go.uber.org/zap" + + "github.com/apernet/hysteria/core/client" +) + +type Server struct { + HyClient client.Client + EventLogger EventLogger + + // for debugging + Logger *zap.Logger + + IfName string + MTU uint32 + Timeout int64 // in seconds, also applied to TCP in system stack + + // required by system stack + Inet4Address []netip.Prefix + Inet6Address []netip.Prefix + + // auto route + AutoRoute bool + StructRoute bool + Inet4RouteAddress []netip.Prefix + Inet6RouteAddress []netip.Prefix + Inet4RouteExcludeAddress []netip.Prefix + Inet6RouteExcludeAddress []netip.Prefix +} + +type EventLogger interface { + TCPRequest(addr, reqAddr string) + TCPError(addr, reqAddr string, err error) + UDPRequest(addr string) + UDPError(addr string, err error) +} + +func (s *Server) Serve() error { + tunOpts := tun.Options{ + Name: s.IfName, + Inet4Address: s.Inet4Address, + Inet6Address: s.Inet6Address, + MTU: s.MTU, + GSO: true, + AutoRoute: s.AutoRoute, + StrictRoute: s.StructRoute, + Inet4RouteAddress: s.Inet4RouteAddress, + Inet6RouteAddress: s.Inet6RouteAddress, + Inet4RouteExcludeAddress: s.Inet4RouteExcludeAddress, + Inet6RouteExcludeAddress: s.Inet6RouteExcludeAddress, + Logger: &singLogger{ + tag: "tun", + zapLogger: s.Logger, + }, + } + tunIf, err := tun.New(tunOpts) + if err != nil { + return fmt.Errorf("failed to create tun interface: %w", err) + } + defer tunIf.Close() + + tunStack, err := tun.NewSystem(tun.StackOptions{ + Context: context.Background(), + Tun: tunIf, + TunOptions: tunOpts, + UDPTimeout: s.Timeout, + Handler: &tunHandler{s}, + Logger: &singLogger{ + tag: "tun-stack", + zapLogger: s.Logger, + }, + ForwarderBindInterface: true, + InterfaceFinder: &interfaceFinder{}, + }) + if err != nil { + return fmt.Errorf("failed to create tun stack: %w", err) + } + defer tunStack.Close() + return tunStack.(tun.StackRunner).Run() +} + +type tunHandler struct { + *Server +} + +var _ tun.Handler = (*tunHandler)(nil) + +func (t *tunHandler) NewConnection(ctx context.Context, conn net.Conn, m metadata.Metadata) error { + addr := m.Source.String() + reqAddr := m.Destination.String() + if t.EventLogger != nil { + t.EventLogger.TCPRequest(addr, reqAddr) + } + var closeErr error + defer func() { + if t.EventLogger != nil { + t.EventLogger.TCPError(addr, reqAddr, closeErr) + } + }() + rc, err := t.HyClient.TCP(reqAddr) + if err != nil { + closeErr = err + // the returned err is ignored by caller + return nil + } + defer rc.Close() + + // start forwarding + copyErrChan := make(chan error, 3) + go func() { + <-ctx.Done() + copyErrChan <- ctx.Err() + }() + go func() { + _, copyErr := io.Copy(rc, conn) + copyErrChan <- copyErr + }() + go func() { + _, copyErr := io.Copy(conn, rc) + copyErrChan <- copyErr + }() + closeErr = <-copyErrChan + return nil +} + +func (t *tunHandler) NewPacketConnection(ctx context.Context, conn network.PacketConn, m metadata.Metadata) error { + addr := m.Source.String() + if t.EventLogger != nil { + t.EventLogger.UDPRequest(addr) + } + var closeErr error + defer func() { + if t.EventLogger != nil { + t.EventLogger.UDPError(addr, closeErr) + } + }() + rc, err := t.HyClient.UDP() + if err != nil { + closeErr = err + // the returned err is simply called into NewError again + return nil + } + defer rc.Close() + + // start forwarding + copyErrChan := make(chan error, 3) + go func() { + <-ctx.Done() + copyErrChan <- ctx.Err() + }() + // local <- remote + go func() { + for { + bs, from, err := rc.Receive() + if err != nil { + copyErrChan <- err + return + } + var fromAddr metadata.Socksaddr + if ap, perr := netip.ParseAddrPort(from); perr == nil { + fromAddr = metadata.SocksaddrFromNetIP(ap) + } else { + fromAddr.Fqdn = from + } + err = conn.WritePacket(buf.As(bs), fromAddr) + if err != nil { + copyErrChan <- err + return + } + } + }() + // local -> remote + go func() { + buffer := buf.NewPacket() + defer buffer.Release() + + for { + buffer.Reset() + addr, err := conn.ReadPacket(buffer) + if err != nil { + copyErrChan <- err + return + } + err = rc.Send(buffer.Bytes(), addr.String()) + if err != nil { + copyErrChan <- err + return + } + } + }() + closeErr = <-copyErrChan + return nil +} + +func (t *tunHandler) NewError(ctx context.Context, err error) { + // unused +} + +type interfaceFinder struct{} + +var _ control.InterfaceFinder = (*interfaceFinder)(nil) + +func (f *interfaceFinder) InterfaceIndexByName(name string) (int, error) { + ifce, err := net.InterfaceByName(name) + if err != nil { + return -1, err + } + return ifce.Index, nil +} + +func (f *interfaceFinder) InterfaceNameByIndex(index int) (string, error) { + ifce, err := net.InterfaceByIndex(index) + if err != nil { + return "", err + } + return ifce.Name, nil +} diff --git a/hysteria/core/go.mod b/hysteria/core/go.mod index d9d3fd995f..76bc92775e 100644 --- a/hysteria/core/go.mod +++ b/hysteria/core/go.mod @@ -21,10 +21,10 @@ require ( github.com/quic-go/qpack v0.4.0 // indirect github.com/stretchr/objx v0.5.0 // indirect go.uber.org/mock v0.3.0 // indirect - golang.org/x/crypto v0.17.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.11.1 // indirect google.golang.org/protobuf v1.33.0 // indirect diff --git a/hysteria/core/go.sum b/hysteria/core/go.sum index b51f59b4e7..7b21427b8c 100644 --- a/hysteria/core/go.sum +++ b/hysteria/core/go.sum @@ -45,17 +45,17 @@ go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= diff --git a/hysteria/extras/go.mod b/hysteria/extras/go.mod index dbaccf58bb..3bb0dcde0c 100644 --- a/hysteria/extras/go.mod +++ b/hysteria/extras/go.mod @@ -9,8 +9,8 @@ require ( github.com/miekg/dns v1.1.55 github.com/stretchr/testify v1.8.4 github.com/txthinking/socks5 v0.0.0-20230325130024-4230056ae301 - golang.org/x/crypto v0.17.0 - golang.org/x/net v0.17.0 + golang.org/x/crypto v0.19.0 + golang.org/x/net v0.21.0 google.golang.org/protobuf v1.33.0 ) @@ -28,7 +28,7 @@ require ( go.uber.org/mock v0.3.0 // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.11.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/hysteria/extras/go.sum b/hysteria/extras/go.sum index 61762b3eda..c635709cd5 100644 --- a/hysteria/extras/go.sum +++ b/hysteria/extras/go.sum @@ -58,8 +58,8 @@ go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo= go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o= golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -70,8 +70,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -84,8 +84,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= diff --git a/hysteria/go.work.sum b/hysteria/go.work.sum index ed76dd6ece..62f146ce78 100644 --- a/hysteria/go.work.sum +++ b/hysteria/go.work.sum @@ -26,6 +26,8 @@ dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999 h1:OR8VhtwhcAI3U48/rzBsVOuHi0zDPzYI1xASVcdSgR8= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= @@ -53,6 +55,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHH github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w= 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/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415 h1:q1oJaUPdmpDm/VyXosjgPgr6wS7c5iV2p0PwJD73bUI= +github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad h1:EmNYJhPYy0pOFjCx2PrgtaBXmee0iUX9hLlxE1xHOJE= github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= @@ -237,8 +241,8 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a h1:Jw5wfR+h9mnIYH+OtGT2im5wV1YGGDora5vTv/aa5bE= +golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI= @@ -264,14 +268,11 @@ golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= @@ -281,9 +282,9 @@ golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -324,6 +325,8 @@ grpc.go4.org v0.0.0-20170609214715-11d0a25b4919 h1:tmXTu+dfa+d9Evp8NpJdgOy6+rt8/ grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8= +honnef.co/go/tools v0.4.5 h1:YGD4H+SuIOOqsyoLOpZDWcieM28W47/zRO7f+9V3nvo= +honnef.co/go/tools v0.4.5/go.mod h1:GUV+uIBCLpdf0/v6UhHHG/yzI/z6qPskBeQCjcNB96k= rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE= rsc.io/quote/v3 v3.1.0 h1:9JKUTTIUgS6kzR9mK1YuGKv6Nl+DijDNIc0ghT58FaY= rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4= diff --git a/mieru/.github/workflows/ci.yaml b/mieru/.github/workflows/ci.yaml index 168ef44b73..d0520e8950 100644 --- a/mieru/.github/workflows/ci.yaml +++ b/mieru/.github/workflows/ci.yaml @@ -15,8 +15,6 @@ jobs: uses: actions/setup-go@v5 with: go-version-file: go.mod - - name: Run go vet - run: make vet - name: Build binaries run: make build - name: Upload artifacts diff --git a/mieru/README.md b/mieru/README.md index a75ff2031b..315cd45fa6 100644 --- a/mieru/README.md +++ b/mieru/README.md @@ -27,7 +27,7 @@ For an explanation of the mieru protocol, see [mieru Proxy Protocol](./docs/prot 6. mieru supports multiple users sharing a single proxy server. 7. mieru supports IPv4 and IPv6. 8. mieru provides socks5, HTTP and HTTPS proxy. -9. The client software supports Windows, Mac OS and Linux. +9. The client software supports Windows, Mac OS, Linux and Android. For Android users, please use [NekoBox](https://github.com/MatsuriDayo/NekoBoxForAndroid) version 1.3.1 or above, and install [mieru plugin](https://github.com/enfein/NekoBoxPlugins). 10. The server software supports socks5 outbound (proxy chain). 11. If you need advanced features like global proxy or customized routing rules, you can use mieru as the backend of a proxy platform such as clash. diff --git a/mieru/README.zh_CN.md b/mieru/README.zh_CN.md index b0d4d3dd38..6b6824ae96 100644 --- a/mieru/README.zh_CN.md +++ b/mieru/README.zh_CN.md @@ -25,7 +25,7 @@ mieru 的翻墙原理与 shadowsocks / v2ray 等软件类似,在客户端和 6. mieru 支持多个用户共享代理服务器。 7. mieru 支持 IPv4 和 IPv6。 8. mieru 提供 socks5, HTTP 和 HTTPS 代理。 -9. 客户端软件支持 Windows, Mac OS 和 Linux 系统。 +9. 客户端软件支持 Windows, Mac OS, Linux 和 Android 系统。Android 用户请使用 [NekoBox](https://github.com/MatsuriDayo/NekoBoxForAndroid) 1.3.1 及以上版本,并安装 [mieru 插件](https://github.com/enfein/NekoBoxPlugins)。 10. 服务器软件支持 socks5 出站(链式代理)。 11. 如果需要全局代理或自定义路由规则等高级功能,可以将 mieru 作为 clash 等代理平台的后端。 diff --git a/mieru/docs/server-install.md b/mieru/docs/server-install.md index 0ba2d0061f..43890d3443 100644 --- a/mieru/docs/server-install.md +++ b/mieru/docs/server-install.md @@ -20,8 +20,6 @@ curl -LSO https://github.com/enfein/mieru/releases/download/v2.7.0/mita-2.7.0-1. curl -LSO https://github.com/enfein/mieru/releases/download/v2.7.0/mita-2.7.0-1.aarch64.rpm ``` -If the above link is blocked, please use your browser to download and install from the GitHub Releases page. - ## Install mita package ```sh @@ -38,6 +36,8 @@ sudo rpm -Uvh --force mita-2.7.0-1.x86_64.rpm sudo rpm -Uvh --force mita-2.7.0-1.aarch64.rpm ``` +Those instructions can also be used to upgrade the version of mita software package. + ## Grant permissions, logout and login again to make the change effective ```sh diff --git a/mieru/docs/server-install.zh_CN.md b/mieru/docs/server-install.zh_CN.md index 7de1265535..048fb9bb90 100644 --- a/mieru/docs/server-install.zh_CN.md +++ b/mieru/docs/server-install.zh_CN.md @@ -20,8 +20,6 @@ curl -LSO https://github.com/enfein/mieru/releases/download/v2.7.0/mita-2.7.0-1. curl -LSO https://github.com/enfein/mieru/releases/download/v2.7.0/mita-2.7.0-1.aarch64.rpm ``` -如果上述链接被墙,请翻墙后使用浏览器从 GitHub Releases 页面下载安装。 - ## 安装 mita 软件包 ```sh @@ -38,6 +36,8 @@ sudo rpm -Uvh --force mita-2.7.0-1.x86_64.rpm sudo rpm -Uvh --force mita-2.7.0-1.aarch64.rpm ``` +上述指令也可以用来升级 mita 软件包的版本。 + ## 赋予当前用户操作 mita 的权限,重新登录使此设置生效 ```sh diff --git a/mihomo/dns/client.go b/mihomo/dns/client.go index fc76c1241f..3b4efed105 100644 --- a/mihomo/dns/client.go +++ b/mihomo/dns/client.go @@ -78,7 +78,9 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) options = append(options, dialer.WithInterface(c.iface)) } - conn, err := getDialHandler(c.r, c.proxyAdapter, c.proxyName, options...)(ctx, network, net.JoinHostPort(ip.String(), c.port)) + dialHandler := getDialHandler(c.r, c.proxyAdapter, c.proxyName, options...) + addr := net.JoinHostPort(ip.String(), c.port) + conn, err := dialHandler(ctx, network, addr) if err != nil { return nil, err } @@ -111,7 +113,16 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) if msg != nil && msg.Truncated && c.Client.Net == "" { tcpClient := *c.Client // copy a client tcpClient.Net = "tcp" + network = "tcp" log.Debugln("[DNS] Truncated reply from %s:%s for %s over UDP, retrying over TCP", c.host, c.port, m.Question[0].String()) + dConn.Conn, err = dialHandler(ctx, network, addr) + if err != nil { + ch <- result{msg, err} + return + } + defer func() { + _ = conn.Close() + }() msg, _, err = tcpClient.ExchangeWithConn(m, dConn) } diff --git a/openwrt-packages/alist/Makefile b/openwrt-packages/alist/Makefile index bbbba4a9bc..308969f464 100644 --- a/openwrt-packages/alist/Makefile +++ b/openwrt-packages/alist/Makefile @@ -45,7 +45,7 @@ define Package/$(PKG_NAME) CATEGORY:=Network SUBMENU:=Web Servers/Proxies TITLE:=A file list program that supports multiple storage - URL:=https://alist-doc.nn.ci/ + URL:=https://alist.nn.ci/ DEPENDS:=$(GO_ARCH_DEPENDS) +ca-bundle endef diff --git a/openwrt-packages/luci-app-alist/root/etc/init.d/alist b/openwrt-packages/luci-app-alist/root/etc/init.d/alist index 23ceeee579..ed0eab2380 100755 --- a/openwrt-packages/luci-app-alist/root/etc/init.d/alist +++ b/openwrt-packages/luci-app-alist/root/etc/init.d/alist @@ -103,7 +103,7 @@ start_service() { "force_https": false, "cert_file": "$ssl_cert", "key_file": "$ssl_key", - "unix_file": "/var/alist.sock" + "unix_file": "/var/run/alist.sock" }, "temp_dir": "$temp_dir", "bleve_dir": "$data_dir/bleve", @@ -121,13 +121,15 @@ start_service() { } EOF - procd_open_instance alist + procd_open_instance procd_set_param command $PROG procd_append_param command server --data $data_dir procd_set_param stdout 0 procd_set_param stderr 0 procd_set_param respawn - procd_close_instance alist + procd_set_param limits core="unlimited" + procd_set_param limits nofile="200000 200000" + procd_close_instance } service_triggers() { diff --git a/sing-box/clients/android/build.gradle b/sing-box/clients/android/build.gradle index 68e7ea70d3..2a80751d96 100644 --- a/sing-box/clients/android/build.gradle +++ b/sing-box/clients/android/build.gradle @@ -5,8 +5,8 @@ buildscript { } plugins { - id 'com.android.application' version '8.3.0' apply false - id 'com.android.library' version '8.3.0' apply false + id 'com.android.application' version '8.3.1' apply false + id 'com.android.library' version '8.3.1' apply false id 'org.jetbrains.kotlin.android' version '1.9.0' apply false id 'com.google.devtools.ksp' version '1.9.0-1.0.12' apply false id 'com.github.triplet.play' version '3.8.4' apply false diff --git a/sing-box/clients/android/version.properties b/sing-box/clients/android/version.properties index 7dac9df35f..5229687e55 100644 --- a/sing-box/clients/android/version.properties +++ b/sing-box/clients/android/version.properties @@ -1,3 +1,3 @@ -VERSION_CODE=305 +VERSION_CODE=307 VERSION_NAME=1.8.10 GO_VERSION=go1.22.1 diff --git a/sing-box/go.mod b/sing-box/go.mod index e882441480..da26de8154 100644 --- a/sing-box/go.mod +++ b/sing-box/go.mod @@ -33,7 +33,7 @@ require ( github.com/sagernet/sing-shadowsocks v0.2.6 github.com/sagernet/sing-shadowsocks2 v0.2.0 github.com/sagernet/sing-shadowtls v0.1.4 - github.com/sagernet/sing-tun v0.2.5-beta.2 + github.com/sagernet/sing-tun v0.2.6-beta.1 github.com/sagernet/sing-vmess v0.1.8 github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 diff --git a/sing-box/go.sum b/sing-box/go.sum index d8c1b2874d..25eefe59a5 100644 --- a/sing-box/go.sum +++ b/sing-box/go.sum @@ -123,8 +123,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wK github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= -github.com/sagernet/sing-tun v0.2.5-beta.2 h1:mOWW80jYEup8LIFG3VuWASWgiRzyusuX5kH+Lbl+V7s= -github.com/sagernet/sing-tun v0.2.5-beta.2/go.mod h1:E+KwQKzYkdGEhfIxjmoaB1ZkADaxeXUNzx6GRDRKOfE= +github.com/sagernet/sing-tun v0.2.6-beta.1 h1:6yfOJQaa706/VAKb7SVa8ziXppTxVOg/p9p63qk2N/o= +github.com/sagernet/sing-tun v0.2.6-beta.1/go.mod h1:E+KwQKzYkdGEhfIxjmoaB1ZkADaxeXUNzx6GRDRKOfE= github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc= github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= diff --git a/small/gn/Makefile b/small/gn/Makefile index bc6fc1ed73..43f79c89b2 100644 --- a/small/gn/Makefile +++ b/small/gn/Makefile @@ -9,9 +9,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://gn.googlesource.com/gn.git -PKG_SOURCE_DATE:=2024-03-08 -PKG_SOURCE_VERSION:=59c4bb920542ee903ee1df39097ae024e2e8226f -PKG_MIRROR_HASH:=604096e2804bd49b9d2ed6c6aaea1101db0d475a20ebfd2693dc4082e88cbdf6 +PKG_SOURCE_DATE:=2024-03-21 +PKG_SOURCE_VERSION:=06cdcc8e1fa8e56f70efb4357d473345b7d1c083 +PKG_MIRROR_HASH:=98a72b8a4e4a7d50da27821a5ee42417f19f3a8ab4382297362168676002ec06 PKG_LICENSE:=BSD 3-Clause PKG_LICENSE_FILES:=LICENSE diff --git a/small/gn/src/out/last_commit_position.h b/small/gn/src/out/last_commit_position.h index 4b1262a4e2..fa7bc26a9d 100644 --- a/small/gn/src/out/last_commit_position.h +++ b/small/gn/src/out/last_commit_position.h @@ -3,7 +3,7 @@ #ifndef OUT_LAST_COMMIT_POSITION_H_ #define OUT_LAST_COMMIT_POSITION_H_ -#define LAST_COMMIT_POSITION_NUM 2157 -#define LAST_COMMIT_POSITION "2157 (59c4bb920542)" +#define LAST_COMMIT_POSITION_NUM 2159 +#define LAST_COMMIT_POSITION "2159 (06cdcc8e1fa8)" #endif // OUT_LAST_COMMIT_POSITION_H_ diff --git a/small/sing-box/Makefile b/small/sing-box/Makefile index cea9b2f556..891cf8d354 100644 --- a/small/sing-box/Makefile +++ b/small/sing-box/Makefile @@ -6,12 +6,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=sing-box -PKG_VERSION:=1.8.9 +PKG_VERSION:=1.8.10 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/SagerNet/sing-box/tar.gz/v$(PKG_VERSION)? -PKG_HASH:=764c51bdf43af86e67b2657baf87bf67a2e1d8e42b0d39ee9ef7a9a414c658fc +PKG_HASH:=a959f9a40148ed4166b8161072672f3ce1532957adef7717132c7277bb96dcf6 PKG_LICENSE:=GPL-3.0-or-later PKG_LICENSE_FILES:=LICENSE diff --git a/suyu/.forgejo/workflows/ci.yml b/suyu/.forgejo/workflows/ci.yml index 25ef1f0789..143ad8982e 100644 --- a/suyu/.forgejo/workflows/ci.yml +++ b/suyu/.forgejo/workflows/ci.yml @@ -1,33 +1,37 @@ # SPDX-FileCopyrightText: 2021 yuzu Emulator Project +# SPDX-FileCopyrightText: 2024 suyu Emulator Project # SPDX-License-Identifier: GPL-2.0-or-later -name: yuzu-ci +# Actions Documentation: https://forgejo.org/docs/next/user/actions/#list-of-tasks-in-a-repository + +name: suyu-ci on: push: - branches: [ master ] + branches: [ "dev" ] tags: [ "*" ] pull_request: - branches: [ master ] + branches: [ "dev" ] jobs: - transifex: - runs-on: ubuntu-latest - container: yuzuemu/build-environments:linux-transifex - if: ${{ github.repository == 'yuzu-emu/yuzu' && !github.head_ref }} - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - fetch-depth: 0 - - name: Update Translation - run: ./.ci/scripts/transifex/docker.sh - env: - TX_TOKEN: ${{ secrets.TRANSIFEX_API_TOKEN }} +# transifex: +# runs-on: ubuntu-latest +# container: fijxu/build-environments:linux-transifex +# if: ${{ GITHUB_REPOSITORY == 'suyu/suyu' && !GITHUB_HEAD_REF }} +# steps: +# - uses: https://code.forgejo.org/actions/checkout@v3 +# with: +# submodules: recursive +# fetch-depth: 0 +# - name: Update Translation +# run: ./.ci/scripts/transifex/docker.sh +# env: +# TX_TOKEN: ${{ secrets.TRANSIFEX_API_TOKEN }} reuse: runs-on: ubuntu-latest - if: ${{ github.repository == 'yuzu-emu/yuzu' }} + if: ${{ github.repository == 'suyu/suyu' }} steps: - - uses: actions/checkout@v3 - - uses: fsfe/reuse-action@v1 + - uses: https://code.forgejo.org/actions/checkout@v3 + - uses: https://github.com/fsfe/reuse-action@v1 + diff --git a/suyu/.forgejo/workflows/codespell.yml b/suyu/.forgejo/workflows/codespell.yml index 76fb7ef48c..bf6d35d1e8 100644 --- a/suyu/.forgejo/workflows/codespell.yml +++ b/suyu/.forgejo/workflows/codespell.yml @@ -9,7 +9,13 @@ # Actions Documentation: https://forgejo.org/docs/next/user/actions/#list-of-tasks-in-a-repository name: codespell -on: pull_request +on: + push: + branches: [ "*" ] + tags: [ "*" ] + pull_request: + branches: [ "*" ] + permissions: {} jobs: codespell: @@ -20,3 +26,4 @@ jobs: with: persist-credentials: false - uses: https://github.com/codespell-project/actions-codespell@master + diff --git a/suyu/.forgejo/workflows/verify.yml b/suyu/.forgejo/workflows/verify.yml index a9e28eefd0..e379168033 100644 --- a/suyu/.forgejo/workflows/verify.yml +++ b/suyu/.forgejo/workflows/verify.yml @@ -1,30 +1,39 @@ # SPDX-FileCopyrightText: 2022 yuzu Emulator Project +# SPDX-FileCopyrightText: 2024 suyu Emulator Project # SPDX-License-Identifier: GPL-3.0-or-later -name: 'yuzu verify' +# Actions Documentation: https://forgejo.org/docs/next/user/actions/#list-of-tasks-in-a-repository + +name: 'suyu verify' on: pull_request: - branches: [ master ] + branches: [ "dev" ] + push: + branches: [ "dev" ] env: PR_NUMBER: pr${{ github.event.number }} + CCACHE_DIR: '.ccache' + jobs: format: - name: 'verify format' + name: 'Verify Format' runs-on: ubuntu-latest + container: + image: fijxu/build-environments:linux-clang-format steps: - - uses: actions/checkout@v3 + - uses: https://code.forgejo.org/actions/checkout@v3 with: submodules: false - - name: set up JDK 17 - uses: actions/setup-java@v3 - with: - java-version: '17' - distribution: 'temurin' + # - name: set up JDK 17 + # uses: https://github.com/actions/setup-java@v3 + # with: + # java-version: '17' + # distribution: 'temurin' - name: 'Verify Formatting' run: bash -ex ./.ci/scripts/format/script.sh - build: + build-linux: name: 'test build' needs: format runs-on: ubuntu-latest @@ -39,24 +48,24 @@ jobs: - type: windows image: linux-mingw container: - image: yuzuemu/build-environments:${{ matrix.image }} + image: fijxu/build-environments:${{ matrix.image }} options: -u 1001 steps: - - uses: actions/checkout@v3 + - uses: https://code.forgejo.org/actions/checkout@v3 with: submodules: recursive fetch-depth: 0 - name: Set up cache - uses: actions/cache@v3 + uses: https://code.forgejo.org/actions/cache@v3 id: ccache-restore with: - path: ~/.ccache + path: .ccache key: ${{ runner.os }}-${{ matrix.type }}-${{ github.sha }} restore-keys: | ${{ runner.os }}-${{ matrix.type }}- - name: Create ccache directory if: steps.ccache-restore.outputs.cache-hit != 'true' - run: mkdir -p ~/.ccache + run: mkdir -p .ccache - name: Build run: ./.ci/scripts/${{ matrix.type }}/docker.sh env: @@ -66,112 +75,112 @@ jobs: env: NO_SOURCE_PACK: "YES" - name: Upload - uses: actions/upload-artifact@v3 + uses: https://code.forgejo.org/actions/upload-artifact@v3 with: name: ${{ matrix.type }} path: artifacts/ - build-mac: - name: 'test build (macos)' - needs: format - runs-on: macos-14 - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - fetch-depth: 0 - - name: Install dependencies - run: | - brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd - - name: Build - run: | - mkdir build - cd build - export Qt5_DIR="$(brew --prefix qt@5)/lib/cmake" - cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DSUYU_USE_BUNDLED_VCPKG=OFF -DSUYU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF - ninja - build-msvc: - name: 'test build (windows, msvc)' - needs: format - runs-on: windows-2022 - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - fetch-depth: 0 - - name: Set up cache - uses: actions/cache@v3 - with: - path: ~/.buildcache - key: ${{ runner.os }}-msvc-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-msvc- - - name: Install dependencies - shell: pwsh - run: | - $ErrorActionPreference = "Stop" - $BuildCacheVer = "v0.28.4" - $File = "buildcache-windows.zip" - $Uri = "https://github.com/mbitsnbites/buildcache/releases/download/$BuildCacheVer/$File" - $WebClient = New-Object System.Net.WebClient - $WebClient.DownloadFile($Uri, $File) - 7z x $File - $CurrentDir = Convert-Path . - echo "$CurrentDir/buildcache/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - - name: Install Vulkan SDK - shell: pwsh - run: .\.ci\scripts\windows\install-vulkan-sdk.ps1 - - name: Set up MSVC - uses: ilammy/msvc-dev-cmd@v1 - - name: Configure - env: - CC: cl.exe - CXX: cl.exe - run: | - glslangValidator --version - mkdir build - cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DSUYU_USE_BUNDLED_QT=1 -DSUYU_USE_BUNDLED_SDL2=1 -DSUYU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DSUYU_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DGIT_BRANCH=pr-verify -DSUYU_CRASH_DUMPS=ON - - name: Build - run: cmake --build build - - name: Cache Summary - run: buildcache -s - - name: Pack - shell: pwsh - run: .\.ci\scripts\windows\upload.ps1 - - name: Upload - uses: actions/upload-artifact@v3 - with: - name: msvc - path: artifacts/ - - name: Upload EXE - uses: actions/upload-artifact@v3 - with: - name: ${{ env.INDIVIDUAL_EXE }} - path: ${{ env.INDIVIDUAL_EXE }} + # build-mac: + # name: 'test build (macos)' + # needs: format + # runs-on: macos-14 + # steps: + # - uses: https://code.forgejo.org/actions/checkout@v3 + # with: + # submodules: recursive + # fetch-depth: 0 + # - name: Install dependencies + # run: | + # brew install autoconf automake boost ccache ffmpeg fmt glslang hidapi libtool libusb lz4 ninja nlohmann-json openssl pkg-config qt@5 sdl2 speexdsp zlib zlib zstd + # - name: Build + # run: | + # mkdir build + # cd build + # export Qt5_DIR="$(brew --prefix qt@5)/lib/cmake" + # cmake .. -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DSUYU_USE_BUNDLED_VCPKG=OFF -DSUYU_TESTS=OFF -DENABLE_WEB_SERVICE=OFF -DENABLE_LIBUSB=OFF + # ninja + # build-msvc: + # name: 'test build (windows, msvc)' + # needs: format + # runs-on: windows-2022 + # steps: + # - uses: https://code.forgejo.org/actions/checkout@v3 + # with: + # submodules: recursive + # fetch-depth: 0 + # - name: Set up cache + # uses: https://code.forgejo.org/actions/cache@v3 + # with: + # path: ~/.buildcache + # key: ${{ runner.os }}-msvc-${{ github.sha }} + # restore-keys: | + # ${{ runner.os }}-msvc- + # - name: Install dependencies + # shell: pwsh + # run: | + # $ErrorActionPreference = "Stop" + # $BuildCacheVer = "v0.28.4" + # $File = "buildcache-windows.zip" + # $Uri = "https://github.com/mbitsnbites/buildcache/releases/download/$BuildCacheVer/$File" + # $WebClient = New-Object System.Net.WebClient + # $WebClient.DownloadFile($Uri, $File) + # 7z x $File + # $CurrentDir = Convert-Path . + # echo "$CurrentDir/buildcache/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + # - name: Install Vulkan SDK + # shell: pwsh + # run: .\.ci\scripts\windows\install-vulkan-sdk.ps1 + # - name: Set up MSVC + # uses: https://github.com/ilammy/msvc-dev-cmd@v1 + # - name: Configure + # env: + # CC: cl.exe + # CXX: cl.exe + # run: | + # glslangValidator --version + # mkdir build + # cmake . -B build -GNinja -DCMAKE_TOOLCHAIN_FILE="CMakeModules/MSVCCache.cmake" -DUSE_CCACHE=ON -DSUYU_USE_BUNDLED_QT=1 -DSUYU_USE_BUNDLED_SDL2=1 -DSUYU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DSUYU_ENABLE_COMPATIBILITY_REPORTING=ON -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DCMAKE_BUILD_TYPE=Release -DGIT_BRANCH=pr-verify -DSUYU_CRASH_DUMPS=ON + # - name: Build + # run: cmake --build build + # - name: Cache Summary + # run: buildcache -s + # - name: Pack + # shell: pwsh + # run: .\.ci\scripts\windows\upload.ps1 + # - name: Upload + # uses: https://code.forgejo.org/actions/upload-artifact@v3 + # with: + # name: msvc + # path: artifacts/ + # - name: Upload EXE + # uses: https://code.forgejo.org/actions/upload-artifact@v3 + # with: + # name: ${{ env.INDIVIDUAL_EXE }} + # path: ${{ env.INDIVIDUAL_EXE }} android: runs-on: ubuntu-latest needs: format steps: - - uses: actions/checkout@v3 + - uses: https://code.forgejo.org/actions/checkout@v3 with: submodules: recursive fetch-depth: 0 - name: set up JDK 17 - uses: actions/setup-java@v3 + uses: https://github.com/actions/setup-java@v3 with: java-version: '17' distribution: 'temurin' - name: Set up cache - uses: actions/cache@v3 + uses: https://code.forgejo.org/actions/cache@v3 with: path: | ~/.gradle/caches ~/.gradle/wrapper - ~/.ccache + .ccache key: ${{ runner.os }}-android-${{ github.sha }} restore-keys: | ${{ runner.os }}-android- - name: Query tag name - uses: olegtarasov/get-tag@v2.1.2 + uses: https://github.com/olegtarasov/get-tag@v2.1.2 id: tagName - name: Install dependencies run: | @@ -186,7 +195,8 @@ jobs: ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }} run: ./.ci/scripts/android/upload.sh - name: Upload - uses: actions/upload-artifact@v3 + uses: https://code.forgejo.org/actions/upload-artifact@v3 with: name: android path: artifacts/ + diff --git a/suyu/.gitmodules b/suyu/.gitmodules index 318fa81c66..d9fbaf3971 100644 --- a/suyu/.gitmodules +++ b/suyu/.gitmodules @@ -9,22 +9,22 @@ url = https://github.com/mozilla/cubeb.git [submodule "dynarmic"] path = externals/dynarmic - url = https://gitlab.com/suyu-emu/dynarmic.git + url = https://git.suyu.dev/suyu/dynarmic.git [submodule "libusb"] path = externals/libusb/libusb url = https://github.com/libusb/libusb.git [submodule "discord-rpc"] path = externals/discord-rpc - url = https://gitlab.com/suyu-emu/discord-rpc.git + url = https://git.suyu.dev/suyu/discord-rpc.git [submodule "Vulkan-Headers"] path = externals/Vulkan-Headers url = https://github.com/KhronosGroup/Vulkan-Headers.git [submodule "sirit"] path = externals/sirit - url = https://gitlab.com/suyu-emu/sirit.git + url = https://git.suyu.dev/suyu/sirit.git [submodule "mbedtls"] path = externals/mbedtls - url = https://gitlab.com/suyu-emu/mbedtls.git + url = https://git.suyu.dev/suyu/mbedtls.git [submodule "xbyak"] path = externals/xbyak url = https://github.com/herumi/xbyak.git @@ -57,7 +57,7 @@ url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git [submodule "breakpad"] path = externals/breakpad - url = https://gitlab.com/suyu-emu/breakpad.git + url = https://git.suyu.dev/suyu/breakpad.git [submodule "simpleini"] path = externals/simpleini url = https://github.com/brofield/simpleini.git diff --git a/suyu/README.md b/suyu/README.md index c50c7bceba..0f6657592a 100644 --- a/suyu/README.md +++ b/suyu/README.md @@ -1,6 +1,6 @@ **Note**: We do not support or condone piracy in any form. In order to use suyu, you'll need keys from your real Switch system, and games which you have legally obtained and paid for. We do not intend to make money or profit from this project. @@ -60,8 +60,10 @@ We have official builds [here.](https://git.suyu.dev/suyu/suyu/releases) If any ## Building -* __Windows__: [Wiki page](https://git.suyu.dev/suyu/suyu/wiki/Building-for-Windows) -* __Linux__: [Wiki page](https://git.suyu.dev/suyu/suyu/wiki/Building-for-Linux) +* __Windows__: [Windows Build](https://git.suyu.dev/suyu/suyu/wiki/Building-For-Windows) +* __Linux__: [Linux Build](https://git.suyu.dev/suyu/suyu/wiki/Building-For-Linux) +* __Android__: [Android Build](https://git.suyu.dev/suyu/suyu/wiki/Building-For-Android) +* __MacOS__: [MacOS Build](https://git.suyu.dev/suyu/suyu/wiki/Building-for-macOS) @@ -72,4 +74,4 @@ If you have any questions, don't hesitate to ask us on [Discord](https://discord ## License -suyu is licensed under the free and open-source GPL v3 license. +suyu is licensed under the free and open-source GPL-3.0-or-later license. diff --git a/suyu/src/suyu/main.cpp b/suyu/src/suyu/main.cpp index 0d07c8d6d0..0d6189a8e9 100644 --- a/suyu/src/suyu/main.cpp +++ b/suyu/src/suyu/main.cpp @@ -12,6 +12,7 @@ #include #include "core/hle/service/am/applet_manager.h" #include "core/loader/nca.h" +#include "core/loader/nro.h" #include "core/tools/renderdoc.h" #ifdef __APPLE__ @@ -1747,18 +1748,21 @@ void GMainWindow::AllowOSSleep() { } bool GMainWindow::LoadROM(const QString& filename, Service::AM::FrontendAppletParameters params) { - if (!CheckFirmwarePresence()) { - QMessageBox::critical(this, tr("Component Missing"), tr("Missing Firmware.")); - return false; - } + if (Loader::AppLoader_NRO::IdentifyType(Core::GetGameFileFromPath(vfs, filename.toStdString())) != + Loader::FileType::NRO) { + if (!CheckFirmwarePresence()) { + QMessageBox::critical(this, tr("Component Missing"), tr("Missing Firmware.")); + return false; + } - if (!ContentManager::AreKeysPresent()) { - QMessageBox::warning(this, tr("Derivation Components Missing"), - tr("Encryption keys are missing. " - "In order to use this emulator" - "you need to provide your own encryption keys" - "in order to play them.")); - return false; + if (!ContentManager::AreKeysPresent()) { + QMessageBox::warning(this, tr("Derivation Components Missing"), + tr("Encryption keys are missing. " + "In order to use this emulator, " + "you need to provide your own encryption keys " + "in order to play them.")); + return false; + } } // Shutdown previous session if the emu thread is still active... @@ -4630,8 +4634,8 @@ void GMainWindow::OnCheckFirmwareDecryption() { if (!ContentManager::AreKeysPresent()) { QMessageBox::warning(this, tr("Derivation Components Missing"), tr("Encryption keys are missing. " - "In order to use this emulator" - "you need to provide your own encryption keys" + "In order to use this emulator, " + "you need to provide your own encryption keys " "in order to play them.")); } diff --git a/suyu/src/video_core/vulkan_common/vulkan_device.h b/suyu/src/video_core/vulkan_common/vulkan_device.h index 79f62b9241..15dc7b789c 100644 --- a/suyu/src/video_core/vulkan_common/vulkan_device.h +++ b/suyu/src/video_core/vulkan_common/vulkan_device.h @@ -702,7 +702,7 @@ public: return properties.driver.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY; } - /// Checks if we are runing MolvenVK. + /// Checks if we are running MolvenVK. bool IsMoltenVK() const noexcept { return properties.driver.driverID == VK_DRIVER_ID_MOLTENVK; } diff --git a/v2rayn/v2rayN/v2rayN/Common/DownloaderHelper.cs b/v2rayn/v2rayN/v2rayN/Common/DownloaderHelper.cs index 9ae47282de..9f4fe96386 100644 --- a/v2rayn/v2rayN/v2rayN/Common/DownloaderHelper.cs +++ b/v2rayn/v2rayN/v2rayN/Common/DownloaderHelper.cs @@ -11,7 +11,7 @@ namespace v2rayN public async Task DownloadStringAsync(IWebProxy? webProxy, string url, string? userAgent, int timeout) { - if (string.IsNullOrEmpty(url)) + if (Utile.IsNullOrEmpty(url)) { return null; } @@ -57,7 +57,7 @@ namespace v2rayN public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress progress, int timeout) { - if (string.IsNullOrEmpty(url)) + if (Utile.IsNullOrEmpty(url)) { throw new ArgumentNullException(nameof(url)); } @@ -120,11 +120,11 @@ namespace v2rayN public async Task DownloadFileAsync(IWebProxy? webProxy, string url, string fileName, IProgress progress, int timeout) { - if (string.IsNullOrEmpty(url)) + if (Utile.IsNullOrEmpty(url)) { throw new ArgumentNullException(nameof(url)); } - if (string.IsNullOrEmpty(fileName)) + if (Utile.IsNullOrEmpty(fileName)) { throw new ArgumentNullException(nameof(fileName)); } diff --git a/v2rayn/v2rayN/v2rayN/Common/HttpClientHelper.cs b/v2rayn/v2rayN/v2rayN/Common/HttpClientHelper.cs index 8f541c99d4..51707be5ea 100644 --- a/v2rayn/v2rayN/v2rayN/Common/HttpClientHelper.cs +++ b/v2rayn/v2rayN/v2rayN/Common/HttpClientHelper.cs @@ -23,13 +23,13 @@ namespace v2rayN public async Task GetAsync(string url) { - if (string.IsNullOrEmpty(url)) return null; + if (Utile.IsNullOrEmpty(url)) return null; return await httpClient.GetStringAsync(url); } public async Task GetAsync(HttpClient client, string url, CancellationToken token = default) { - if (string.IsNullOrWhiteSpace(url)) return null; + if (Utile.IsNullOrEmpty(url)) return null; return await client.GetStringAsync(url, token); } @@ -88,7 +88,7 @@ namespace v2rayN public async Task DownloadDataAsync4Speed(HttpClient client, string url, IProgress progress, CancellationToken token = default) { - if (string.IsNullOrEmpty(url)) + if (Utile.IsNullOrEmpty(url)) { throw new ArgumentNullException(nameof(url)); } diff --git a/v2rayn/v2rayN/v2rayN/Common/JsonUtile.cs b/v2rayn/v2rayN/v2rayN/Common/JsonUtile.cs index bf585cbdb6..1c76fc4e25 100644 --- a/v2rayn/v2rayN/v2rayN/Common/JsonUtile.cs +++ b/v2rayn/v2rayN/v2rayN/Common/JsonUtile.cs @@ -28,7 +28,7 @@ namespace v2rayN { try { - if (string.IsNullOrEmpty(strJson)) + if (string.IsNullOrWhiteSpace(strJson)) { return default; } @@ -49,7 +49,7 @@ namespace v2rayN { try { - if (string.IsNullOrEmpty(strJson)) + if (string.IsNullOrWhiteSpace(strJson)) { return null; } diff --git a/v2rayn/v2rayN/v2rayN/Common/Utile.cs b/v2rayn/v2rayN/v2rayN/Common/Utile.cs index 13e0b0e394..672b576333 100644 --- a/v2rayn/v2rayN/v2rayN/Common/Utile.cs +++ b/v2rayn/v2rayN/v2rayN/Common/Utile.cs @@ -361,7 +361,7 @@ namespace v2rayN /// public static string GetPunycode(string url) { - if (string.IsNullOrWhiteSpace(url)) + if (Utile.IsNullOrEmpty(url)) { return url; } @@ -391,7 +391,7 @@ namespace v2rayN public static string Convert2Comma(string text) { - if (string.IsNullOrWhiteSpace(text)) + if (Utile.IsNullOrEmpty(text)) { return text; } @@ -428,7 +428,7 @@ namespace v2rayN /// public static bool IsNullOrEmpty(string? text) { - if (string.IsNullOrEmpty(text)) + if (string.IsNullOrWhiteSpace(text)) { return true; } @@ -840,7 +840,7 @@ namespace v2rayN { Directory.CreateDirectory(_tempPath); } - if (string.IsNullOrEmpty(filename)) + if (Utile.IsNullOrEmpty(filename)) { return _tempPath; } @@ -876,7 +876,7 @@ namespace v2rayN { Directory.CreateDirectory(_tempPath); } - if (string.IsNullOrEmpty(filename)) + if (Utile.IsNullOrEmpty(filename)) { return _tempPath; } @@ -901,7 +901,7 @@ namespace v2rayN Directory.CreateDirectory(_tempPath); } } - if (string.IsNullOrEmpty(filename)) + if (Utile.IsNullOrEmpty(filename)) { return _tempPath; } @@ -918,7 +918,7 @@ namespace v2rayN { Directory.CreateDirectory(_tempPath); } - if (string.IsNullOrEmpty(filename)) + if (Utile.IsNullOrEmpty(filename)) { return _tempPath; } @@ -935,7 +935,7 @@ namespace v2rayN { Directory.CreateDirectory(_tempPath); } - if (string.IsNullOrEmpty(filename)) + if (Utile.IsNullOrEmpty(filename)) { return _tempPath; } @@ -1107,7 +1107,7 @@ namespace v2rayN /// public static void AutoStart(string taskName, string fileName, string description) { - if (string.IsNullOrEmpty(taskName)) + if (Utile.IsNullOrEmpty(taskName)) { return; } @@ -1122,7 +1122,7 @@ namespace v2rayN { taskService.RootFolder.DeleteTask(t.Name); } - if (string.IsNullOrEmpty(fileName)) + if (Utile.IsNullOrEmpty(fileName)) { return; } diff --git a/v2rayn/v2rayN/v2rayN/Converters/MaterialDesignFonts.cs b/v2rayn/v2rayN/v2rayN/Converters/MaterialDesignFonts.cs index 313182db0d..938db7cc85 100644 --- a/v2rayn/v2rayN/v2rayN/Converters/MaterialDesignFonts.cs +++ b/v2rayn/v2rayN/v2rayN/Converters/MaterialDesignFonts.cs @@ -12,7 +12,7 @@ namespace v2rayN.Converters try { var fontFamily = LazyConfig.Instance.GetConfig().uiItem.currentFontFamily; - if (!string.IsNullOrEmpty(fontFamily)) + if (!Utile.IsNullOrEmpty(fontFamily)) { var fontPath = Utile.GetFontsPath(); MyFont = new FontFamily(new Uri(@$"file:///{fontPath}\"), $"./#{fontFamily}"); diff --git a/v2rayn/v2rayN/v2rayN/Handler/ConfigHandler.cs b/v2rayn/v2rayN/v2rayN/Handler/ConfigHandler.cs index 4d18e528da..4b430705e8 100644 --- a/v2rayn/v2rayN/v2rayN/Handler/ConfigHandler.cs +++ b/v2rayn/v2rayN/v2rayN/Handler/ConfigHandler.cs @@ -1177,6 +1177,46 @@ namespace v2rayN.Handler return false; } + //Is v2ray array configuration + var configObjects = JsonUtile.Deserialize(clipboardData); + if (configObjects != null && configObjects.Length > 0) + { + if (isSub && !Utile.IsNullOrEmpty(subid)) + { + RemoveServerViaSubid(config, subid, isSub); + } + + int count = 0; + foreach (var configObject in configObjects) + { + var objectString = JsonUtile.Serialize(configObject); + var v2rayCon = JsonUtile.Deserialize(objectString); + if (v2rayCon?.inbounds?.Count > 0 && v2rayCon.outbounds?.Count > 0) + { + var fileName = Utile.GetTempPath($"{Utile.GetGUID(false)}.json"); + File.WriteAllText(fileName, objectString); + + var profileIt = new ProfileItem + { + coreType = ECoreType.Xray, + address = fileName, + remarks = v2rayCon.remarks ?? "v2ray_custom", + subid = subid, + isSub = isSub + }; + + if (AddCustomServer(config, profileIt, true) == 0) + { + count++; + } + } + } + if (count > 0) + { + return count; + } + } + ProfileItem profileItem = new(); //Is v2ray configuration var v2rayConfig = JsonUtile.Deserialize(clipboardData); @@ -1188,7 +1228,7 @@ namespace v2rayN.Handler profileItem.coreType = ECoreType.Xray; profileItem.address = fileName; - profileItem.remarks = "v2ray_custom"; + profileItem.remarks = v2rayConfig.remarks ?? "v2ray_custom"; } //Is Clash configuration else if (Contains(clipboardData, "port", "socks-port", "proxies")) diff --git a/v2rayn/v2rayN/v2rayN/Handler/CoreConfigSingbox.cs b/v2rayn/v2rayN/v2rayN/Handler/CoreConfigSingbox.cs index ece9e17ac4..ab6177ee99 100644 --- a/v2rayn/v2rayN/v2rayN/Handler/CoreConfigSingbox.cs +++ b/v2rayn/v2rayN/v2rayN/Handler/CoreConfigSingbox.cs @@ -354,11 +354,11 @@ namespace v2rayN.Handler if (node.streamSecurity == Global.StreamSecurityReality || node.streamSecurity == Global.StreamSecurity) { var server_name = string.Empty; - if (!string.IsNullOrWhiteSpace(node.sni)) + if (!Utile.IsNullOrEmpty(node.sni)) { server_name = node.sni; } - else if (!string.IsNullOrWhiteSpace(node.requestHost)) + else if (!Utile.IsNullOrEmpty(node.requestHost)) { server_name = Utile.String2List(node.requestHost)[0]; } @@ -761,7 +761,7 @@ namespace v2rayN.Handler { var item = LazyConfig.Instance.GetDNSItem(ECoreType.sing_box); var tunDNS = item?.tunDNS; - if (string.IsNullOrWhiteSpace(tunDNS)) + if (Utile.IsNullOrEmpty(tunDNS)) { tunDNS = Utile.GetEmbedText(Global.TunSingboxDNSFileName); } @@ -771,7 +771,7 @@ namespace v2rayN.Handler { var item = LazyConfig.Instance.GetDNSItem(ECoreType.sing_box); var normalDNS = item?.normalDNS; - if (string.IsNullOrWhiteSpace(normalDNS)) + if (Utile.IsNullOrEmpty(normalDNS)) { normalDNS = "{\"servers\":[{\"address\":\"tcp://8.8.8.8\"}]}"; } @@ -972,6 +972,13 @@ namespace v2rayN.Handler singboxConfig.route.rules.Add(rule); } + GenDns(new(), singboxConfig); + var dnsServer = singboxConfig.dns?.servers.FirstOrDefault(); + if (dnsServer != null) + { + dnsServer.detour = singboxConfig.route.rules.LastOrDefault()?.outbound; + } + //msg = string.Format(ResUI.SuccessfulConfiguration"), node.getSummary()); return 0; } diff --git a/v2rayn/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs b/v2rayn/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs index 93db1bc915..e882078cb5 100644 --- a/v2rayn/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs +++ b/v2rayn/v2rayN/v2rayN/Handler/CoreConfigV2ray.cs @@ -533,11 +533,11 @@ namespace v2rayN.Handler alpn = node.GetAlpn(), fingerprint = node.fingerprint.IsNullOrEmpty() ? _config.coreBasicItem.defFingerprint : node.fingerprint }; - if (!string.IsNullOrWhiteSpace(sni)) + if (!Utile.IsNullOrEmpty(sni)) { tlsSettings.serverName = sni; } - else if (!string.IsNullOrWhiteSpace(host)) + else if (!Utile.IsNullOrEmpty(host)) { tlsSettings.serverName = Utile.String2List(host)[0]; } @@ -592,15 +592,15 @@ namespace v2rayN.Handler WsSettings4Ray wsSettings = new(); wsSettings.headers = new Headers4Ray(); string path = node.path; - if (!string.IsNullOrWhiteSpace(host)) + if (!Utile.IsNullOrEmpty(host)) { wsSettings.headers.Host = host; } - if (!string.IsNullOrWhiteSpace(path)) + if (!Utile.IsNullOrEmpty(path)) { wsSettings.path = path; } - if (!string.IsNullOrWhiteSpace(useragent)) + if (!Utile.IsNullOrEmpty(useragent)) { wsSettings.headers.UserAgent = useragent; } @@ -611,11 +611,11 @@ namespace v2rayN.Handler case nameof(ETransport.httpupgrade): HttpupgradeSettings4Ray httpupgradeSettings = new(); - if (!string.IsNullOrWhiteSpace(node.path)) + if (!Utile.IsNullOrEmpty(node.path)) { httpupgradeSettings.path = node.path; } - if (!string.IsNullOrWhiteSpace(host)) + if (!Utile.IsNullOrEmpty(host)) { httpupgradeSettings.host = host; } @@ -626,7 +626,7 @@ namespace v2rayN.Handler case nameof(ETransport.h2): HttpSettings4Ray httpSettings = new(); - if (!string.IsNullOrWhiteSpace(host)) + if (!Utile.IsNullOrEmpty(host)) { httpSettings.host = Utile.String2List(host); } @@ -649,7 +649,7 @@ namespace v2rayN.Handler streamSettings.quicSettings = quicsettings; if (node.streamSecurity == Global.StreamSecurity) { - if (!string.IsNullOrWhiteSpace(sni)) + if (!Utile.IsNullOrEmpty(sni)) { streamSettings.tlsSettings.serverName = sni; } @@ -663,6 +663,7 @@ namespace v2rayN.Handler case nameof(ETransport.grpc): GrpcSettings4Ray grpcSettings = new() { + authority = Utile.IsNullOrEmpty(host) ? null : host, serviceName = node.path, multiMode = (node.headerType == Global.GrpcMultiMode), idle_timeout = _config.grpcItem.idle_timeout, @@ -721,13 +722,13 @@ namespace v2rayN.Handler var item = LazyConfig.Instance.GetDNSItem(ECoreType.Xray); var normalDNS = item?.normalDNS; var domainStrategy4Freedom = item?.domainStrategy4Freedom; - if (string.IsNullOrWhiteSpace(normalDNS)) + if (Utile.IsNullOrEmpty(normalDNS)) { normalDNS = "1.1.1.1,8.8.8.8"; } //Outbound Freedom domainStrategy - if (!string.IsNullOrWhiteSpace(domainStrategy4Freedom)) + if (!Utile.IsNullOrEmpty(domainStrategy4Freedom)) { var outbound = v2rayConfig.outbounds[1]; outbound.settings.domainStrategy = domainStrategy4Freedom; diff --git a/v2rayn/v2rayN/v2rayN/Handler/CoreHandler.cs b/v2rayn/v2rayN/v2rayN/Handler/CoreHandler.cs index 3f6582dc53..2105842b46 100644 --- a/v2rayn/v2rayN/v2rayN/Handler/CoreHandler.cs +++ b/v2rayn/v2rayN/v2rayN/Handler/CoreHandler.cs @@ -292,7 +292,7 @@ namespace v2rayN.Handler { proc.OutputDataReceived += (sender, e) => { - if (!string.IsNullOrEmpty(e.Data)) + if (!Utile.IsNullOrEmpty(e.Data)) { string msg = e.Data + Environment.NewLine; ShowMsg(false, msg); @@ -300,7 +300,7 @@ namespace v2rayN.Handler }; proc.ErrorDataReceived += (sender, e) => { - if (!string.IsNullOrEmpty(e.Data)) + if (!Utile.IsNullOrEmpty(e.Data)) { string msg = e.Data + Environment.NewLine; ShowMsg(false, msg); diff --git a/v2rayn/v2rayN/v2rayN/Handler/ShareHandler.cs b/v2rayn/v2rayN/v2rayN/Handler/ShareHandler.cs index 1a3d85c132..ee41d262ff 100644 --- a/v2rayn/v2rayN/v2rayN/Handler/ShareHandler.cs +++ b/v2rayn/v2rayN/v2rayN/Handler/ShareHandler.cs @@ -364,6 +364,7 @@ namespace v2rayN.Handler case nameof(ETransport.grpc): if (!Utile.IsNullOrEmpty(item.path)) { + dicQuery.Add("authority", Utile.UrlEncode(item.requestHost)); dicQuery.Add("serviceName", Utile.UrlEncode(item.path)); if (item.headerType is Global.GrpcGunMode or Global.GrpcMultiMode) { @@ -592,7 +593,7 @@ namespace v2rayN.Handler break; default: - if (!string.IsNullOrWhiteSpace(i.streamSecurity)) + if (!Utile.IsNullOrEmpty(i.streamSecurity)) return null; break; } @@ -981,6 +982,7 @@ namespace v2rayN.Handler break; case nameof(ETransport.grpc): + item.requestHost = Utile.UrlDecode(query["authority"] ?? ""); item.path = Utile.UrlDecode(query["serviceName"] ?? ""); item.headerType = Utile.UrlDecode(query["mode"] ?? Global.GrpcGunMode); break; diff --git a/v2rayn/v2rayN/v2rayN/Handler/StatisticsSingbox.cs b/v2rayn/v2rayN/v2rayN/Handler/StatisticsSingbox.cs index 29de41feb2..10e29fc03d 100644 --- a/v2rayn/v2rayN/v2rayN/Handler/StatisticsSingbox.cs +++ b/v2rayn/v2rayN/v2rayN/Handler/StatisticsSingbox.cs @@ -84,7 +84,7 @@ namespace v2rayN.Handler while (!res.CloseStatus.HasValue) { var result = Encoding.UTF8.GetString(buffer, 0, res.Count); - if (!string.IsNullOrEmpty(result)) + if (!Utile.IsNullOrEmpty(result)) { ParseOutput(result, out ulong up, out ulong down); diff --git a/v2rayn/v2rayN/v2rayN/Handler/UpdateHandle.cs b/v2rayn/v2rayN/v2rayN/Handler/UpdateHandle.cs index 5d7a50dfc6..823e96cf83 100644 --- a/v2rayn/v2rayN/v2rayN/Handler/UpdateHandle.cs +++ b/v2rayn/v2rayN/v2rayN/Handler/UpdateHandle.cs @@ -207,7 +207,7 @@ namespace v2rayN.Handler //convert if (!Utile.IsNullOrEmpty(item.convertTarget)) { - var subConvertUrl = string.IsNullOrEmpty(config.constItem.subConvertUrl) ? Global.SubConvertUrls.FirstOrDefault() : config.constItem.subConvertUrl; + var subConvertUrl = Utile.IsNullOrEmpty(config.constItem.subConvertUrl) ? Global.SubConvertUrls.FirstOrDefault() : config.constItem.subConvertUrl; url = string.Format(subConvertUrl!, Utile.UrlEncode(url)); if (!url.Contains("target=")) { diff --git a/v2rayn/v2rayN/v2rayN/Model/V2rayConfig.cs b/v2rayn/v2rayN/v2rayN/Model/V2rayConfig.cs index a301efef4c..b99e2d7135 100644 --- a/v2rayn/v2rayN/v2rayN/Model/V2rayConfig.cs +++ b/v2rayn/v2rayN/v2rayN/Model/V2rayConfig.cs @@ -7,6 +7,11 @@ namespace v2rayN.Model /// public class V2rayConfig { + /// + /// Properties that do not belong to Ray + /// + public string? remarks { get; set; } + /// /// 日志配置 /// @@ -634,7 +639,8 @@ namespace v2rayN.Model public class GrpcSettings4Ray { - public string serviceName { get; set; } + public string? authority { get; set; } + public string? serviceName { get; set; } public bool multiMode { get; set; } public int idle_timeout { get; set; } public int health_check_timeout { get; set; } diff --git a/v2rayn/v2rayN/v2rayN/Resx/ResUI.Designer.cs b/v2rayn/v2rayN/v2rayN/Resx/ResUI.Designer.cs index 46b792cf08..10c8a1de4f 100644 --- a/v2rayn/v2rayN/v2rayN/Resx/ResUI.Designer.cs +++ b/v2rayn/v2rayN/v2rayN/Resx/ResUI.Designer.cs @@ -3283,6 +3283,15 @@ namespace v2rayN.Resx { } } + /// + /// 查找类似 *grpc Authority 的本地化字符串。 + /// + public static string TransportRequestHostTip5 { + get { + return ResourceManager.GetString("TransportRequestHostTip5", resourceCulture); + } + } + /// /// 查找类似 Ungrouped 的本地化字符串。 /// diff --git a/v2rayn/v2rayN/v2rayN/Resx/ResUI.resx b/v2rayn/v2rayN/v2rayN/Resx/ResUI.resx index 12cdb236f5..78eeb13f65 100644 --- a/v2rayn/v2rayN/v2rayN/Resx/ResUI.resx +++ b/v2rayn/v2rayN/v2rayN/Resx/ResUI.resx @@ -1195,4 +1195,7 @@ Test terminating... + + *grpc Authority + \ No newline at end of file diff --git a/v2rayn/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx b/v2rayn/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx index c694f7f2b9..b53aa46fc0 100644 --- a/v2rayn/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx +++ b/v2rayn/v2rayN/v2rayN/Resx/ResUI.zh-Hans.resx @@ -1192,4 +1192,7 @@ 测试终止中... + + *grpc Authority + \ No newline at end of file diff --git a/v2rayn/v2rayN/v2rayN/Resx/ResUI.zh-Hant.resx b/v2rayn/v2rayN/v2rayN/Resx/ResUI.zh-Hant.resx index 8b3e6ac2da..6e6ff80ed9 100644 --- a/v2rayn/v2rayN/v2rayN/Resx/ResUI.zh-Hant.resx +++ b/v2rayn/v2rayN/v2rayN/Resx/ResUI.zh-Hant.resx @@ -1165,4 +1165,7 @@ 測試終止中... + + *grpc Authority + \ No newline at end of file diff --git a/v2rayn/v2rayN/v2rayN/ViewModels/SubEditViewModel.cs b/v2rayn/v2rayN/v2rayN/ViewModels/SubEditViewModel.cs index ce20356f29..41da092b32 100644 --- a/v2rayn/v2rayN/v2rayN/ViewModels/SubEditViewModel.cs +++ b/v2rayn/v2rayN/v2rayN/ViewModels/SubEditViewModel.cs @@ -46,7 +46,7 @@ namespace v2rayN.ViewModels private void SaveSub() { string remarks = SelectedSource.remarks; - if (string.IsNullOrEmpty(remarks)) + if (Utile.IsNullOrEmpty(remarks)) { _noticeHandler?.Enqueue(ResUI.PleaseFillRemarks); return; diff --git a/v2rayn/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs b/v2rayn/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs index e79b2db3f9..6e0f5f86f8 100644 --- a/v2rayn/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs +++ b/v2rayn/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs @@ -346,6 +346,7 @@ namespace v2rayN.Views break; case nameof(ETransport.grpc): + tipRequestHost.Text = ResUI.TransportRequestHostTip5; tipPath.Text = ResUI.TransportPathTip4; tipHeaderType.Text = ResUI.TransportHeaderTypeTip4; labHeaderType.Visibility = Visibility.Hidden; diff --git a/v2rayn/v2rayN/v2rayN/Views/MsgView.xaml.cs b/v2rayn/v2rayN/v2rayN/Views/MsgView.xaml.cs index 6d207f924b..66c830914d 100644 --- a/v2rayn/v2rayN/v2rayN/Views/MsgView.xaml.cs +++ b/v2rayn/v2rayN/v2rayN/Views/MsgView.xaml.cs @@ -48,7 +48,7 @@ namespace v2rayN.Views var MsgFilter = cmbMsgFilter.Text.TrimEx(); if (MsgFilter != lastMsgFilter) lastMsgFilterNotAvailable = false; - if (!string.IsNullOrEmpty(MsgFilter) && !lastMsgFilterNotAvailable) + if (!Utile.IsNullOrEmpty(MsgFilter) && !lastMsgFilterNotAvailable) { try { diff --git a/xray-core/app/proxyman/config.pb.go b/xray-core/app/proxyman/config.pb.go index 7e142bfdc9..501908d0ea 100644 --- a/xray-core/app/proxyman/config.pb.go +++ b/xray-core/app/proxyman/config.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.33.0 -// protoc v4.23.1 +// protoc v5.26.0 // source: app/proxyman/config.proto package proxyman @@ -524,6 +524,7 @@ type SenderConfig struct { StreamSettings *internet.StreamConfig `protobuf:"bytes,2,opt,name=stream_settings,json=streamSettings,proto3" json:"stream_settings,omitempty"` ProxySettings *internet.ProxyConfig `protobuf:"bytes,3,opt,name=proxy_settings,json=proxySettings,proto3" json:"proxy_settings,omitempty"` MultiplexSettings *MultiplexingConfig `protobuf:"bytes,4,opt,name=multiplex_settings,json=multiplexSettings,proto3" json:"multiplex_settings,omitempty"` + ViaCidr string `protobuf:"bytes,5,opt,name=via_cidr,json=viaCidr,proto3" json:"via_cidr,omitempty"` } func (x *SenderConfig) Reset() { @@ -586,6 +587,13 @@ func (x *SenderConfig) GetMultiplexSettings() *MultiplexingConfig { return nil } +func (x *SenderConfig) GetViaCidr() string { + if x != nil { + return x.ViaCidr + } + return "" +} + type MultiplexingConfig struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -855,7 +863,7 @@ var file_app_proxyman_config_proto_rawDesc = []byte{ 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x52, 0x0d, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x10, 0x0a, 0x0e, 0x4f, 0x75, 0x74, 0x62, 0x6f, - 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xb0, 0x02, 0x0a, 0x0c, 0x53, 0x65, + 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0xcb, 0x02, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2d, 0x0a, 0x03, 0x76, 0x69, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x49, 0x50, 0x4f, 0x72, 0x44, 0x6f, @@ -874,26 +882,28 @@ var file_app_proxyman_config_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x2e, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x22, 0xa4, 0x01, 0x0a, - 0x12, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, - 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0b, 0x63, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, - 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x63, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, - 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, - 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, - 0x34, 0x34, 0x33, 0x2a, 0x23, 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6c, 0x73, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, - 0x07, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, - 0x78, 0x72, 0x61, 0x79, 0x2e, 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, - 0x6e, 0x50, 0x01, 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, - 0x70, 0x70, 0x2f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, - 0x61, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, - 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x6c, 0x65, 0x78, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x19, 0x0a, 0x08, + 0x76, 0x69, 0x61, 0x5f, 0x63, 0x69, 0x64, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x76, 0x69, 0x61, 0x43, 0x69, 0x64, 0x72, 0x22, 0xa4, 0x01, 0x0a, 0x12, 0x4d, 0x75, 0x6c, 0x74, + 0x69, 0x70, 0x6c, 0x65, 0x78, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, + 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x63, + 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, + 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, + 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x43, 0x6f, 0x6e, 0x63, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x63, 0x79, 0x12, 0x28, 0x0a, 0x0f, 0x78, 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x78, + 0x75, 0x64, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x55, 0x44, 0x50, 0x34, 0x34, 0x33, 0x2a, 0x23, + 0x0a, 0x0e, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x73, + 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x4c, + 0x53, 0x10, 0x01, 0x42, 0x55, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, + 0x61, 0x70, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x50, 0x01, 0x5a, 0x26, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, + 0x78, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x70, 0x72, + 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0xaa, 0x02, 0x11, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x41, 0x70, + 0x70, 0x2e, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x6d, 0x61, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/xray-core/app/proxyman/config.proto b/xray-core/app/proxyman/config.proto index 5d063ebaa0..fe18c378f6 100644 --- a/xray-core/app/proxyman/config.proto +++ b/xray-core/app/proxyman/config.proto @@ -91,6 +91,7 @@ message SenderConfig { xray.transport.internet.StreamConfig stream_settings = 2; xray.transport.internet.ProxyConfig proxy_settings = 3; MultiplexingConfig multiplex_settings = 4; + string via_cidr = 5; } message MultiplexingConfig { diff --git a/xray-core/app/proxyman/outbound/handler.go b/xray-core/app/proxyman/outbound/handler.go index 2df2b2c393..41713d0b8c 100644 --- a/xray-core/app/proxyman/outbound/handler.go +++ b/xray-core/app/proxyman/outbound/handler.go @@ -4,6 +4,8 @@ import ( "context" "errors" "io" + "math/rand" + gonet "net" "os" "github.com/xtls/xray-core/app/proxyman" @@ -269,7 +271,11 @@ func (h *Handler) Dial(ctx context.Context, dest net.Destination) (stat.Connecti outbound = new(session.Outbound) ctx = session.ContextWithOutbound(ctx, outbound) } - outbound.Gateway = h.senderSettings.Via.AsAddress() + if h.senderSettings.ViaCidr == "" { + outbound.Gateway = h.senderSettings.Via.AsAddress() + } else { //Get a random address. + outbound.Gateway = ParseRandomIPv6(h.senderSettings.Via.AsAddress(), h.senderSettings.ViaCidr) + } } } @@ -312,3 +318,17 @@ func (h *Handler) Close() error { common.Close(h.mux) return nil } + +// Return random IPv6 in a CIDR block +func ParseRandomIPv6(address net.Address, prefix string) net.Address { + addr := address.IP().String() + _, network, _ := gonet.ParseCIDR(addr + "/" + prefix) + + ipv6 := network.IP.To16() + prefixLen, _ := network.Mask.Size() + for i := prefixLen / 8; i < 16; i++ { + ipv6[i] = byte(rand.Intn(256)) + } + + return net.ParseAddress(gonet.IP(ipv6).String()) +} diff --git a/xray-core/infra/conf/transport_internet.go b/xray-core/infra/conf/transport_internet.go index 96b458ed79..3feb734773 100644 --- a/xray-core/infra/conf/transport_internet.go +++ b/xray-core/infra/conf/transport_internet.go @@ -183,6 +183,7 @@ func (c *WebSocketConfig) Build() (proto.Message, error) { type HttpUpgradeConfig struct { Path string `json:"path"` Host string `json:"host"` + Headers map[string]string `json:"headers"` AcceptProxyProtocol bool `json:"acceptProxyProtocol"` } @@ -202,6 +203,7 @@ func (c *HttpUpgradeConfig) Build() (proto.Message, error) { config := &httpupgrade.Config{ Path: path, Host: c.Host, + Header: c.Headers, AcceptProxyProtocol: c.AcceptProxyProtocol, Ed: ed, } diff --git a/xray-core/infra/conf/xray.go b/xray-core/infra/conf/xray.go index c99dca597e..645da473d0 100644 --- a/xray-core/infra/conf/xray.go +++ b/xray-core/infra/conf/xray.go @@ -11,6 +11,7 @@ import ( "github.com/xtls/xray-core/app/dispatcher" "github.com/xtls/xray-core/app/proxyman" "github.com/xtls/xray-core/app/stats" + "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/serial" core "github.com/xtls/xray-core/core" "github.com/xtls/xray-core/transport/internet" @@ -279,7 +280,7 @@ func (c *InboundDetourConfig) Build() (*core.InboundHandlerConfig, error) { type OutboundDetourConfig struct { Protocol string `json:"protocol"` - SendThrough *Address `json:"sendThrough"` + SendThrough *string `json:"sendThrough"` Tag string `json:"tag"` Settings *json.RawMessage `json:"settings"` StreamSetting *StreamConfig `json:"streamSettings"` @@ -305,9 +306,14 @@ func (c *OutboundDetourConfig) Build() (*core.OutboundHandlerConfig, error) { } if c.SendThrough != nil { - address := c.SendThrough - if address.Family().IsDomain() { - return nil, newError("unable to send through: " + address.String()) + address := ParseSendThough(c.SendThrough) + //Check if CIDR exists + if strings.Contains(*c.SendThrough, "/") { + senderSettings.ViaCidr = strings.Split(*c.SendThrough, "/")[1] + } else { + if address.Family().IsDomain() { + return nil, newError("unable to send through: " + address.String()) + } } senderSettings.Via = address.Build() } @@ -397,19 +403,19 @@ type Config struct { // and should not be used. OutboundDetours []OutboundDetourConfig `json:"outboundDetour"` - LogConfig *LogConfig `json:"log"` - RouterConfig *RouterConfig `json:"routing"` - DNSConfig *DNSConfig `json:"dns"` - InboundConfigs []InboundDetourConfig `json:"inbounds"` - OutboundConfigs []OutboundDetourConfig `json:"outbounds"` - Transport *TransportConfig `json:"transport"` - Policy *PolicyConfig `json:"policy"` - API *APIConfig `json:"api"` - Metrics *MetricsConfig `json:"metrics"` - Stats *StatsConfig `json:"stats"` - Reverse *ReverseConfig `json:"reverse"` - FakeDNS *FakeDNSConfig `json:"fakeDns"` - Observatory *ObservatoryConfig `json:"observatory"` + LogConfig *LogConfig `json:"log"` + RouterConfig *RouterConfig `json:"routing"` + DNSConfig *DNSConfig `json:"dns"` + InboundConfigs []InboundDetourConfig `json:"inbounds"` + OutboundConfigs []OutboundDetourConfig `json:"outbounds"` + Transport *TransportConfig `json:"transport"` + Policy *PolicyConfig `json:"policy"` + API *APIConfig `json:"api"` + Metrics *MetricsConfig `json:"metrics"` + Stats *StatsConfig `json:"stats"` + Reverse *ReverseConfig `json:"reverse"` + FakeDNS *FakeDNSConfig `json:"fakeDns"` + Observatory *ObservatoryConfig `json:"observatory"` BurstObservatory *BurstObservatoryConfig `json:"burstObservatory"` } @@ -717,3 +723,10 @@ func (c *Config) Build() (*core.Config, error) { return config, nil } + +// Convert string to Address. +func ParseSendThough(Addr *string) *Address { + var addr Address + addr.Address = net.ParseAddress(strings.Split(*Addr, "/")[0]) + return &addr +} diff --git a/xray-core/main/commands/all/api/balancer_info.go b/xray-core/main/commands/all/api/balancer_info.go index 4ba33236ad..0d376d63d6 100644 --- a/xray-core/main/commands/all/api/balancer_info.go +++ b/xray-core/main/commands/all/api/balancer_info.go @@ -43,12 +43,16 @@ Example: func executeBalancerInfo(cmd *base.Command, args []string) { setSharedFlags(cmd) cmd.Flag.Parse(args) + unnamedArgs := cmd.Flag.Args() + if len(unnamedArgs) == 0 { + fmt.Println("set balancer tag") + unnamedArgs = []string{""} + } conn, ctx, close := dialAPIServer() defer close() - client := routerService.NewRoutingServiceClient(conn) - r := &routerService.GetBalancerInfoRequest{Tag: args[0]} + r := &routerService.GetBalancerInfoRequest{Tag: unnamedArgs[0]} resp, err := client.GetBalancerInfo(ctx, r) if err != nil { base.Fatalf("failed to get health information: %s", err) @@ -75,9 +79,10 @@ func showBalancerInfo(b *routerService.BalancerMsg) { } // Selects sb.WriteString(" - Selects:\n") - - for i, o := range b.PrincipleTarget.Tag { - writeRow(sb, tableIndent, i+1, []string{o}, nil) + if b.PrincipleTarget != nil { + for i, o := range b.PrincipleTarget.Tag { + writeRow(sb, tableIndent, i+1, []string{o}, nil) + } } os.Stdout.WriteString(sb.String()) } diff --git a/xray-core/transport/internet/httpupgrade/config.pb.go b/xray-core/transport/internet/httpupgrade/config.pb.go index edd4e753fd..e265b09239 100644 --- a/xray-core/transport/internet/httpupgrade/config.pb.go +++ b/xray-core/transport/internet/httpupgrade/config.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.33.0 -// protoc v4.23.1 +// protoc v5.26.0 // source: transport/internet/httpupgrade/config.proto package httpupgrade @@ -25,10 +25,11 @@ type Config struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` - Host string `protobuf:"bytes,3,opt,name=host,proto3" json:"host,omitempty"` - AcceptProxyProtocol bool `protobuf:"varint,4,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` - Ed uint32 `protobuf:"varint,5,opt,name=ed,proto3" json:"ed,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` + Host string `protobuf:"bytes,3,opt,name=host,proto3" json:"host,omitempty"` + AcceptProxyProtocol bool `protobuf:"varint,4,opt,name=accept_proxy_protocol,json=acceptProxyProtocol,proto3" json:"accept_proxy_protocol,omitempty"` + Ed uint32 `protobuf:"varint,5,opt,name=ed,proto3" json:"ed,omitempty"` + Header map[string]string `protobuf:"bytes,6,rep,name=header,proto3" json:"header,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *Config) Reset() { @@ -91,6 +92,13 @@ func (x *Config) GetEd() uint32 { return 0 } +func (x *Config) GetHeader() map[string]string { + if x != nil { + return x.Header + } + return nil +} + var File_transport_internet_httpupgrade_config_proto protoreflect.FileDescriptor var file_transport_internet_httpupgrade_config_proto_rawDesc = []byte{ @@ -99,24 +107,33 @@ var file_transport_internet_httpupgrade_config_proto_rawDesc = []byte{ 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x75, 0x70, 0x67, 0x72, 0x61, - 0x64, 0x65, 0x22, 0x7a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, - 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, - 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x68, 0x6f, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x5f, 0x70, - 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, 0x78, 0x79, - 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x65, 0x64, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x65, 0x64, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x42, 0x8b, - 0x01, 0x0a, 0x27, 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, - 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, - 0x74, 0x74, 0x70, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x50, 0x01, 0x5a, 0x38, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, - 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, - 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x75, - 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0xaa, 0x02, 0x23, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, - 0x2e, 0x48, 0x74, 0x74, 0x70, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x64, 0x65, 0x22, 0x86, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, + 0x68, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x32, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x5f, + 0x70, 0x72, 0x6f, 0x78, 0x79, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x50, 0x72, 0x6f, 0x78, + 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x65, 0x64, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x65, 0x64, 0x12, 0x4f, 0x0a, 0x06, 0x68, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x78, 0x72, 0x61, 0x79, + 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x74, 0x74, 0x70, 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x2e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x1a, 0x39, 0x0a, 0x0b, 0x48, 0x65, + 0x61, 0x64, 0x65, 0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x01, 0x10, 0x02, 0x42, 0x8b, 0x01, 0x0a, 0x27, + 0x63, 0x6f, 0x6d, 0x2e, 0x78, 0x72, 0x61, 0x79, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x74, 0x74, 0x70, + 0x75, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x50, 0x01, 0x5a, 0x38, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x78, 0x74, 0x6c, 0x73, 0x2f, 0x78, 0x72, 0x61, 0x79, 0x2d, + 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x74, 0x74, 0x70, 0x75, 0x70, 0x67, 0x72, + 0x61, 0x64, 0x65, 0xaa, 0x02, 0x23, 0x58, 0x72, 0x61, 0x79, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x48, 0x74, + 0x74, 0x70, 0x55, 0x70, 0x67, 0x72, 0x61, 0x64, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, } var ( @@ -131,16 +148,18 @@ func file_transport_internet_httpupgrade_config_proto_rawDescGZIP() []byte { return file_transport_internet_httpupgrade_config_proto_rawDescData } -var file_transport_internet_httpupgrade_config_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_transport_internet_httpupgrade_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_transport_internet_httpupgrade_config_proto_goTypes = []interface{}{ (*Config)(nil), // 0: xray.transport.internet.httpupgrade.Config + nil, // 1: xray.transport.internet.httpupgrade.Config.HeaderEntry } var file_transport_internet_httpupgrade_config_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name + 1, // 0: xray.transport.internet.httpupgrade.Config.header:type_name -> xray.transport.internet.httpupgrade.Config.HeaderEntry + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name } func init() { file_transport_internet_httpupgrade_config_proto_init() } @@ -168,7 +187,7 @@ func file_transport_internet_httpupgrade_config_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_transport_internet_httpupgrade_config_proto_rawDesc, NumEnums: 0, - NumMessages: 1, + NumMessages: 2, NumExtensions: 0, NumServices: 0, }, diff --git a/xray-core/transport/internet/httpupgrade/config.proto b/xray-core/transport/internet/httpupgrade/config.proto index c1874c9ecf..33d8c05469 100644 --- a/xray-core/transport/internet/httpupgrade/config.proto +++ b/xray-core/transport/internet/httpupgrade/config.proto @@ -15,4 +15,5 @@ message Config { bool accept_proxy_protocol = 4; uint32 ed = 5; + map header = 6; } diff --git a/xray-core/transport/internet/httpupgrade/connection.go b/xray-core/transport/internet/httpupgrade/connection.go new file mode 100644 index 0000000000..c7a33af987 --- /dev/null +++ b/xray-core/transport/internet/httpupgrade/connection.go @@ -0,0 +1,19 @@ +package httpupgrade + +import "net" + +type connnection struct { + net.Conn + remoteAddr net.Addr +} + +func newConnection(conn net.Conn, remoteAddr net.Addr) *connnection { + return &connnection{ + Conn: conn, + remoteAddr: remoteAddr, + } +} + +func (c *connnection) RemoteAddr() net.Addr { + return c.remoteAddr +} diff --git a/xray-core/transport/internet/httpupgrade/dialer.go b/xray-core/transport/internet/httpupgrade/dialer.go index 691f85a8ac..b54af9a6a8 100644 --- a/xray-core/transport/internet/httpupgrade/dialer.go +++ b/xray-core/transport/internet/httpupgrade/dialer.go @@ -73,6 +73,9 @@ func dialhttpUpgrade(ctx context.Context, dest net.Destination, streamSettings * Host: transportConfiguration.Host, Header: make(http.Header), } + for key, value := range transportConfiguration.Header { + req.Header.Add(key, value) + } req.Header.Set("Connection", "upgrade") req.Header.Set("Upgrade", "websocket") diff --git a/xray-core/transport/internet/httpupgrade/hub.go b/xray-core/transport/internet/httpupgrade/hub.go index f87d020f99..f78f844284 100644 --- a/xray-core/transport/internet/httpupgrade/hub.go +++ b/xray-core/transport/internet/httpupgrade/hub.go @@ -9,6 +9,7 @@ import ( "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/net" + http_proto "github.com/xtls/xray-core/common/protocol/http" "github.com/xtls/xray-core/common/session" "github.com/xtls/xray-core/transport/internet" "github.com/xtls/xray-core/transport/internet/stat" @@ -68,6 +69,20 @@ func (s *server) Handle(conn net.Conn) (stat.Connection, error) { _ = conn.Close() return nil, err } + + forwardedAddrs := http_proto.ParseXForwardedFor(req.Header) + remoteAddr := conn.RemoteAddr() + if len(forwardedAddrs) > 0 && forwardedAddrs[0].Family().IsIP() { + remoteAddr = &net.TCPAddr{ + IP: forwardedAddrs[0].IP(), + Port: int(0), + } + } + if remoteAddr == nil { + return nil, newError("remoteAddr is nil") + } + + conn = newConnection(conn, remoteAddr) return stat.Connection(conn), nil } diff --git a/youtube-dl/youtube_dl/extractor/youtube.py b/youtube-dl/youtube_dl/extractor/youtube.py index db840fc455..90c16e172b 100644 --- a/youtube-dl/youtube_dl/extractor/youtube.py +++ b/youtube-dl/youtube_dl/extractor/youtube.py @@ -1647,10 +1647,10 @@ class YoutubeIE(YoutubeBaseInfoExtractor): except JSInterpreter.Exception as e: self.report_warning( '%s (%s %s)' % ( - self.__ie_msg( - 'Unable to decode n-parameter: download likely to be throttled'), + 'Unable to decode n-parameter: download likely to be throttled', error_to_compat_str(e), - traceback.format_exc())) + traceback.format_exc()), + video_id=video_id) return self.write_debug('Decrypted nsig {0} => {1}'.format(n, ret)) diff --git a/yt-dlp/yt_dlp/networking/_websockets.py b/yt-dlp/yt_dlp/networking/_websockets.py index 43bdd7045e..6e235b0c62 100644 --- a/yt-dlp/yt_dlp/networking/_websockets.py +++ b/yt-dlp/yt_dlp/networking/_websockets.py @@ -1,5 +1,6 @@ from __future__ import annotations +import contextlib import io import logging import ssl @@ -38,27 +39,40 @@ if websockets_version < (12, 0): import websockets.sync.client from websockets.uri import parse_uri +# In websockets Connection, recv_exc and recv_events_exc are defined +# after the recv events handler thread is started [1]. +# On our CI using PyPy, in some cases a race condition may occur +# where the recv events handler thread tries to use these attributes before they are defined [2]. +# 1: https://github.com/python-websockets/websockets/blame/de768cf65e7e2b1a3b67854fb9e08816a5ff7050/src/websockets/sync/connection.py#L93 +# 2: "AttributeError: 'ClientConnection' object has no attribute 'recv_events_exc'. Did you mean: 'recv_events'?" +import websockets.sync.connection # isort: split +with contextlib.suppress(Exception): + # > 12.0 + websockets.sync.connection.Connection.recv_exc = None + # 12.0 + websockets.sync.connection.Connection.recv_events_exc = None + class WebsocketsResponseAdapter(WebSocketResponse): - def __init__(self, wsw: websockets.sync.client.ClientConnection, url): + def __init__(self, ws: websockets.sync.client.ClientConnection, url): super().__init__( - fp=io.BytesIO(wsw.response.body or b''), + fp=io.BytesIO(ws.response.body or b''), url=url, - headers=wsw.response.headers, - status=wsw.response.status_code, - reason=wsw.response.reason_phrase, + headers=ws.response.headers, + status=ws.response.status_code, + reason=ws.response.reason_phrase, ) - self.wsw = wsw + self._ws = ws def close(self): - self.wsw.close() + self._ws.close() super().close() def send(self, message): # https://websockets.readthedocs.io/en/stable/reference/sync/client.html#websockets.sync.client.ClientConnection.send try: - return self.wsw.send(message) + return self._ws.send(message) except (websockets.exceptions.WebSocketException, RuntimeError, TimeoutError) as e: raise TransportError(cause=e) from e except SocksProxyError as e: @@ -69,7 +83,7 @@ class WebsocketsResponseAdapter(WebSocketResponse): def recv(self): # https://websockets.readthedocs.io/en/stable/reference/sync/client.html#websockets.sync.client.ClientConnection.recv try: - return self.wsw.recv() + return self._ws.recv() except SocksProxyError as e: raise ProxyError(cause=e) from e except (websockets.exceptions.WebSocketException, RuntimeError, TimeoutError) as e: