Compare commits

..
Author SHA1 Message Date
世界 253b41936e Bump version 2025-01-11 20:58:00 +08:00
世界 ce5b4b06b5 auto-redirect: Fix fetch interfaces 2025-01-07 21:24:52 +08:00
世界 50f5006c43 Fix leak in reality server 2025-01-07 17:27:10 +08:00
世界 e42ff22c2e quic: Fix source not unwrapped 2025-01-07 17:27:10 +08:00
世界 578571b972 Bump version 2025-01-02 15:21:13 +08:00
世界 935beca45d Fix check interface 2025-01-01 12:19:56 +08:00
世界 3e246f1173 Fix vmess mux leak 2025-01-01 12:18:56 +08:00
世界 1bc27a32c2 Fix linter configuration 2025-01-01 12:18:56 +08:00
世界 bc2e3960e4 Enable fix stack for Android 7 and 9 2024-12-28 15:06:57 +08:00
世界 9c4ab0bf33 Bump version 2024-12-21 17:20:56 +08:00
世界 27bdef34c7 release: Fix create app store version 2024-12-21 17:20:56 +08:00
世界 3c00099ed4 Fix process rule check 2024-12-21 17:15:41 +08:00
世界 2babf07f9a Fix wireguard 2024-12-21 16:07:19 +08:00
世界 4795ed712b release: Fix android version 2024-12-21 16:07:19 +08:00
世界 d4cd564dbe release: Fix check tag 2024-12-21 16:07:19 +08:00
世界 1676e13d3e Bump version 2024-12-17 13:43:17 +08:00
世界 50576084c6 release: Add publish testflight 2024-12-17 13:43:17 +08:00
世界 3a94e792a2 documentation: Fix uid range example 2024-12-15 13:56:25 +08:00
世界 9f69f41f68 Update http file server usage 2024-12-15 13:56:25 +08:00
世界 e6847ff50e Add locale support ford deprecated messages 2024-12-15 02:57:08 +08:00
世界 2ac2589d14 release: Fix publish testflight 2024-12-15 02:57:08 +08:00
世界 64a94e8144 release: Fix UpdateBuildForAppStoreVersion 2024-12-14 20:18:36 +08:00
世界 3ed8a5c5d1 wireguard: Fix windows tun read 2024-12-14 20:18:36 +08:00
世界 0a922c6fe3 release: Fix Xcode version 2024-12-14 20:18:36 +08:00
世界 52f3a4226c release: Add app store connect actions 2024-12-14 20:18:36 +08:00
世界 483d9fa503 release: Fix check prerelease 2024-12-14 20:18:36 +08:00
世界 dd9de694f8 release: Update macOS project version atomically 2024-12-14 20:18:36 +08:00
世界 5cdf5c1d9e release: Fix play release 2024-12-14 20:18:36 +08:00
世界 cec7e47086 Add workaround for bulkBarrierPreWrite: unaligned arguments panic 2024-12-14 20:18:36 +08:00
世界 1e6a3f1f0b release: Update debug iOS library build 2024-12-12 14:51:47 +08:00
世界 f0b6818b4c Add workaround for golang/go#68760 2024-12-10 10:30:42 +08:00
世界 3032317918 release: Add workflow build 2024-12-10 09:25:11 +08:00
世界 db22f61846 Update NDK to r28-rc1 2024-12-09 15:11:38 +08:00
世界 8c3a98faa2 wireguard: Fix set reserved 2024-12-05 17:58:09 +08:00
世界 1e787cb607 Fix initial traffic value 2024-12-03 21:43:56 +08:00
世界 558585b01d release: Set upload threads to 5 2024-12-03 17:36:19 +08:00
世界 6e7ecbd4f5 Fix wireguard listen 2024-11-30 12:20:48 +08:00
世界 5a661cde67 clashapi: Remove traffic loop 2024-11-28 12:57:56 +08:00
世界 3cc0e87cfb Bump version 2024-11-27 10:45:24 +08:00
世界 effea5a2b3 Update quic-go to v0.48.2 2024-11-27 10:37:00 +08:00
世界 7f168c5ec6 release: Clean before iOS build 2024-11-27 10:35:20 +08:00
Zephyrusoand世界 0e9129ee3f clashapi: Add mode list 2024-11-27 10:34:47 +08:00
世界 1086d5e665 Fix test tags 2024-11-23 12:20:12 +08:00
世界 d9102ba599 Fix build on bsd systems 2024-11-23 12:16:46 +08:00
世界 17019f1729 Bump version 2024-11-20 12:03:42 +08:00
世界 6be07ed51f Fix start watcher 2024-11-20 11:32:53 +08:00
世界 af58e3bec0 Fix debug listener 2024-11-20 11:32:53 +08:00
世界 e58b549d0f Fix "Fix reloading of tls.certificate_path, tls.key_path and tls.ech.key_path" 2024-11-18 19:03:24 +08:00
zeetexand世界 1d81996ceb Fix reloading of tls.certificate_path, tls.key_path and tls.ech.key_path 2024-11-18 14:09:54 +08:00
世界 97c47e72c4 Update dependencies 2024-11-18 14:07:00 +08:00
世界 122be275b0 release: Notarize macos standalone manually with --no-s3-acceleration 2024-11-18 14:07:00 +08:00
世界 0bb1132034 selector: Fix crash before start 2024-11-18 14:07:00 +08:00
世界 de14337b4b Fix deprecated check 2024-11-18 14:07:00 +08:00
世界 1e07633914 Downgrade NDK to 26.2.11394342 2024-11-18 13:10:06 +08:00
世界 e3e203844e Fix decompile rule-set 2024-11-18 13:10:06 +08:00
世界 84a102a6ef Fix mux stream accept 2024-11-09 12:26:49 +08:00
世界 f1c76c4dde Fix deprecated version check 2024-11-08 20:31:29 +08:00
世界 8df0aa5719 Downgrade NDK to r26d 2024-11-07 19:58:53 +08:00
世界 21faadb992 Uniq deprecated notes 2024-11-07 19:58:53 +08:00
世界 88099a304a platform: Add SendNotification 2024-11-06 12:53:32 +08:00
世界 f504fb0d46 Revert "platform: Add openURL event"
This reverts commit 718cffea9a.
2024-11-05 20:03:39 +08:00
世界 1d517b6ca5 platform: Add link flags 2024-11-05 18:28:13 +08:00
世界 b702d0b67a Update dependencies 2024-11-05 18:28:03 +08:00
世界 a001e30d8b platform: Remove SetTraceback("all") 2024-11-05 18:28:02 +08:00
世界 cdb93f0bb2 Fix "Fix metadata context" 2024-11-05 18:27:51 +08:00
世界 718cffea9a platform: Add openURL event 2024-11-05 18:27:51 +08:00
世界 9585c53e9f release: Add upload dSYMs 2024-10-30 15:35:20 +08:00
世界 d66d5cd457 Add deprecated warnings 2024-10-30 14:01:28 +08:00
世界 8c143feec8 Increase timeouts 2024-10-30 14:01:28 +08:00
世界 419058f466 Update NDK version 2024-10-30 14:01:13 +08:00
世界 1a6047a61b Fix metadata context 2024-10-30 14:01:13 +08:00
世界 327bb35ddd Rename HTTP start context 2024-10-30 14:01:13 +08:00
世界 6ed9a06394 Fix rule-set format 2024-10-25 22:12:47 +08:00
世界 b80ec55ba0 Bump version 2024-10-16 21:11:31 +08:00
世界 08718112ae Retry system forwarder listen 2024-10-16 20:47:26 +08:00
956ee361df Fix corrected improper use of reader and bReader
Co-authored-by: x_123 <x@a>
2024-10-16 20:45:18 +08:00
世界 e93d0408be documentation: Fix release notes 2024-10-16 20:45:13 +08:00
世界 137832ff3e Bump version 2024-10-13 21:17:59 +08:00
世界 3ede29fb6d documentation: Improve theme 2024-10-13 13:07:18 +08:00
世界 82ab68b542 build: Fix find NDK 2024-10-13 13:07:18 +08:00
renovate[bot]and世界 e55723d84d [dependencies] Update actions/checkout digest to eef6144 2024-10-13 13:07:18 +08:00
世界 2f4d2d97f9 auto-redirect: Let fw4 take precedence over prerouting 2024-10-13 13:07:18 +08:00
世界 926d6f769e Update utls to v1.6.7 2024-10-13 13:07:02 +08:00
srk24and世界 846777cd0c Add process_path_regex rule type 2024-10-13 13:07:02 +08:00
世界 06533b7a3b clash-api: Add PNA support 2024-10-13 13:07:02 +08:00
世界 4a95558c53 Add RDP sniffer 2024-10-13 13:07:02 +08:00
世界 e39a28ed5a Add SSH sniffer 2024-10-13 13:07:02 +08:00
世界 b2c708a3e6 Write close error to log 2024-10-13 13:07:02 +08:00
世界 a9209bb3e5 Add AdGuard DNS filter support 2024-10-13 13:07:02 +08:00
世界 9dc3bb975a Improve QUIC sniffer 2024-10-13 13:07:02 +08:00
世界 3a7acaa92a Add inline rule-set & Add reload for local rule-set 2024-10-13 13:07:02 +08:00
世界 6bebe2483b Unique rule-set names 2024-10-13 13:07:02 +08:00
世界 93cf134995 Add accept empty DNS rule option 2024-10-13 13:07:02 +08:00
世界 ff7d8c9ba8 Add custom options for TUN auto-route and auto-redirect 2024-10-13 13:07:02 +08:00
世界 50f07b42f6 Improve base DNS transports & Minor fixes 2024-10-13 13:07:02 +08:00
世界 db3a0c636d Add auto-redirect & Improve auto-route 2024-10-13 13:07:02 +08:00
世界 fec38f85cd Add rule-set decompile command 2024-10-13 13:07:02 +08:00
世界 dcb0141646 Add IP address support for rule-set match match 2024-10-13 13:07:02 +08:00
世界 f4f5a3c925 Improve usages of json.Unmarshal 2024-10-13 13:07:02 +08:00
世界 9b8d6c1b73 Bump rule-set version 2024-10-13 13:07:02 +08:00
世界 2f776168de Implement read deadline for QUIC based UDP inbounds 2024-10-13 13:07:02 +08:00
世界 923d3222b0 WTF is this 2024-10-13 13:07:01 +08:00
世界 bda93d516b platform: Fix clash server reload on android 2024-10-13 13:06:57 +08:00
世界 7eec3fb57a platform: Add log update interval 2024-10-13 13:06:57 +08:00
世界 b1d75812c5 platform: Prepare connections list 2024-10-13 13:06:55 +08:00
世界 d44e7d9834 Drop support for go1.18 and go1.19 2024-10-07 04:58:48 +08:00
世界 369bc7cea3 Add DTLS sniffer 2024-10-07 04:58:48 +08:00
iosmanthusand世界 4b7a83da16 Introduce bittorrent related protocol sniffers
* Introduce bittorrent related protocol sniffers

including, sniffers of
1. BitTorrent Protocol (TCP)
2. uTorrent Transport Protocol (UDP)

Signed-off-by: iosmanthus <myosmanthustree@gmail.com>
Co-authored-by: 世界 <i@sekai.icu>
2024-10-07 04:58:48 +08:00
世界 0f7154afbd Update workflow to go1.23 2024-10-07 04:58:47 +08:00
世界 a06d10c3bc Bump version 2024-10-07 04:34:48 +08:00
世界 63cc6cc76c Fix Makefile 2024-10-07 04:34:48 +08:00
世界 d55c5b5cab documentation: Update package status 2024-10-07 04:34:48 +08:00
世界 b624c2dcc7 Fix context used by DNS outbounds 2024-10-07 04:34:48 +08:00
世界 9415444ebd Fix base path not applied to local rule-sets 2024-10-07 04:34:48 +08:00
世界 95606191d8 Add completions for linux packages 2024-10-07 04:34:48 +08:00
世界 e586d9e9bc Bump version 2024-09-20 23:37:06 +08:00
世界 8c7eaa4477 Fix docker build 2024-09-20 23:37:06 +08:00
世界 8464c8cb7c Fix version script 2024-09-20 21:10:15 +08:00
世界 39d7127651 Revert "Fix stream sniffer" 2024-09-20 20:40:02 +08:00
世界 e2077009c4 documentation: Update client status 2024-09-20 20:13:55 +08:00
世界 700a8eb425 Minor fixes 2024-09-20 20:13:14 +08:00
世界 3b0cba0852 Fix wireguard start 2024-09-20 20:12:52 +08:00
世界 f5554dd8b8 Bump version 2024-09-18 07:04:29 +08:00
世界 4d0362d530 Update macOS build workflow 2024-09-17 22:01:05 +08:00
世界 97ccd2ca04 documentation: Add sponsors page 2024-09-17 18:47:33 +08:00
世界 1ed6654ad4 Add mips64 build 2024-09-15 12:12:25 +08:00
世界 5385f75f53 documentation: Update build requirements 2024-09-15 12:10:00 +08:00
世界 ad97d4e11f Fix disconnected interface selected as default in windows 2024-09-15 11:59:32 +08:00
世界 09d4e91b77 Fix cached conn eats up read deadlines 2024-09-15 11:56:04 +08:00
Monicaand世界 3dbdda9555 documentation: Fix dial.zh.md
The Chinese documentation incorrectly stated that the default value for the domain_strategy field in the direct outbound module is dns.strategy. The correct value should be inbound.domain_strategy, as specified in the English documentation. This commit corrects the Chinese documentation to align with the accurate behavior described in the English version.

Signed-off-by: Monica <1379531829@qq.com>
2024-09-15 11:53:03 +08:00
世界 1f4ed6ff8f documentation: Update client status 2024-09-13 10:09:08 +08:00
世界 6ddbe19bc0 platform: Update bundle id 2024-09-12 17:55:53 +08:00
世界 d7205ecc60 Fix Makefile 2024-09-12 17:55:53 +08:00
世界 9e243e0ff9 gomobile: Fix go mod version 2024-09-10 23:05:13 +08:00
世界 02bc3e0a0a Update quic-go to v0.47.0 2024-09-09 14:45:46 +08:00
世界 87be6dc235 Update README 2024-09-09 08:48:35 +08:00
世界 c1c30976dc Improve docker workflow 2024-09-08 11:11:47 +08:00
世界 9bac18bcd1 wireguard: Fix events chan leak 2024-09-08 10:07:12 +08:00
世界 ceda5cc95d clash-api: Fix bad redirect 2024-09-08 10:07:07 +08:00
世界 27d6b63e71 Fix stream sniffer 2024-09-08 10:07:07 +08:00
世界 b57abcc73c tfo: Fix build with go1.23 2024-08-27 11:24:51 +08:00
世界 f1147965dd documentation: Fix missing zh headline 2024-08-21 18:52:38 +08:00
世界 45f3234c73 documentation: Update package status 2024-08-21 11:39:07 +08:00
Mingye Wangand世界 aae3fded32 documentation: Two updates
* Copyedit documentation

Close #1378

* remove yum, go full on dnf

fixes #2049
2024-08-21 11:32:43 +08:00
世界 090494faf5 Do not close bug and enhancement issues 2024-08-21 08:09:15 +08:00
世界 db5719e22f Fix no error return when empty DNS cache retrieved 2024-08-20 23:23:48 +08:00
世界 064fb9b873 Fix direct dialer not resolving domain 2024-08-20 21:02:52 +08:00
世界 f6a1e123fc Make linter happy 2024-08-19 18:42:02 +08:00
世界 3066dfe3b3 Bump version 2024-08-19 10:43:09 +08:00
Liu Bingyanand世界 1128fdd8c7 documentation: Update injectable description 2024-08-19 07:40:31 +08:00
世界 cfd9879b17 documentation: Remove unused 2024-08-19 06:39:33 +08:00
世界 9ceb660c57 documentation: Announce that our apps on Apple platforms are no longer available 2024-08-19 06:39:33 +08:00
世界 7d00d7df28 Update quic-go to v0.46.0 2024-08-19 06:25:15 +08:00
世界 21b1ac26b9 Fix UDP conn stuck on sniff
This change only avoids permanent hangs. We need to implement read deadlines for UDP conns in 1.10 for server inbounds.
2024-08-18 11:27:12 +08:00
世界 7fec8d842e Update golangci-lint configuration 2024-08-18 11:17:01 +08:00
世界 07c678fb85 Fix crash on Android when using process rules 2024-08-18 10:23:28 +08:00
世界 baecfc7778 Update quic-go to v0.45.2 2024-08-18 10:23:17 +08:00
世界 07de36ecdb Fix tests 2024-08-03 12:46:38 +08:00
世界 2c8a8303cd dns: Minor fixes 2024-07-27 11:04:57 +08:00
ruokeqxand世界 e5991cae0b Use unix.SysctlRaw for macOS 2024-07-22 12:42:22 +08:00
世界 1349acfd5a Fix panic caused by possible generation of duplicate keys for domain_suffix 2024-07-17 16:02:17 +08:00
世界 98ff897f35 Fix reset outbounds 2024-07-13 17:46:22 +08:00
ayoohandGitHub 6144c8e340 Fix default end value of the rangeItem 2024-07-13 17:45:32 +08:00
HystericalDragonandGitHub c8caac9f67 Fix v2rayquic default NextProtos (#1934) 2024-07-11 23:34:09 +08:00
printferand世界 81e9eda357 documentation: Fix typo 2024-07-07 16:09:41 +08:00
世界 7cba3da108 shadowsocks: Fix packet process for AEAD multi-user server 2024-07-05 17:09:09 +08:00
世界 82d06b43e7 vless: Fix missing deadline interfaces 2024-07-05 17:08:10 +08:00
世界 a7ac91f573 Move legacy vless implemetation to library 2024-07-03 20:17:32 +08:00
世界 0540a95a43 Fix v2ray-plugin 2024-07-02 14:08:17 +08:00
世界 94707dfcdd Add name to errors from v2ray HTTP transports 2024-07-02 14:08:17 +08:00
世界 8a17043502 Fix command output for rule-set match 2024-06-26 12:26:35 +08:00
世界 b0aaa86806 Minor fixes 2024-06-25 13:14:45 +08:00
世界 8a2d3fbb28 Update quic-go to v0.45.1 & Filter HTTPS ipv4/6hint 2024-06-24 11:07:32 +08:00
renovate[bot]and世界 4652019608 [dependencies] Update docker/build-push-action action to v6 2024-06-24 10:24:13 +08:00
世界 06fa5abf63 Fix non-IP queries accepted by address filter rules 2024-06-24 10:13:16 +08:00
世界 996fbbf0c3 docs: Switch to venv 2024-06-24 10:10:49 +08:00
renovate[bot]and世界 142ff1b455 [dependencies] Update actions/checkout digest to 692973e 2024-06-17 13:05:54 +08:00
世界 74d662f7a3 Fix always create package manager 2024-06-11 21:16:57 +08:00
世界 085f603377 Bump version 2024-06-09 13:20:56 +08:00
世界 460fae83dc Fix quic-go is caching dialErr since v0.43.0 2024-06-09 13:15:40 +08:00
世界 bb9bd9bff6 Fix package manager start order 2024-06-09 07:21:50 +08:00
世界 c2354ebf25 Bump version 2024-06-08 22:00:46 +08:00
世界 c1f4755c4e Fix parse UDP DNS server with addr:port address 2024-06-08 22:00:46 +08:00
世界 0ca5909b06 Stop passing device sleep events on Android and Apple platforms 2024-06-08 22:00:46 +08:00
世界 e77a8114c5 Fix rule-set start order 2024-06-08 22:00:46 +08:00
renovate[bot]and世界 f1393235ff [dependencies] Update actions/checkout digest to a5ac7e5 2024-06-08 22:00:46 +08:00
renovate[bot]and世界 bdba2365de [dependencies] Update goreleaser/goreleaser-action action to v6 2024-06-08 18:58:22 +08:00
世界 ce0da5b557 Fix typo 2024-06-08 18:58:14 +08:00
世界 3853201412 Bump version 2024-06-07 19:07:46 +08:00
世界 7003ef40a3 Fix wireguard start 2024-06-07 19:07:46 +08:00
世界 59ec92228c Fix repeatedly no route logs 2024-06-07 15:03:48 +08:00
世界 0eeb2da323 Fix reset HTTP3 DNS transport 2024-06-06 22:28:43 +08:00
世界 977b0fac02 Fix get source address from X-Forwarded-For 2024-06-06 22:21:37 +08:00
世界 51964801ff Fix enforced power listener on windows 2024-06-06 22:20:23 +08:00
世界 e08c052fc9 Fix wireguard client bind 2024-06-06 22:20:21 +08:00
世界 53927d8bbd Remove logs in router initialize 2024-06-06 22:20:19 +08:00
世界 968b9bc217 Fix crash on *bsd 2024-06-06 22:20:17 +08:00
lgjintand世界 69dc87aa6d Fix set KDE6 system proxy 2024-06-06 22:20:14 +08:00
Fei1Yangand世界 4193df375f build: Remove vendor in RPM packages 2024-05-27 19:28:15 +08:00
世界 5ff7006326 Bump version 2024-05-25 11:30:43 +08:00
世界 a89107ea9d documentation: Bump version 2024-05-23 14:57:45 +08:00
世界 9ffdbba2ed documentation: Add manuel for mitigating tunnelvision attacks 2024-05-23 14:57:27 +08:00
世界 65c71049ea documentation: Update DNS manual 2024-05-23 14:57:26 +08:00
世界 7d4e6a7f4e dialer: Allow nil router 2024-05-23 14:57:26 +08:00
世界 d612620c5d Add rule-set match command 2024-05-23 14:57:26 +08:00
世界 8a9a77a438 Add bypass_domain and search_domain platform HTTP proxy options 2024-05-23 14:57:26 +08:00
世界 a2098c18e1 Handle includeAllNetworks 2024-05-23 14:57:26 +08:00
世界 cf2181dd3a Update gVisor to 20240422.0 2024-05-23 14:57:15 +08:00
世界 5899e95ff1 Update quic-go to v0.43.1 2024-05-21 15:12:05 +08:00
世界 d7160c19cf Fixed order for Clash modes 2024-05-21 15:12:05 +08:00
世界 da9e22b4e6 Add custom prefix support in EDNS0 client subnet options 2024-05-21 15:12:05 +08:00
气息and世界 0e120f8a44 Fix DNS exchange index
Signed-off-by: 气息 <qdshizh@gmail.com>
2024-05-21 15:12:05 +08:00
dyhkwongand世界 d918863ac5 Always disable cache for fake-ip servers 2024-05-21 15:12:04 +08:00
PuerNyaand世界 2ae192305c Always disable cache for fake-ip DNS transport if independent_cache disabled 2024-05-21 15:12:03 +08:00
世界 71d1879bd6 Fix missing rule_set_ipcidr_match_source item in DNS rules 2024-05-21 15:12:03 +08:00
世界 917514e09f Improve DNS truncate behavior 2024-05-21 15:12:03 +08:00
世界 5327aeaea4 Fix DNS fallthrough incorrectly 2024-05-21 15:12:03 +08:00
世界 93ae3f7a1e Add rejected DNS response cache support 2024-05-21 15:12:03 +08:00
世界 f24a2aed7d Add support for client-subnet DNS options 2024-05-21 15:12:03 +08:00
世界 0517ceef76 Add address filter support for DNS rules 2024-05-21 15:12:02 +08:00
世界 830ea46932 Fix timezone for Android and iOS 2024-05-21 15:11:52 +08:00
世界 cd0fcd5ddc Improve loopback detector 2024-05-21 15:11:52 +08:00
世界 003176f069 Remove unused fakeip packet conn 2024-05-21 15:11:52 +08:00
世界 71d92518c1 Set the default TCP keep alive period 2024-05-21 15:11:52 +08:00
世界 b5dcd6bf59 Migrate ntp service to library 2024-05-21 15:11:52 +08:00
世界 11c7b4a866 Handle Windows power events 2024-05-21 15:11:52 +08:00
世界 ee14135298 Improve domain suffix match behavior
For historical reasons, sing-box's `domain_suffix` rule matches literal prefixes instead of the same as other projects.

This change modifies the behavior of `domain_suffix`: If the rule value is prefixed with `.`,
the behavior is unchanged, otherwise it matches `(domain|.+\.domain)` instead.
2024-05-21 15:11:41 +08:00
世界 cbcf005f37 Remove PROCESS_NAME_NATIVE dwFlag in process query output
The `process_path` rule of sing-box is inherited from Clash,
the original code uses the local system's path format (e.g. `\Device\HarddiskVolume1\folder\program.exe`),
but when the device has multiple disks, the HarddiskVolume serial number is not stable.

This change make QueryFullProcessImageNameW output a Win32 path (such as `C:\folder\program.exe`),
which will disrupt the existing `process_path` use cases in Windows.
2024-05-18 17:22:14 +08:00
世界 daee0b154e badtls: Support uTLS and TLS ECH for read waiter 2024-05-18 17:22:14 +08:00
世界 d530c724c0 Bump version 2024-05-18 16:53:05 +08:00
世界 7f698c1104 Fix hysteria2 panic 2024-05-18 16:20:32 +08:00
renovate[bot]and世界 7a4a44c6d2 [dependencies] Update golangci/golangci-lint-action action to v6 2024-05-10 19:49:20 +08:00
世界 44277e5dd2 Fix urltest logic 2024-05-10 17:41:20 +08:00
世界 1f470c69c4 Update docker workflow 2024-05-03 19:33:20 +08:00
世界 742adacce7 Bump version 2024-05-03 17:38:26 +08:00
世界 32e1d5a5e2 documentation: Update package status 2024-05-03 17:38:26 +08:00
世界 cb9f4ce597 Minor fixes 2024-05-03 15:34:47 +08:00
世界 4b1a6185ba Fix DNF repo 2024-04-29 23:13:04 +08:00
世界 8d85c92356 Fix multiplex client dialer context 2024-04-29 11:58:20 +08:00
世界 c6164c9eca Fix usage of github actions 2024-04-29 11:58:20 +08:00
dyhkwongand世界 3c85b8bc48 Fix fake-ip mapping 2024-04-29 11:58:20 +08:00
HystericalDragonand世界 8b8fb4344c Remove unused encoder 2024-04-29 11:58:20 +08:00
renovate[bot]and世界 e85a38e059 [dependencies] Update golangci/golangci-lint-action action to v5 2024-04-29 11:58:20 +08:00
renovate[bot]and世界 f3ac91673a [dependencies] Update actions/checkout digest to 0ad4b8f 2024-04-29 11:58:20 +08:00
世界 0f1e58b917 documentation: Update TestFlight 2024-04-29 11:58:20 +08:00
世界 c4cfe24aef documentation: Fix strict_route description 2024-04-29 11:58:20 +08:00
世界 3d73b159ba Fix linux workflow 2024-04-29 11:58:20 +08:00
世界 0ae1afef44 Bump version 2024-04-23 14:14:40 +08:00
世界 a5e2a4073b Update dependencies 2024-04-23 14:03:55 +08:00
世界 b6cb3948a3 Fix initial packet MTU for QUIC protocols 2024-04-23 11:12:31 +08:00
世界 7b0f5061dc Fix loopback detector 2024-04-17 21:45:54 +08:00
世界 76f20482f7 Fix linux repo 2024-04-12 22:52:37 +08:00
世界 e735a5bdc8 Update dependencies 2024-04-12 22:52:37 +08:00
世界 70381e93c8 Bump version 2024-04-08 11:55:41 +08:00
世界 07a40716e8 Update dependencies 2024-04-08 11:45:00 +08:00
世界 5fea5956db Fix linux network monitor 2024-04-08 11:45:00 +08:00
世界 d20a389043 Fix timer usage 2024-04-08 11:45:00 +08:00
世界 4a4180bde5 Fixes for QUIC protocols 2024-04-08 11:44:55 +08:00
世界 7ecb6daabb Update dependencies 2024-03-29 04:52:06 +00:00
世界 712bdd9ae5 Fix fury release 2024-03-25 10:44:57 +08:00
世界 a3b74591a7 Fix syscall packet read waiter 2024-03-25 01:49:59 +08:00
世界 2f4abc6523 Fix canceler 2024-03-24 19:12:07 +08:00
dyhkwongandGitHub 965ab075d9 Fix source_ip_is_private matching 2024-03-24 19:06:02 +08:00
世界 ed2f8b9637 Bump version 2024-03-23 20:50:45 +08:00
世界 0f71ce5120 tun: Fix GSO batch size 2024-03-22 14:54:57 +08:00
世界 f8085ab111 Fix Makefile 2024-03-21 23:32:02 +08:00
世界 f61b272cbf Fix WireGuard client bind 2024-03-20 10:52:24 +08:00
世界 59d437b9d2 Use local legacy compiler 2024-03-19 13:53:34 +08:00
世界 a7338fdc2b Fix DNS panic 2024-03-19 12:17:32 +08:00
Puqns67and世界 d88860928e Fix the installation location of service files in prebuilded package 2024-03-19 12:13:59 +08:00
世界 20a2e38f47 Fix build for F-Droid 2024-03-17 21:43:22 +08:00
世界 acd438be23 Fix fury workflow 2024-03-17 21:43:22 +08:00
世界 e27fb51b54 Bump version 2024-03-16 12:05:58 +08:00
世界 adc38b26eb Fix Makefile 2024-03-15 18:06:37 +08:00
世界 7e943e743a Fix darwin interface monitor 2024-03-15 18:06:37 +08:00
世界 ceffcc0ad2 platform: Improve stop on apple platforms 2024-03-15 18:06:37 +08:00
世界 fdc451f7c6 platform: Fix missing log on apple platforms 2024-03-15 18:06:37 +08:00
世界 b48c471e6a Add repo release 2024-03-15 18:06:37 +08:00
世界 4b1fabd007 Fix lint workflow 2024-03-13 19:39:59 +08:00
世界 2b5eb1c59e Add sponsor link to issue template 2024-03-13 19:39:59 +08:00
世界 e2d3862e64 platform: reset network on invalid power events 2024-03-13 19:39:59 +08:00
世界 4f5e7b974d Fix crash in HTTP proxy server again 2024-03-10 16:53:58 +08:00
世界 21dedddd93 Update dependencies 2024-03-08 23:36:33 +08:00
世界 e02502bec0 Update go 1.20 2024-03-08 23:31:42 +08:00
世界 ba67633ee8 Fix missing source address in inbound logs in QUIC inbounds 2024-03-07 10:47:16 +08:00
世界 7fd9abe802 Bump version 2024-03-05 13:14:38 +08:00
世界 78a5f59202 documentation: Add link to F-Droid 2024-03-05 13:13:31 +08:00
世界 8d0da685d2 Update dependencies 2024-03-02 14:29:28 +08:00
世界 e6644f784e Fix crash in HTTP proxy server 2024-03-02 14:28:47 +08:00
世界 2b93b74d38 Fix SO_BINDTOIFINDEX usage 2024-02-29 13:03:05 +08:00
世界 dd52c26ae1 Don't return error in WireGurad client bind 2024-02-28 15:28:38 +08:00
世界 f288e3898b Bump version 2024-02-28 15:10:28 +08:00
世界 1bc893a73a documentation: Update privacy policy to make Play Store happy 2024-02-28 15:10:28 +08:00
世界 7359fdf195 platform: Upgrade NDK to the latest LTS version 2024-02-28 15:10:28 +08:00
世界 02b7041de6 Update dependencies 2024-02-26 22:53:31 +08:00
世界 96ac931b11 Fix network/interface monitor 2024-02-26 22:53:31 +08:00
世界 3077a82650 Fix reproducible builds 2024-02-24 23:19:31 +08:00
世界 de998c5119 Fix docker workflow 2024-02-24 22:49:07 +08:00
世界 d32c30c4b7 documentation: Bump version 2024-02-24 13:20:43 +08:00
世界 4823023806 Remove invalid archlinux packages from release 2024-02-24 13:20:43 +08:00
Aleksandr Razumovand世界 bb355d17b2 Add riscv64 to platform list in release 2024-02-24 13:20:43 +08:00
hiddifyand世界 aaf30bf92b platform: Fix group update interval not taking effect 2024-02-24 13:20:43 +08:00
hiddifyand世界 f8c400cffc platform: Remove duplicated close 2024-02-24 13:20:43 +08:00
hatune-mikuand世界 3c24411e14 documentation: Fix navigation menu 2024-02-24 13:20:42 +08:00
世界 4a44aa3c21 Fix HTTP inbound 2024-02-24 13:20:42 +08:00
世界 8db2ae0c83 Fix documentation 2024-02-24 13:20:42 +08:00
世界 80d1aebcb7 platform: Unify client versions 2024-02-24 13:20:27 +08:00
世界 5583e01c99 platform: Export NeedWIFIState for Android 2024-02-18 14:24:21 +08:00
世界 bca0b86549 Copy DNS message struct instead of deep copy 2024-02-10 23:49:09 +08:00
世界 8332878cdc Fix destination IP CIDR match in DNS 2024-02-10 22:37:42 +08:00
世界 d0ba69ad22 Fix TUN unaligned panic on windows 2024-02-10 21:22:02 +08:00
世界 31b8834427 documentation: Fix description for with_ech 2024-02-10 12:01:09 +08:00
renovate[bot]and世界 d0f7a59e9b [dependencies] Update golang Docker tag to v1.22 2024-02-10 11:54:40 +08:00
renovate[bot]and世界 71e7d517a8 [dependencies] Update github-actions 2024-02-10 11:54:31 +08:00
世界 e6885e9967 platform: Ignore momentary pause on iOS 2024-02-09 13:57:47 +08:00
世界 e2090923db Bump Go version 2024-02-08 20:31:40 +08:00
世界 46be319976 Fix external controller crash before started 2024-02-08 20:31:40 +08:00
renovate[bot]and世界 b27bc45cf2 [dependencies] Update actions/cache action to v4 2024-02-03 15:08:41 +08:00
世界 3d735281f4 documentation: Bump version 2024-02-02 17:51:40 +08:00
世界 8760a0d94d Fix android interface monitor 2024-02-02 17:51:40 +08:00
世界 2239b59933 Remove duplicated rules 2024-02-02 14:30:27 +08:00
世界 425a63f59d Fix rawConn not closed for hy/hy2 2024-02-02 14:30:27 +08:00
世界 b85725c009 urltest: Remember the last choice when there is no valid result 2024-02-02 11:27:36 +08:00
世界 17aebc56c1 Fix UDP DNS response not truncated 2024-02-01 14:43:59 +08:00
Devmanand世界 f76b21b02c Fix mobile build on windows
gobind executable name is not exactly `gobind` on windows it's `gobind.exe`

Signed-off-by: Devman <85770917+amir-devman@users.noreply.github.com>
2024-02-01 12:07:39 +08:00
kkocdkoandGitHub 704545a2ec Fix rule description header of domain_suffix
I read other rule_item_xxx.go files, they are all snake case. This description is showed on dashboard like yacd.

Signed-off-by: kkocdko <31189892+kkocdko@users.noreply.github.com>
2024-02-01 10:42:12 +08:00
dyhkwongandGitHub dc7b7afc06 Fix loop back detector 2024-02-01 10:41:38 +08:00
世界 e478d3c2dc Update workflow 2024-01-24 12:21:18 +08:00
世界 c8318058bb documentation: Bump version 2024-01-23 11:57:28 +08:00
世界 abca2118e7 documentation: Update geosite usage 2024-01-23 11:57:28 +08:00
世界 a8ee41715a platform: Add service error wrapper for macOS system extension 2024-01-22 19:00:09 +08:00
世界 94f76d6671 Update dependencies 2024-01-22 14:37:21 +08:00
世界 bf6cc8903c Fix missing write result in TFO open 2024-01-19 11:22:13 +08:00
世界 1b15e1692a Add sponsor button 2024-01-19 11:22:13 +08:00
世界 017372db25 Fix missing loopback detect 2024-01-19 11:22:12 +08:00
世界 216a0380fe documentation: Bump version 2024-01-16 05:50:07 +08:00
Noob Zhangand世界 71b9e4ff17 Add network-online.target in .service files
This helps the daemon work better on IoT devices
like RaspberryPi.
According to systemd's documentation,
`network.target` means there has already been
a network manager started, but the network may
not be "up". On most PCs this does not matter
because the network will turn to "up" almost
immidiately. The IoT devices' network interface
may not be set up quickly enough, so they may
meet that the sing-box daemon is started before
network is ready, which results that sing-box
cannot find a working route. The workaround
of this is restarting sing-box daemon but it
absolutely is not the perfect solution.
As `network-online.target` must be triggered by
network manager after you configured it, I keep
`network.target` so there will be no change to
those who do not enabled proper trigger service
like `NetworkManager-wait-online.service`.

See also: https://systemd.io/NETWORK_ONLINE/
2024-01-16 05:50:07 +08:00
printferand世界 9b7deb5246 Enhanced light/dark mode support in mkdocs configuration 2024-01-16 05:50:07 +08:00
世界 a850a73e1a Fix missing upstream func for read wait conn 2024-01-16 05:50:07 +08:00
世界 c4d9be9e0d Fix rule match 2024-01-14 13:01:57 +08:00
世界 f31c604b3d documentation: Bump version 2024-01-09 12:22:22 +08:00
世界 4c8a50a52b Fix TLS conn cast for vision 2024-01-09 12:22:22 +08:00
世界 b326e60998 Update dependencies 2024-01-09 12:22:22 +08:00
世界 11bec79a06 documentation: Bump version 2024-01-05 11:17:49 +08:00
世界 16eff06c37 documentation: remove usages of category-companies@cn since merged into cn 2024-01-03 12:21:53 +08:00
世界 2911eba236 documentation: Update package managers 2024-01-03 12:21:48 +08:00
世界 2e607118c3 Remove unnecessary context wrappers 2024-01-03 12:21:48 +08:00
世界 89c723e3e4 Improve read wait interface &
Refactor Authenticator interface to struct &
Update smux &
Update gVisor to 20231204.0 &
Update quic-go to v0.40.1 &
Update wireguard-go &
Add GSO support for TUN/WireGuard &
Fix router pre-start &
Fix bind forwarder to interface for systems stack
2024-01-03 12:21:47 +08:00
世界 35fd9de3ff Make generated files have SUDO_USER's permissions if possible. 2024-01-03 12:21:47 +08:00
世界 6ddcd3954d Refactor inbound/outbound options struct 2024-01-03 12:21:47 +08:00
世界 36b0f2e91a Improve configuration merge 2024-01-03 12:21:47 +08:00
世界 fe053e26b5 Update uTLS to 1.5.4 2024-01-03 12:21:47 +08:00
世界 269434cfe6 Update tfo-go 2024-01-03 12:21:47 +08:00
世界 88495a24dc Update gomobile and add tag 2024-01-03 12:21:46 +08:00
世界 d131a7c10a Update cloudflare-tls to go1.21.5 2024-01-03 12:21:46 +08:00
世界 744a5d703b Make type check strict 2024-01-03 12:21:46 +08:00
世界 09421b6378 Remove comparable limit for Listable 2024-01-03 12:21:46 +08:00
世界 21283b554a Avoid opening log output before start &
Replace tracing logs with task monitor
2024-01-03 12:21:46 +08:00
世界 25810b50c1 Update documentation 2024-01-03 12:21:37 +08:00
世界 f1e3a59db3 Add idle_timeout for URLTest outbound 2024-01-03 12:21:37 +08:00
世界 a99deb2cb5 Skip internal fake-ip queries 2024-01-03 12:21:37 +08:00
世界 38d28e0763 Migrate contentjson and badjson to library &
Add omitempty in format
2024-01-03 12:21:37 +08:00
世界 e09a94bb9e Update documentation 2024-01-03 12:21:36 +08:00
世界 a21c5324fd Independent source_ip_is_private and ip_is_private rules 2024-01-03 12:21:36 +08:00
世界 4b43acfec0 Add rule-set 2024-01-03 12:21:36 +08:00
世界 7df151e820 Update buffer usage 2024-01-03 12:21:36 +08:00
世界 5948ffb965 Allow nested logical rules 2024-01-03 12:21:36 +08:00
世界 bf4e556f67 Migrate to independent cache file 2024-01-03 12:21:36 +08:00
世界 e3f8567690 documentation: Bump version 2024-01-02 14:31:53 +08:00
世界 40c7f3e170 Fix geoip close 2024-01-02 14:31:23 +08:00
世界 c506255e0f Fix grpc lite transport encoding 2024-01-01 16:16:58 +08:00
世界 87c6fd4c0f Fix h2mux request context 2024-01-01 16:15:49 +08:00
世界 19c445d28e documentation: Bump version 2023-12-29 18:00:40 +08:00
世界 9119a5209b dcoumentation: Fix description of cipher_suites 2023-12-29 18:00:40 +08:00
世界 46c8d6e61f Fix pprof URL path 2023-12-29 18:00:40 +08:00
世界 ea17c2786d Update dependencies 2023-12-27 10:37:18 +08:00
世界 12ababd911 Fix mux test 2023-12-27 10:30:19 +08:00
世界 0523845833 Update issue reporting templates
Enhanced the issue reporting templates for both English and Chinese versions by adding more structured and comprehensive guideline checkboxes. This aims to ensure contributors provide sufficient and beneficial information for reproducing and resolving issues, thereby improving the quality of reports and making issue tracking more efficient.
2023-12-26 19:05:19 +08:00
renovate[bot]and世界 57794919fa [dependencies] Update actions/upload-artifact action to v4 2023-12-26 19:04:51 +08:00
世界 f5bb5cf343 Fix missing marshal for udp_timeout 2023-12-26 10:52:46 +08:00
世界 3eed614dea Fix ACME ALPN conflict 2023-12-26 09:02:58 +08:00
世界 76a295a660 Fix missing nil check for URLTest 2023-12-26 09:02:58 +08:00
世界 082e3fb8df Fix V2Ray transport path validation behavior 2023-12-26 09:02:58 +08:00
世界 a0cab4f563 Fix websocket client initialize 2023-12-22 20:38:06 +08:00
世界 aeb7308e81 documentation: Bump version 2023-12-21 15:25:19 +08:00
世界 bb1ebfda83 documentation: Fix link format 2023-12-21 15:24:05 +08:00
世界 c05c798221 Fix missing UDP timeout for QUIC protocols 2023-12-21 15:16:36 +08:00
世界 55b1bcc6a5 Migrate udp_timeout from seconds to duration format 2023-12-21 14:50:33 +08:00
世界 d6eddce420 Fix missing handshake timeout for multiplex 2023-12-21 14:21:59 +08:00
世界 4bf057139b Fix DNS dial context 2023-12-21 14:19:27 +08:00
世界 a1b28b8282 Try to fix HTTP server leak again 2023-12-21 14:16:16 +08:00
世界 d0aaf71770 Fix direct UDP override 2023-12-18 21:48:59 +08:00
世界 2f31202c6b documentation: Update shadowsocks example
Remove the information on password generation for `2022-blake3-aes-128-gcm` cipher from the Server Example section in the shadowsocks.md file as it is no longer needed.
2023-12-14 21:05:41 +08:00
renovate[bot]and世界 e4cc510712 [dependencies] Update github-actions 2023-12-14 15:14:22 +08:00
世界 e329bf6865 Update dependencies 2023-12-14 15:09:03 +08:00
世界 2badcec765 platform: Fix check config 2023-12-12 20:26:41 +08:00
世界 e71c13b1a2 documentation: Bump version 2023-12-12 13:54:23 +08:00
世界 a959a67ed3 FIx error handling for netlink banned in Android 2023-12-12 13:54:23 +08:00
世界 a1044af579 platform: Fix VPN route 2023-12-11 21:59:59 +08:00
世界 a64b57451a Update dependencies 2023-12-11 21:40:11 +08:00
世界 f0e2318cbd Fix auto-route IPv6 on darwin 2023-12-11 21:39:29 +08:00
世界 ebec308fd8 documentation: Bump version 2023-12-09 00:22:27 +08:00
世界 ca094587be Fix incorrect dependency 2023-12-09 00:22:27 +08:00
世界 ca3b86c781 Update bug report template 2023-12-08 21:56:30 +08:00
世界 5a1d0047b9 documentation: Bump version 2023-12-08 21:38:34 +08:00
世界 4669854039 Fix method check for v2ray HTTP transport 2023-12-08 21:12:52 +08:00
世界 2eecdc38a4 Fix gun conn setup 2023-12-08 21:10:36 +08:00
世界 83581b7c1a Update dependencies 2023-12-08 11:18:52 +08:00
世界 d346f0023d Fix HTTP connect client again 2023-12-08 11:18:52 +08:00
世界 47b7a29cbd Fix fallback packet conn 2023-12-06 18:47:50 +08:00
世界 cffc07579d Fix missing omitempty for NTP server fields 2023-12-05 18:32:21 +08:00
世界 0ef268637e Prevent nil LocalAddr or RemoteAddr 2023-12-05 15:11:09 +08:00
世界 50f5a76380 Update dependencies 2023-12-04 21:06:15 +08:00
世界 20ca05dd36 Fix crash on websocket concurrent request 2023-12-04 20:42:01 +08:00
世界 5a792b186a documentation: Bump version 2023-12-03 16:54:49 +08:00
世界 3f458064a3 Fix not set Host header for HTTP outbound 2023-12-03 16:54:49 +08:00
世界 5269231df0 Fix URLTest outbound 2023-12-02 17:55:58 +08:00
世界 fc8e49994c documentation: Bump version 2023-12-01 20:39:01 +08:00
世界 e911d4aa4b Fix URLTest group early start 2023-12-01 20:39:01 +08:00
世界 01f6e70bc5 Fix deadline usage 2023-12-01 20:39:01 +08:00
世界 5f1e39a42c documentation: Bump version 2023-11-29 21:01:28 +08:00
世界 4f7770e254 Update dependencies 2023-11-29 21:01:19 +08:00
世界 e8c4c942c0 documentation: Bump version & Refactor docs 2023-11-28 11:21:57 +08:00
世界 253976d6c0 Add wifi_ssid and wifi_bssid route and DNS rules 2023-11-28 11:21:44 +08:00
世界 f0571b4122 Update quic-go to v0.40.0 2023-11-28 11:21:44 +08:00
世界 1b71e52e90 Migrate multiplex and UoT server to inbound & Add tcp-brutal support for multiplex 2023-11-28 11:21:44 +08:00
世界 6d24be23da Add support for v2ray http upgrade transport 2023-11-28 11:21:44 +08:00
世界 2a45c178fa Add exclude route support for tun &
Update gVisor to 20231113.0
2023-11-28 11:21:43 +08:00
世界 81e214812f Add udp_disable_domain_unmapping inbound listen option 2023-11-28 11:21:43 +08:00
世界 4d23773a25 Migrate to gobwas/ws 2023-11-28 11:21:43 +08:00
世界 40a0b69918 Fix dhcp reset 2023-11-28 11:20:48 +08:00
世界 a7b37c5953 documentation: Bump version 2023-11-24 20:58:48 +08:00
世界 03663a5093 Fix cachefile permission 2023-11-24 20:58:48 +08:00
世界 b08226a850 Fix "Fix HTTP server leak" 2023-11-24 19:58:31 +08:00
世界 edbae5dc4d Fix missing UDP user context on TUIC/Hysteria2 inbounds 2023-11-24 19:56:43 +08:00
世界 0f8ad0234b Remove unused code 2023-11-24 19:55:53 +08:00
世界 661eadc3bd documentation: Bump version 2023-11-21 10:22:44 +08:00
世界 50c1290567 Update dependencies 2023-11-21 10:22:44 +08:00
世界 eaccc9759a Fix platform API check 2023-11-21 10:22:44 +08:00
世界 925214869b Add test for ss2022 EIH 2023-11-20 18:36:44 +08:00
世界 6a2bfd26d0 Fix QUIC sniffer 2023-11-16 22:48:16 +08:00
世界 72a81afb76 Fix "Fix Linux IPv6 auto route rules" 2023-11-16 18:25:07 +08:00
世界 240abe204c Fix zero TTL was incorrectly reset 2023-11-16 18:25:07 +08:00
世界 7c49196792 build: Fix bad environment key 2023-11-16 01:42:24 +08:00
嫦悅and世界 3a2808cff6 documentation: Fix typo
The old meaning is wrong. Correct the meaning according to the English documentation and the actual effect of the option.

Signed-off-by: 嫦悅 <lomombwlo@gmail.com>
2023-11-16 01:12:26 +08:00
guangwuandGitHub 005d6cf4cf chore: unnecessary use of fmt.Sprintf 2023-11-16 01:10:52 +08:00
世界 36dff630d6 documentation: Bump version 2023-11-15 14:10:37 +08:00
世界 1825869124 platform: Refactor log interface 2023-11-15 14:10:37 +08:00
世界 3cadc90375 Fix TUIC authentication failed error message 2023-11-14 20:15:41 +08:00
renovate[bot]世界renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2c6967d7f9 dependencies: Update actions/checkout digest to b4ffde6
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-11-14 20:15:41 +08:00
世界 fe866b123a Fix sing-tun version 2023-11-14 20:15:41 +08:00
世界 cbef1b1e59 Remove apk build due to missing openrc configuration 2023-11-14 20:15:41 +08:00
世界 e21f84932c build: Fix missing linux/386 2023-11-14 10:35:27 +08:00
0x7d274284andGitHub 7a679bc328 Fix Dockerfile
Keep the .git folder at compile time to get the correct version

Signed-off-by: 0x7d274284 <112329548+0x7d274284@users.noreply.github.com>
2023-11-14 10:34:38 +08:00
世界 6635dd9abc documentation: Bump version 2023-11-13 21:50:36 +08:00
世界 ce164724ea build: Add apk and archlinux package builds 2023-11-13 15:28:28 +08:00
世界andmaskedeken a3ef7a7d88 Fix trojan-go mux context
Co-authored-by: maskedeken <maskedeken@yahoo.com>
Co-authored-by: 世界 <i@sekai.icu>
2023-11-13 14:12:35 +08:00
世界 71218ef0d3 build: Unify build tags 2023-11-13 14:12:35 +08:00
世界andMahdi-zarei e777b4c6dc Fix not closing outConn
Co-authored-by: Mahdi-zarei  <mahdi.zrei@gmail.com>
Co-authored-by: 世界 <i@sekai.icu>
2023-11-13 13:54:03 +08:00
世界 6815f94180 build: Update Go to 1.20.11 for legacy builds 2023-11-13 13:47:15 +08:00
世界 b013acd89d tun: Fix broadcast filter not applied to mixed stack 2023-11-13 13:35:10 +08:00
世界 f7c2eb6e76 Fix v2ray ws crash 2023-11-13 13:34:31 +08:00
世界 3ef9b1b343 Update protobuf generated binary 2023-11-10 10:56:25 +08:00
SakuraWaldand世界 2224c68959 Fix issue template 2023-11-10 10:36:46 +08:00
Kumiko as a ServiceandGitHub bb7d03d1db Use golang's cross-compilation capabilities 2023-11-10 10:36:32 +08:00
世界 50036924e8 documentation: Bump version 2023-11-10 10:24:18 +08:00
世界 c2c3f7284f Revert "Fix Host ignored in v2ray websocket transport"
This reverts commit aaa6702863.
2023-11-09 16:55:47 +08:00
世界 f6fee53676 Fix mux client close 2023-11-09 16:55:47 +08:00
世界 63b8e8ed23 platform: Increase HTTP timeout to 15s 2023-11-09 16:55:47 +08:00
世界 6ae86eda98 build: Update gradle command 2023-11-09 16:55:47 +08:00
世界 267d9617b7 build: Fix tag calculate 2023-11-07 22:27:37 +08:00
世界 0a06ccae50 platform: Fix legacy code 2023-11-07 22:14:23 +08:00
世界 8de0fad9f5 documentation: Bump version 2023-11-07 10:20:05 +08:00
世界 e05bf6308e Fix build script 2023-11-07 10:20:05 +08:00
世界 a20a0cb455 Add broadcast filter 2023-11-07 10:20:05 +08:00
世界 d29f7475d2 documentation: Bump version 2023-11-06 19:37:45 +08:00
世界 aaa6702863 Fix Host ignored in v2ray websocket transport 2023-11-05 23:27:11 +08:00
世界 bb928f096a Fix missing default next proto in hysteria2 2023-11-05 23:11:40 +08:00
johnthecoderproand世界 9f01d5c5b4 Fix download geo resources 2023-11-05 16:03:15 +08:00
世界 11629a931b Update release script 2023-11-05 16:02:18 +08:00
世界 126f825241 Update dependencies 2023-11-05 16:02:10 +08:00
世界 998cc7bd22 Add multicast filter for tun 2023-11-04 08:04:17 +08:00
世界 3efccaa8f5 Update dependencies 2023-10-31 18:24:58 +08:00
世界 d57b35ec30 documentation: Add privacy policy for android 2023-10-31 17:32:18 +08:00
世界 e82dab027d documentation: Bump version 2023-10-30 13:59:49 +08:00
世界 9350f3983b docs: Remove obsolete fields 2023-10-30 13:59:49 +08:00
世界 53b123241f android: Add build info tools for debug 2023-10-30 12:41:24 +08:00
世界 97286eea1e Add TLS self sign generate command 2023-10-30 12:41:23 +08:00
世界 343e24969d Add brutal debug option for Hysteria2 2023-10-30 12:41:23 +08:00
世界 31c294d998 Update BBR and Hysteria congestion control & Migrate legacy Hysteria protocol to library 2023-10-30 12:41:22 +08:00
世界 3b161ab30c Fix netip.Prefix usage 2023-10-30 12:41:22 +08:00
septsand世界 41fd1778a7 Improve HTTP headers option 2023-10-30 12:41:22 +08:00
septsand世界 ac930cf1aa Improve naive auth logical 2023-10-30 12:41:22 +08:00
世界 e143fc510d Update gVisor to 20230814.0 2023-10-30 12:41:21 +08:00
世界 bea177a4cd Improve linux bind interface 2023-10-30 12:41:21 +08:00
世界 aa05a4d050 Remove deprecated features 2023-10-30 12:41:21 +08:00
世界 a8112ff824 Update workflows 2023-10-30 12:40:52 +08:00
世界 a7710c3845 documentation: Bump version 2023-10-30 10:42:42 +08:00
世界 cb2e15f8a7 Fix UDP domain NAT 2023-10-28 21:41:39 +08:00
世界 23aa8a0543 Add legacy builds for old Windows and macOS versions 2023-10-26 14:02:24 +08:00
世界 edf7d046eb Fix outbound not found message 2023-10-26 14:02:19 +08:00
世界 de0b5cc1c2 Fix Linux IPv6 auto route rules 2023-10-26 12:02:00 +08:00
世界 2686e8afea Fix TUIC server TLS config not started 2023-10-26 12:01:28 +08:00
世界 d9853ca2be Update dependencies 2023-10-26 11:57:18 +08:00
世界 b617eb5adf documentation: Bump version 2023-10-23 14:09:09 +08:00
世界 ddf38799e2 makefile: Fix release command 2023-10-23 14:09:06 +08:00
世界 5291d43dc8 makefile: Add -allowProvisioningUpdates to Apple build commands 2023-10-21 17:51:00 +08:00
世界 a634830d85 Fix invalid address check in UoT conn 2023-10-21 17:23:30 +08:00
世界 e5d191ca73 Add retry for bbolt open 2023-10-14 19:24:05 +08:00
世界 2371f0fd51 Update dependencies 2023-10-14 17:36:35 +08:00
世界 cfdce7a96f Fix bbolt panic on arm32 2023-10-14 17:36:13 +08:00
世界 dc8ac01dec documentation: Bump version 2023-10-11 12:05:31 +08:00
世界 5f18738b2b Fix task cancel context 2023-10-11 12:05:27 +08:00
世界 7b4e4ca2d0 Fix compatibility with Android 14 2023-10-10 15:09:49 +08:00
世界 01ba4668b6 platform: Also reset connections on wake 2023-10-10 15:08:18 +08:00
dyhkwongand世界 e782d21806 Fix connect domain for IP outbound 2023-10-10 15:08:16 +08:00
世界 00155d61fc documentation: Bump version 2023-10-07 10:04:10 +08:00
世界 8f2273a2b4 documentation: Bump version 2023-10-06 17:10:53 +08:00
世界 0d0526afa2 Update dependencies 2023-10-06 17:10:31 +08:00
世界 ac2d07b61a Fix UDP dialer network 2023-10-03 11:08:31 +08:00
世界 d35487f422 Fix ip_version does not take effect 2023-10-03 11:01:25 +08:00
世界 2749f4a013 documentation: Bump version 2023-10-03 09:22:29 +08:00
世界 45c679648e platform: Fix log server 2023-10-03 09:22:29 +08:00
世界 5f2f7fc8b9 Fix HTTP inbound leak 2023-10-01 14:39:58 +08:00
世界 83c79102cf Update xcode version script 2023-10-01 14:05:51 +08:00
世界 8b95292e53 Update dependencies 2023-09-30 22:34:54 +08:00
世界 3de7a2ddd3 Fix concurrent access on task returnError 2023-09-30 21:52:11 +08:00
Shanoa IceandGitHub 8437a6cb4e Fix set KDE system proxy 2023-09-30 16:44:58 +08:00
世界 9c4d08c6e1 documentation: Bump version 2023-09-28 16:02:54 +08:00
世界 e26096085e Remove invalid code 2023-09-28 15:52:05 +08:00
世界 2f1b2199c5 Fix DHCPv4 listen address 2023-09-27 18:25:23 +08:00
世界 af791db01f documentation: Bump version 2023-09-27 14:16:04 +08:00
世界 abcf030d89 Update dependencies 2023-09-27 14:16:04 +08:00
世界 7840dc73e3 Fix resolve dialer 2023-09-27 13:17:16 +08:00
世界 df9050400e android: Fix netlink check 2023-09-26 17:41:07 +08:00
世界 fdd38d6cf8 documentation: Bump version 2023-09-25 21:56:32 +08:00
世界 9891fd672f Reject SOCKS4 unauthenticated request 2023-09-25 21:16:14 +08:00
世界 92a84ee112 Update dependencies 2023-09-25 17:56:21 +08:00
世界 992331f17e documentation: Bump version 2023-09-24 14:40:03 +08:00
世界 4fb227ed86 Fix payload not return to pool 2023-09-24 14:40:03 +08:00
世界 5a1ddea100 Fix dns log 2023-09-24 12:38:33 +08:00
世界 fbaa2f9de9 Fix merge command 2023-09-24 12:12:35 +08:00
世界 97ab9bb194 Fix shadow-tls user context 2023-09-24 12:12:35 +08:00
世界 61ac141124 Improve URLTest delay calculate 2023-09-23 20:27:43 +08:00
世界 d4d49d9df5 Fix ACME DNS01 DNS challenge 2023-09-23 20:26:46 +08:00
世界 c60a944aac Fix missing context in geo resources download 2023-09-23 20:26:46 +08:00
世界 17584c245f documentation: Bump version 2023-09-22 12:08:09 +08:00
世界 6e84b694a4 Minor fixes 2023-09-22 12:07:39 +08:00
世界 34a93171f0 Update dependencies 2023-09-20 22:20:40 +08:00
世界 678f6ef72f Fix debug.SetMemoryLimit usage 2023-09-20 22:01:58 +08:00
世界 ae8187ed15 documentation: Bump version 2023-09-20 14:15:54 +08:00
世界 12dd1ac87f Improve conntrack 2023-09-20 14:15:00 +08:00
世界 85c8f00885 documentation: Bump version 2023-09-19 19:59:29 +08:00
世界 e7b7ae811f Add merge command 2023-09-19 19:59:07 +08:00
世界 a9743b77f6 Don't return success as an error when the lookup result is empty 2023-09-19 19:05:23 +08:00
世界 4068871d97 Update quic-go 2023-09-19 18:33:44 +08:00
世界 f05afcea39 Update dependencies 2023-09-19 18:33:06 +08:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
688e9daef4 [dependencies] Update github-actions
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-09-17 13:12:03 +08:00
世界 64edacffb7 Bump version 2023-09-17 01:09:48 +08:00
世界 743df5373b Fix hysteria2 mbps calculation 2023-09-17 01:09:48 +08:00
世界 e80084316d Fix panic on create system proxy failed 2023-09-17 01:09:41 +08:00
世界 9dcd427743 Fix v2ray websocket transport 2023-09-17 01:09:41 +08:00
世界 d17e93384b Add ACME DNS01 challenge support via libdns 2023-09-17 01:09:41 +08:00
世界 c1ffcf365e Fix test 2023-09-16 23:45:47 +08:00
世界 3040e97222 Fix gomobile build on macOS 2023-09-16 00:09:45 +08:00
世界 5f063fb0b5 Update Makefile 2023-09-16 00:09:41 +08:00
世界 a7dadd8671 documentation: Update Clash default_mode description 2023-09-16 00:09:41 +08:00
世界 c320be75a7 Add interrupt support for outbound groups 2023-09-16 00:09:41 +08:00
世界 bd7adcbb7e Migrate QUIC wrapper and protocol implementations to library 2023-09-16 00:09:41 +08:00
世界 1d6d3edec5 documentation: Update changelog for stable versions 2023-09-15 17:34:39 +08:00
世界 46bfeb574c documentation: Bump version 2023-09-12 15:57:33 +08:00
世界 a1449ee40e Mark deprecated features 2023-09-12 13:26:23 +08:00
世界 8cb41b5fa6 documentation: Add hysteria2 2023-09-12 13:26:22 +08:00
世界 53475c7390 Add hysteria2 protocol 2023-09-12 13:26:21 +08:00
世界 5d8af150a7 Improve system proxy API 2023-09-12 13:26:21 +08:00
69499a51a5 Add KDE set system proxy support
Co-authored-by: Hiddify <114227601+hiddify1@users.noreply.github.com>
2023-09-12 13:26:20 +08:00
世界 4c050d7f4b Add ECH support for QUIC based protocols 2023-09-12 13:26:20 +08:00
世界 533fca9fa3 documentation: Update TLS ECH struct 2023-09-12 13:26:20 +08:00
世界 187bf2f7bc Enable with_ech by default 2023-09-12 13:26:19 +08:00
世界 983a4222ad Add ECH keypair generator 2023-09-12 13:26:19 +08:00
世界 2ea506aeb8 Remove legacy NTP usages 2023-09-12 13:26:19 +08:00
世界 5b343d4c72 Improve ECH support 2023-09-12 13:26:19 +08:00
世界 be61ca64d4 Fix SOCKS outbound 2023-09-12 13:26:03 +08:00
世界 efe33cf48d Fix QUIC DNS 2023-09-12 13:14:21 +08:00
世界 fe8d46cce5 Fix TFO async write 2023-09-09 19:52:13 +08:00
世界 b1f289bce5 Fix TUIC context 2023-09-09 11:41:04 +08:00
世界 a8beb80876 Update Makefile 2023-09-07 22:37:55 +08:00
世界 ff209471d8 Fix QUIC defragger 2023-09-07 21:35:25 +08:00
unknownand世界 806f7d0a2b Fix QUIC stream usage 2023-09-07 21:34:36 +08:00
世界 6b943caf37 Reject invalid connection 2023-09-07 21:34:36 +08:00
世界 4ea2d460f4 Fix router close 2023-09-07 21:34:35 +08:00
世界 c84c18f960 platform: Fix crash on android 2023-09-07 21:34:35 +08:00
世界 1402bdab41 Fix connect domain for IP outbounds 2023-09-07 21:34:35 +08:00
renovate[bot]and世界 7082cf277e [dependencies] Update actions/checkout action to v4 2023-09-07 21:34:35 +08:00
世界 b9310154a7 clash-api: Move default mode to first 2023-09-07 21:34:35 +08:00
世界 55c34e3fb0 platform: Improve client 2023-09-07 21:34:35 +08:00
世界 68f2202eec documentation: Bump version 2023-08-31 23:32:44 +08:00
renovate[bot]世界renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
5057e50bb8 [dependencies] Update actions/stale action to v8
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-08-31 23:32:44 +08:00
世界 23e1a69955 Update Makefile 2023-08-31 23:32:44 +08:00
世界 b83c6c9d20 Fix return nil addr in conn 2023-08-30 21:28:03 +08:00
世界 67deac6d44 Fix hysteria packet write 2023-08-30 18:23:17 +08:00
世界 ea3731162b Update Makefile 2023-08-30 18:23:17 +08:00
世界 c75e32e722 documentation: Update changelog 2023-08-29 10:26:11 +08:00
世界 e7b35be5f6 Update Makefile 2023-08-29 10:26:11 +08:00
世界 5a309266f0 Fix TUIC client 2023-08-28 19:58:02 +08:00
世界 05669eaaad documentation: Update changelog 2023-08-25 20:33:16 +08:00
世界 e91a6e5439 Update dependencies 2023-08-25 20:21:14 +08:00
世界 43f72a6419 Add store_mode and platform Clash mode selector 2023-08-25 20:21:14 +08:00
世界 6dcacf3b5e Fix sniffer 2023-08-24 21:53:06 +08:00
世界 edad4d1ce7 Update dependencies 2023-08-24 11:31:29 +08:00
世界 262842c87d Fix test 2023-08-22 11:22:13 +08:00
世界 376f527742 documentation: Bump version 2023-08-21 18:24:31 +08:00
世界 c0bbb3849d Fix TUIC UDP 2023-08-21 18:16:38 +08:00
世界 738c25d818 Fix Makefile 2023-08-21 18:14:27 +08:00
dyhkwongandGitHub 027af4d4ee Fix SOCKS5 UDP sniffing accidentially enabled 2023-08-20 19:06:37 +08:00
世界 6011f4483a Remove bad scripts 2023-08-20 17:57:39 +08:00
世界 fc22466e3b documentation: Bump version 2023-08-20 17:29:22 +08:00
世界 975e13a313 Add [include/exclude]_interface iproute2 options 2023-08-20 17:29:22 +08:00
世界 f46732bc0e Add udp over stream support for TUIC 2023-08-20 14:15:22 +08:00
世界 5c5c25e3ad Update tfo-go 2023-08-20 13:32:07 +08:00
世界 53a0bf2d11 minor: Remove unused parameter 2023-08-20 13:32:07 +08:00
renovate[bot]and世界 7b79d98f59 [dependencies] Update golang Docker tag to v1.21 2023-08-20 13:31:56 +08:00
世界 1dd2c26f31 Fix UDP route 2023-08-20 13:31:55 +08:00
armv9and世界 d14170348d Fix process search with fakeip 2023-08-20 13:31:55 +08:00
世界 9f94b21687 platform: Add group expand status 2023-08-20 13:31:55 +08:00
世界 cf57e46d69 Add new issue template 2023-08-20 13:31:49 +08:00
世界 b459001600 Update documentation 2023-08-20 13:31:48 +08:00
世界 73267fd6ad Fix ci build 2023-08-20 13:31:48 +08:00
世界 1019ecfdcf Add TCP MultiPath support 2023-08-20 13:31:48 +08:00
世界 81b847faca Pause recurring tasks when no network 2023-08-20 13:31:48 +08:00
世界 ce4c76cdd2 documentation: Add TUIC 2023-08-20 13:31:47 +08:00
世界 917420e79a Add TUIC protocol 2023-08-20 13:31:40 +08:00
世界 0b14dc3228 Update quic-go 2023-08-20 13:31:40 +08:00
世界 cbdaf3272b Update dependencies 2023-08-20 13:31:36 +08:00
世界 d51ab2b0a7 Fix missing HandshakeConn interface 2023-08-20 13:31:31 +08:00
世界 1363e16312 platform: Enable Clash API support by default 2023-08-20 13:31:29 +08:00
世界 f43d0141f3 Save fakeip metadata immediately 2023-08-20 13:31:27 +08:00
世界 90b3aad83a Fix network monitor 2023-08-20 13:30:50 +08:00
世界 2675aff98a Fix tag detect 2023-08-07 22:07:24 +08:00
世界 09ffa2c66e documentation: Update changelog 2023-08-05 21:37:08 +08:00
世界 9fba4f02b6 Update dependencies 2023-08-05 21:37:08 +08:00
世界 59987747e5 platform: Improve status 2023-08-04 21:10:32 +08:00
世界 c40140bbae Fix UDP async write 2023-08-04 12:38:51 +08:00
世界 2123b216c0 Fix http proxy server again 2023-08-04 12:38:51 +08:00
世界 1983f54907 platform: Add sleep support for NetworkExtension 2023-08-04 12:38:51 +08:00
世界 8d629ef323 documentation: Update changelog 2023-07-31 09:49:07 +08:00
世界 f57bee2f4b Update quic-go 2023-07-31 09:49:07 +08:00
世界 679739683e Update dependencies 2023-07-31 09:07:32 +08:00
世界 4fcce1f073 Fix http proxy server 2023-07-31 09:04:55 +08:00
世界 ff14220e08 platform: Update profile binary format 2023-07-30 20:55:27 +08:00
世界 a7b7a5c3c5 documentation:Add tvOS page 2023-07-29 21:09:15 +08:00
世界 b054441f34 platform: Add support for tvOS 2023-07-29 21:01:43 +08:00
世界 1e31d26e03 documentation: Update installation 2023-07-29 21:01:43 +08:00
世界 ffe515d0e0 documentation: Update changelog 2023-07-25 13:21:15 +08:00
世界 aad021f521 Fix gVisor UDP 2023-07-25 08:28:24 +08:00
世界 4a986459ee documentation: Update changelog 2023-07-24 17:56:39 +08:00
世界 9532d0cba4 Fix cache file 2023-07-24 16:51:03 +08:00
世界 cadc34f3ad Add support for macOS system extension 2023-07-24 16:51:03 +08:00
世界 db23a48b36 Update dependencies 2023-07-23 14:23:51 +08:00
世界 407cf68e59 Fix certmagic usage 2023-07-20 20:03:20 +08:00
世界 e0058ca9c5 Fix fakeip unsaved state 2023-07-20 19:59:04 +08:00
世界 8140af01aa Fix download geo resources 2023-07-20 19:41:22 +08:00
世界 98bf696d01 Fix cache file 2023-07-20 19:41:22 +08:00
世界 e075bb5c8d Update changelog 2023-07-19 14:59:30 +08:00
世界 c6baabedef Update dependencies 2023-07-19 14:45:30 +08:00
世界 6e6998dab7 Improve platform status 2023-07-16 14:08:45 +08:00
世界 1a29c23263 documentation: Update changelog 2023-07-15 14:53:48 +08:00
世界 0f87396ab6 Fix abx reader for some malformed formats 2023-07-15 14:46:15 +08:00
世界 ffde948860 Update support page 2023-07-15 14:46:09 +08:00
世界 69b5dbdcc3 Build memory limiter for android 2023-07-15 14:46:06 +08:00
世界 1121517755 Fix hysteria inbound context 2023-07-11 20:58:20 +08:00
世界 6879def619 Fix test 2023-07-11 15:44:03 +08:00
世界 5c0f6d0a6f Fix vmess legacy server 2023-07-11 15:44:03 +08:00
世界 d74abbd20e Fix v2ray websocket transport 2023-07-11 15:44:03 +08:00
世界 120dae4eed Fix fakeip lookup 2023-07-11 15:44:02 +08:00
世界 bb651db2d2 platform: Fix output format 2023-07-09 12:24:43 +08:00
世界 e929dde13e documentation: Update changelog 2023-07-09 07:54:08 +08:00
世界 9d75385bbb Fix async FakeIP save 2023-07-08 16:21:11 +08:00
世界 1c526feec1 Update dependencies 2023-07-08 16:19:28 +08:00
世界 7df26986de documentation: Update changelog 2023-07-07 14:23:45 +08:00
世界 5f2d23a12d Fix multi error 2023-07-07 13:57:28 +08:00
世界 d9e65c0969 Fix syscall copy packet 2023-07-07 13:42:42 +08:00
世界 ec1160924f Fix save FakeIP cache 2023-07-07 12:51:38 +08:00
世界 230e8f895d Fix close quic.Listener 2023-07-07 12:43:22 +08:00
世界 af79378734 Update dependencies 2023-07-03 21:47:32 +08:00
世界 07ce5e0d22 Remove stack buffer usage 2023-07-03 21:45:32 +08:00
世界 9c8565cf21 platform: Add group interface 2023-07-02 18:46:41 +08:00
世界 5ad0ea2b5a Try fix StreamDomainNameQuery 2023-07-02 16:38:38 +08:00
世界 e482053c8a documentation: Update changelog 2023-06-27 11:31:24 +08:00
世界 945713d886 Update dependencies 2023-06-27 11:13:30 +08:00
世界 9bb62ad6b5 Check duplicated outbound tag 2023-06-26 18:47:52 +08:00
世界 c2bda9fbde Fix DNS rewrite_ttl logic 2023-06-23 16:12:25 +08:00
世界 1d1db62a44 Prevent write packet IPv6 packet to tun IPv4 connection 2023-06-21 13:29:24 +08:00
世界 39405373f8 documentation: Update changelog 2023-06-19 14:11:41 +08:00
世界 22a7988d3f Update dependencies 2023-06-19 14:11:41 +08:00
世界 b2092fafb7 Fix ios build
Cannot use errno as method and variable due to conflict with objc
2023-06-19 14:11:40 +08:00
世界 cc7b5d8280 Unwrap 4in6 address received by client packet conn 2023-06-19 13:29:41 +08:00
世界 702d96a738 platform: Improve local DNS transport 2023-06-18 10:00:32 +08:00
世界 b9f34f1309 documentation: Update changelog 2023-06-17 12:21:18 +08:00
世界 07724a0ddd Update dependencies 2023-06-17 12:17:43 +08:00
世界 83c3454685 Update quic-go 2023-06-15 14:52:25 +08:00
世界 7d263eb733 documentation: Update changelog 2023-06-14 16:28:44 +08:00
世界 222687d9c5 Update goreleaser usage 2023-06-14 09:39:13 +08:00
世界 07d3652e30 Build with_dhcp by default 2023-06-14 09:14:45 +08:00
世界 8d5b9d240a Fix outbound start sequence 2023-06-13 22:38:05 +08:00
世界 4f12eba944 Fix hysteria outbound 2023-06-13 21:41:33 +08:00
世界 a7f77d59c1 Update documentation 2023-06-11 22:38:37 +08:00
shadow750d6and世界 597248130f Reconnect once if hysteria request fails
This allows graceful recovery when network isn't good enough.

[Original hysteria source
code](https://github.com/apernet/hysteria/blob/13d46da99876c2c9feb1083ff5f2da201d9d0a1e/core/cs/client.go#L182)
has similar mechanism.
2023-06-11 22:21:32 +08:00
世界 3c2c9cf317 Migrate gVisor to fork 2023-06-11 22:07:36 +08:00
世界 e572b9d0cd Update dependencies 2023-06-11 20:58:59 +08:00
世界 52e9059a8d Fix fakeip routing 2023-06-11 20:58:59 +08:00
世界 0cb9cff690 Fix shadowsocks none client 2023-06-08 10:23:39 +08:00
世界 c0669cb2a5 Fix TLS 1.2 support for shadow-tls client 2023-06-07 21:03:39 +08:00
世界 c5902f2473 Fix using v2ray websocket transport with detour 2023-06-07 21:03:21 +08:00
世界 22028602e8 Improve read waiter interface 2023-06-07 21:03:11 +08:00
世界 bd54608473 Fix DNS outbound 2023-06-07 21:03:08 +08:00
世界 3741394269 Add cache_id option for Clash cache file 2023-06-07 21:03:06 +08:00
世界 6266d2df7e Fix shadowsocks AEAD UDP server 2023-06-07 21:02:52 +08:00
世界 01dfba722a Use API to create windows firewall rule 2023-06-07 21:01:29 +08:00
世界 f8d5f01665 Reimplemented shadowsocks client 2023-06-07 20:57:07 +08:00
Hellojackand世界 ad999d4791 Fix UVariantLen usage 2023-06-07 20:56:57 +08:00
世界 6f1b258501 Improve DNS caching 2023-06-07 20:56:55 +08:00
世界 f949ddc0ab Set TCP keepalive for WireGuard gVisor TCP connections 2023-06-07 20:53:26 +08:00
Weltolkand世界 f53007cbf3 documentation: Fix fakeip link broken 2023-06-07 20:53:13 +08:00
世界 c287731df9 Improve direct copy 2023-06-07 20:53:00 +08:00
世界 bc32c78d03 Improve multiplex 2023-06-07 20:46:34 +08:00
世界 daee0db7bb clash-api: Reset outbounds in DELETE /connections 2023-06-07 20:45:39 +08:00
世界 91fbf4c79b Add multiplexer for VLESS outbound 2023-06-07 20:45:39 +08:00
世界 54d9ef2f2a Update gVisor to 20230417.0 2023-06-07 20:45:25 +08:00
世界 e056d4502b Add debug http server 2023-06-07 20:45:25 +08:00
世界 98c2c439aa Add filemanager api 2023-06-07 20:45:25 +08:00
世界 b6068cea6b Update wireguard-go 2023-06-07 20:38:30 +08:00
世界 9c9affa719 Ignore system tun stack bind interface error 2023-06-07 20:35:02 +08:00
世界 8eb7dd0059 Improve VLESS request 2023-06-07 20:35:00 +08:00
世界 a62ad44883 Add deadline interface 2023-06-07 20:34:56 +08:00
世界 2850354070 shadowsocks: Multi-user support for legacy AEAD inbound
Signed-off-by: wwqgtxx <wwqgtxx@gmail.com>
2023-06-07 20:34:54 +08:00
世界 0a4abcbbc8 Add headers option for HTTP outbound 2023-06-07 20:34:52 +08:00
世界 b491c350ae URLTest improvements 2023-06-07 20:33:56 +08:00
世界 1fbe7c54bf Fix wireguard reconnect 2023-06-07 20:33:53 +08:00
世界 9d32fc9bd1 Use HTTPS URLTest source 2023-06-07 20:33:50 +08:00
世界 542612129d clash-api: Add Clash.Meta APIs 2023-06-07 20:33:41 +08:00
世界 750f87bb0a clash api: download clash-dashboard if external-ui directory is empty 2023-06-07 20:33:06 +08:00
世界 e168de79c7 Add multi-peer support for wireguard outbound 2023-06-07 20:33:04 +08:00
世界 9bca5a517f Add fakeip support 2023-06-07 20:31:26 +08:00
世界 aa94cfb876 Refactor rules 2023-06-07 20:28:21 +08:00
世界 52b776b561 Add dns reverse mapping 2023-06-07 20:19:46 +08:00
世界 c74d3a53d4 documentation: Update changelog 2023-05-19 15:48:35 +08:00
世界 fe7ac80a6c Update dependencies 2023-05-19 15:48:35 +08:00
世界 e50b334b9a Fix uTLS ALPN 2023-05-19 15:41:18 +08:00
XYenonand世界 a0d8e374fb Fix incorrect use of sort.Slice 2023-05-19 15:40:48 +08:00
Larvan2and世界 d3a67cb5ae Enable mkdocs search in documentation
Signed-off-by: Larvan2 <78135608+Larvan2@users.noreply.github.com>
2023-05-19 15:40:42 +08:00
世界 e69e98b185 Fix documentation 2023-05-19 15:40:13 +08:00
世界 5e1499d67b Update badtls 2023-05-19 15:39:40 +08:00
世界 e8dad1afeb Fix grpc request 2023-04-22 19:51:04 +08:00
世界 6ce4e31fc8 documentation: Update changelog 2023-04-22 08:26:09 +08:00
世界 d2d4faf520 Revert LRU cache changes 2023-04-22 08:23:49 +08:00
世界 438de36749 Make v2ray http2 conn public 2023-04-22 08:14:55 +08:00
世界andarmv9 df0eef770e Fix http response check
Co-authored-by: armv9 <48624112+arm64v8a@users.noreply.github.com>
2023-04-22 08:14:55 +08:00
世界andarmv9 bbdd495ed5 Fix v2ray-plugin TLS server name
Co-authored-by: armv9 <48624112+arm64v8a@users.noreply.github.com>
2023-04-21 17:48:36 +08:00
世界andarmv9 d686172854 Fix grpc lite request host
Co-authored-by: armv9 <48624112+arm64v8a@users.noreply.github.com>
2023-04-21 17:48:36 +08:00
H1JKand世界 e1d96cb64e Add BaseContext to http servers 2023-04-21 17:48:29 +08:00
H1JKand世界 d5f94b65b7 Fix gRPC service name escape 2023-04-21 17:48:29 +08:00
Hellojackand世界 ec2d0b6b3c Remove TLS requirement for gRPC client 2023-04-21 17:48:29 +08:00
世界 3a92bf993d platform: Add UsePlatformAutoDetectInterfaceControl 2023-04-21 17:47:17 +08:00
armv9and世界 ec13965fd0 Fix HTTP sniffer 2023-04-19 21:58:58 +08:00
世界 ddf747006e Update to uuid v5 2023-04-19 21:58:58 +08:00
世界 4382093868 Prepare deadline interface 2023-04-19 21:58:58 +08:00
世界 a5322850b3 documentation: Update client notes 2023-04-19 21:58:58 +08:00
世界 407b08975c Remove legacy warnings 2023-04-19 21:58:58 +08:00
世界 c7067ff5e8 Fix default interface monitor for darwin 2023-04-19 21:58:58 +08:00
世界 9b2384b296 Add udpnat test 2023-04-19 21:43:13 +08:00
世界 b498a22972 Fix interface monitor for android 2023-04-19 21:42:40 +08:00
世界 20e9da5c67 Fix udp timeout 2023-04-19 21:42:10 +08:00
世界 ec8974673b Fix platform interface monitor & Fix system tun stack for ios 2023-04-19 21:40:03 +08:00
世界 5e6e7923e4 Fix shadowsocksr build 2023-04-17 18:06:43 +08:00
世界 de1b5971e1 Update documentation 2023-04-16 16:28:41 +08:00
世界 5c20d0b4d5 Update dependencies 2023-04-16 16:28:41 +08:00
世界 9df96ac7f1 Fix deadline usage on websocket conn 2023-04-16 16:28:40 +08:00
世界 87cd925144 Fix conntrack return pointer 2023-04-14 21:00:45 +08:00
世界 fecb796000 android: Remove Seq.Delete warning 2023-04-14 21:00:40 +08:00
世界 cfb6c804aa Print sniff result 2023-04-14 21:00:01 +08:00
世界 11c50c7558 Fix processing domain address in packet 2023-04-14 20:59:57 +08:00
世界 34cc7f176e Fix parsing query in http path 2023-04-14 20:59:16 +08:00
Xiaokang Wang (Shelikhoo)and世界 b54da9c6af Fix '?' at end of WebSocket path get escaped
This fix align sing-box's behaviour with V2Ray when it comes to processing ? at the end of WebSocket's path.
2023-04-14 20:58:12 +08:00
世界 f44f86b832 Fix workflows 2023-04-14 20:57:08 +08:00
世界 4ebf40f582 Fix find process user 2023-04-14 20:56:58 +08:00
世界 53e4302143 Fix set HTTP TLS ALPN 2023-04-14 20:56:55 +08:00
世界 cf778eda4f Fix v2ray http transport server read request 2023-04-14 20:56:51 +08:00
世界 bb63429079 Update cancel context usage 2023-04-14 20:56:16 +08:00
世界 f7f9a7ae20 Fix write log to stderr 2023-04-14 20:55:57 +08:00
世界 8699412a4c platform: Add stderr redirect 2023-04-14 20:55:45 +08:00
世界 0d7aa19cd1 Fix write http status after response sent 2023-04-14 20:55:20 +08:00
世界 50a7295360 Replace usages of uber/atomic 2023-04-14 20:55:05 +08:00
世界 e57b6ae98d Update dependencies 2023-04-14 20:54:56 +08:00
世界 6843970536 Add loopback check 2023-04-08 09:13:50 +08:00
世界 62425ad3e4 Add close monitor 2023-04-08 08:10:03 +08:00
世界 e1e217854e Add start and close track message 2023-04-08 08:09:28 +08:00
世界 5bf177b021 platform: Fix build on windows 2023-04-07 21:10:16 +08:00
世界 72dbf2e2b4 documentation: Update changelog 2023-04-07 19:18:26 +08:00
世界 46c318c6fe Fix v2ray HTTP/1.1 transport compatibility 2023-04-07 18:20:07 +08:00
世界 05bb1b88c3 dns: Fix rewrite TTL 2023-04-07 16:19:34 +08:00
世界 5176ea9fe0 Update dependencies 2023-04-07 16:19:34 +08:00
世界 36d349acd2 dns: Fix calculate TTL 2023-04-07 13:12:16 +08:00
世界 4feee983b5 Update reality protocol 2023-04-06 19:05:05 +08:00
世界 9b12e3e389 Update client documentation 2023-04-06 12:51:26 +08:00
世界 afd3464216 Minor fixes 2023-04-05 21:41:06 +08:00
世界 8b64446274 platform: Fixes and improvements 2023-04-05 19:54:20 +08:00
世界 28aa4c4d1f Refactor log factory constructor 2023-04-03 20:24:13 +08:00
世界 0be3cdc8fb platform: Add http client 2023-04-03 15:12:44 +08:00
armv9and世界 f8be484019 conntrack: Fix missing tracking for udp conn 2023-04-02 12:06:03 +08:00
世界 35f03f092d Improve UDP domain destination NAT 2023-04-02 12:05:59 +08:00
世界 c3d7401ead platform: Add check config func 2023-04-02 10:35:03 +08:00
世界 4db7eb9d9e documentation: Update changelog 2023-03-31 16:29:08 +08:00
世界 fd4efd6104 Fix dns transport read 2023-03-31 14:31:35 +08:00
世界 19a35ec6a4 Fix http2 transport close 2023-03-31 14:31:35 +08:00
世界 2012c0ca1e Update release scripts 2023-03-31 14:31:35 +08:00
世界 187421c754 Append time to session log 2023-03-31 14:31:35 +08:00
世界 b3fb86d415 Accept "any" outbound in dns rule 2023-03-31 14:31:35 +08:00
世界 88fafd4e30 Fix dns routing context 2023-03-31 09:14:04 +08:00
世界 8056932f9c Update documentation 2023-03-27 08:23:01 +08:00
世界 c8af003bfc Update dependencies 2023-03-27 08:22:56 +08:00
世界 4999441a85 Fix missing default host in v2ray http transport`s request 2023-03-27 08:20:59 +08:00
世界 09b001e795 Revert remove install shell 2023-03-27 08:20:55 +08:00
世界 3b3a251008 Update LICENSE 2023-03-27 08:20:51 +08:00
世界 2e4eb9aa39 Update dockerfile 2023-03-24 08:29:11 +08:00
世界 77fd284703 documentation: Update changelog 2023-03-24 08:04:36 +08:00
世界 0a4517f4b7 Update dependencies 2023-03-24 07:06:45 +08:00
世界 4395db3206 documentation: Update set_system_proxy usage 2023-03-23 21:27:50 +08:00
世界 dd5b0abc67 Fix slow open 2023-03-23 17:14:38 +08:00
世界 466800aa3a Fix wireguard mutex 2023-03-23 15:43:17 +08:00
世界 4328c535a9 Improve timeout canceler 2023-03-23 15:39:12 +08:00
世界 f9516709da Update documentation 2023-03-23 07:54:24 +08:00
世界 5dce722879 Update dependencies 2023-03-23 07:49:14 +08:00
世界 9324a39d4e Fix import format 2023-03-20 23:01:54 +08:00
世界 84904c5206 Create working directory if not exists 2023-03-20 19:33:00 +08:00
世界 fe4b429fc2 hysteria: Accept inbound configuration without users 2023-03-20 19:22:46 +08:00
世界 f680d0acaf Add with_reality_server to release build tags 2023-03-20 17:36:59 +08:00
世界 4baff5aeb1 documentation: Update changelog 2023-03-20 17:32:59 +08:00
世界 f25296fb23 Update dependencies 2023-03-20 17:27:48 +08:00
世界 e717852c73 Fix optional listen address 2023-03-19 20:46:22 +08:00
世界 13dc70f649 Fix make build 2023-03-19 16:57:07 +08:00
世界 46040a71c3 Fix vision padding overflow 2023-03-19 10:25:35 +08:00
世界 0558b3fc5c ntp: Add write_to_system service option 2023-03-18 23:11:40 +08:00
世界 99b2ab5526 Add command to fetch a URL 2023-03-18 21:02:29 +08:00
世界 e5f3bb6344 Add command to connect an address 2023-03-18 20:27:38 +08:00
世界 c7f89ad88e Add multiple configuration support 2023-03-18 20:27:38 +08:00
世界 e0d9f79445 Fix test 2023-03-18 17:02:55 +08:00
世界 b6dbb69fc4 Fix write nil in buffered vectorised writer 2023-03-18 16:32:28 +08:00
世界 b76fabee65 documentation: Fix broken link 2023-03-18 16:31:15 +08:00
世界 872bcfd1c0 readme: Add packaging status 2023-03-17 17:58:08 +08:00
世界 b033c13ca2 documentation: Update stable changelog 2023-03-17 17:58:08 +08:00
renovate[bot]世界renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2db188f3a1 dependencies: Update actions/setup-go action to v4
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-17 17:58:08 +08:00
世界 11de271c8f Add experimental debug options 2023-03-17 17:58:08 +08:00
世界 40c800c57c documentation: Fix typo 2023-03-17 13:34:36 +08:00
世界 91b0540e95 documentation: Update UoT application support status 2023-03-17 13:28:05 +08:00
世界 ce6d186345 Update documentation 2023-03-17 13:07:22 +08:00
世界 32bc4450a7 Update dependencies 2023-03-17 12:59:12 +08:00
世界 43f31b40ba Update UoT protocol 2023-03-17 12:57:48 +08:00
世界 a3a5185b15 platform: Fix bytes format 2023-03-16 11:28:54 +08:00
世界 14a0f180c8 ios: Add with_quic tag in build 2023-03-16 11:28:54 +08:00
世界 cc9cb0b477 platform: Add oom killer 2023-03-16 11:28:54 +08:00
世界 2cb0e37f50 platform: Add low memory interface 2023-03-16 00:36:04 +08:00
世界 dbd5be55b0 tun: Create gVisor stack by default in Apple Network Extension 2023-03-15 21:50:18 +08:00
世界 f674b4fbd5 Fix build embed tor for mobile 2023-03-15 20:59:45 +08:00
世界 5a4e8fea81 Fix lint 2023-03-15 14:56:06 +08:00
世界 78e02b52ca Update UoT protocol 2023-03-15 14:52:32 +08:00
世界 ffdaae90d7 Update dependencies 2023-03-15 11:59:15 +08:00
世界 c77681ea17 Fix close platform tun 2023-03-13 19:47:00 +08:00
世界 d824390167 Fix cross make build 2023-03-13 19:46:20 +08:00
世界 70cf681ff2 Remove length limit on short_id for reality TLS config 2023-03-13 19:46:16 +08:00
wwqgtxxand世界 b004b9ec81 Fix stack wireguard device returning non-nil interface containing nil pointer 2023-03-13 19:46:16 +08:00
世界 657b05fd96 Print command to shell error 2023-03-13 19:46:16 +08:00
世界 caad60da45 Apply --disable-color to global logger 2023-03-13 11:23:00 +08:00
世界 7d22cf9b45 Support $schema in configuration file 2023-03-13 10:58:29 +08:00
世界 5cb178ca93 Update documentation 2023-03-12 23:07:38 +08:00
世界 16788008b6 Update dependencies 2023-03-12 23:07:24 +08:00
世界 6ec7a33046 Fix make install 2023-03-11 19:24:19 +08:00
世界 6af9c2b3ca Add health check support for http-based v2ray transport 2023-03-11 15:49:02 +08:00
世界 bdc620dab1 Fix http server usage 2023-03-11 15:05:07 +08:00
世界 a88820af31 Fix missing default shadowtls version 2023-03-11 10:12:46 +08:00
世界 3688f2e114 Update documentation 2023-03-10 11:15:00 +08:00
世界 a183958d53 Update dependencies 2023-03-09 23:24:05 +08:00
世界 1c8a9e91b7 Generate version during compilation 2023-03-09 23:24:05 +08:00
世界 325f6c71ff Fix windows interface monitor 2023-03-09 16:00:57 +08:00
世界 6c6c0792ad Update reality and uTLS 2023-03-09 10:51:01 +08:00
世界 9264f2307c Fix link broken in installation documentation page 2023-03-08 15:56:41 +08:00
世界 87dd328700 Fix build check 2023-03-08 15:23:46 +08:00
世界 0cec92dd0f Update documentation 2023-03-08 14:59:09 +08:00
世界 e88afa9665 Fix vmess server buffer 2023-03-07 17:07:37 +08:00
世界 3883a81315 Check constant.Version before build release 2023-03-06 16:34:44 +08:00
Dmitry Rand世界 c919ad079a systemd: Add reload command 2023-03-06 16:32:54 +08:00
世界 83593aee70 Fix vless read cache 2023-03-06 11:19:38 +08:00
世界 ac7cc09694 Update documentation 2023-03-05 23:37:12 +08:00
世界 d032e3568b Update dependencies 2023-03-05 21:38:02 +08:00
世界 c24df037ac Add documentation for tun platform options 2023-03-05 15:19:13 +08:00
世界 a2d43b3746 Fix open cache file 2023-03-05 14:57:50 +08:00
世界 5b3b74bd0f Fix vision read 2023-03-05 14:57:50 +08:00
世界 d24d3b26dc Fix uTLS randomized fingerprint 2023-03-05 14:57:50 +08:00
seiunekoand世界 5db3cd7781 Fix documentation typo 2023-03-05 14:57:50 +08:00
世界 c88af8b081 Fix documentation 2023-03-05 14:57:50 +08:00
世界 45852ca3e7 Fix check config 2023-03-05 14:57:50 +08:00
Hellojackand世界 03ce555104 Add generate commands 2023-03-05 11:21:32 +08:00
世界 dd0a07624e Add stop platform command 2023-03-04 00:40:47 +08:00
世界 b9b2b77814 Add reload platform command 2023-03-03 21:59:54 +08:00
世界 2366835121 Fix close conn 2023-03-03 19:27:30 +08:00
database64128 42e1dea7d2 Update .gitignore 2023-03-03 18:51:33 +08:00
Ella Hollywoodand世界 13d7716b02 Fix documentation typo 2023-03-03 16:35:06 +08:00
世界 7ecb9fc738 Minor fixes 2023-03-03 16:31:07 +08:00
世界 19b15e0d10 Fix UoT UDP address 2023-03-03 11:34:51 +08:00
database64128 0b15de461b Update tfo-go 2023-03-03 10:16:38 +08:00
世界 27aba99e6c Fix command client connect 2023-03-02 16:40:28 +08:00
世界 8151bcfd6b Add ios memory limit 2023-03-02 15:04:59 +08:00
世界 e8802357e1 Fix vless tests 2023-03-02 00:31:56 +08:00
世界 6e22c004f6 Improve server error handling 2023-03-02 00:18:35 +08:00
世界 20e1caa531 Fix custom tls server listener 2023-03-02 00:01:40 +08:00
世界 32ad3c3db3 Remove okhttp form modern fingerprint list 2023-03-01 21:17:30 +08:00
世界 1f5f8a7dde Fixed user flow in vless server 2023-03-01 20:28:40 +08:00
世界 6da1460795 Fix geo resource download path 2023-03-01 19:09:21 +08:00
世界 b14ae51f71 Fix create badhttp2 server 2023-03-01 19:09:21 +08:00
世界 5af8d001ae Refactor platform command api 2023-03-01 19:09:21 +08:00
世界 0ca344df5f Fix uTLS ALPN 2023-02-28 21:16:31 +08:00
世界 49f568abbd Separate uTLS random fingerprint 2023-02-28 21:10:11 +08:00
世界 3b4e811907 Add reality client fallback 2023-02-28 20:55:14 +08:00
世界 d0e9443031 Enable XUDP by default in VLESS 2023-02-28 20:52:26 +08:00
世界 f7e9d9ab1f Fix check early conn 2023-02-28 20:16:15 +08:00
世界 7834d6bca7 Add tun platform options 2023-02-28 19:02:27 +08:00
世界 ed50257735 Add custom TLS server support for http based v2ray transports 2023-02-28 13:03:44 +08:00
世界 f15f525c5c Merge tls interface to library 2023-02-28 11:30:46 +08:00
世界 e4bff0460d Update vision protocol 2023-02-27 15:07:15 +08:00
世界 5ce3ddee9b Add early conn interface 2023-02-26 23:08:20 +08:00
世界 22bf7a9509 Update reality server 2023-02-26 20:55:36 +08:00
世界 842730707c Update TUN creation 2023-02-26 20:55:15 +08:00
世界 a8f13bd956 Fix documentation 2023-02-25 17:25:56 +08:00
世界 cd5c2a7999 Update documentation 2023-02-25 16:28:39 +08:00
世界andGitHub fbc94b9e3e Add VLESS server, vision flow and reality TLS 2023-02-25 16:24:08 +08:00
zakuwakiandGitHub e766f25d55 Fix private ip will never be matched 2023-02-24 13:31:49 +08:00
世界 140ed9a4cb Fix platform wrapper 2023-02-24 13:00:49 +08:00
世界 60094884cd Update documentation 2023-02-22 11:45:31 +08:00
H3arnandGitHub 0e8a4d141a Fix incorrect NTP server address 2023-02-21 23:08:05 +08:00
世界 17b78a6339 Fix documentation 2023-02-21 22:06:12 +08:00
世界 e99741159b Update documentation 2023-02-21 20:54:25 +08:00
世界 6b9603227b Add strict mode support for shadowtls v3 2023-02-21 20:51:26 +08:00
世界 23e8d282a3 Add multiple server names and multi-user support for shadowtls 2023-02-21 16:09:06 +08:00
世界 611d6bbfc5 Add NTP service 2023-02-21 16:09:06 +08:00
世界 f26785c0ba Add uTLS support for shadowtls v3 2023-02-20 21:04:07 +08:00
世界 5bcfb71737 Update dependencies 2023-02-20 21:04:07 +08:00
世界 4135c4974f Merge shadowtls to library 2023-02-20 13:53:06 +08:00
世界 222196b182 Add libbox wrapper 2023-02-20 11:07:49 +08:00
世界 86e55c5c1c Fix tproxy inbound 2023-02-19 18:56:38 +08:00
世界 73c068b96f Update documentation 2023-02-19 17:49:05 +08:00
世界 f516026540 Fix shadowtls in go versiojns below 1.20 2023-02-19 12:02:11 +08:00
dyhkwongandGitHub 3c5bc842ed Update QUIC v2 version number and initial salt 2023-02-18 23:51:55 +08:00
世界 d8270a66f4 Update release script 2023-02-18 21:14:17 +08:00
世界 123c383eae Fix documentation 2023-02-18 19:33:35 +08:00
世界 67814faf92 Remove TLS min version for shadowtls v3 2023-02-18 19:26:05 +08:00
世界 ec4a0c8497 Update documentation 2023-02-18 15:02:27 +08:00
世界andGitHub 21cb227bc2 Add ShadowTLS protocol v3 2023-02-18 14:55:47 +08:00
世界 1610bdc5dd Update workflow 2023-02-18 14:28:21 +08:00
世界 3296a2f7b2 Update dependencies 2023-02-18 14:28:21 +08:00
世界 2bd91baad0 Add fallback support for v2ray transport 2023-02-18 14:28:21 +08:00
世界 a624cd9b49 Disable vmess header protection if transport enabled 2023-02-13 05:15:26 +08:00
Tim XylonandGitHub 02afba132f Replace deprecated 'set-output' 2023-02-09 22:07:00 +08:00
世界 99890a1af0 Fix socks connect response 2023-02-09 21:25:00 +08:00
世界 437f1f819c Fix lint 2023-02-09 21:01:48 +08:00
世界 92a79e6158 Remove cancel-workflow-action 2023-02-09 18:04:49 +08:00
renovate[bot]世界renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
c9efd0a74f [dependencies] Update golang Docker tag to v1.20
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-09 18:04:16 +08:00
renovate[bot]GitHubrenovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
9da349748a [dependencies] Update github-actions
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-09 17:42:06 +08:00
世界 2423cbbbfe Add renovate config 2023-02-09 17:39:15 +08:00
Gavin Luoand世界 4833f6d5db Fix systemd service caps for process sniffing 2023-02-09 13:32:31 +08:00
世界 9db3cb5cb7 Update scripts 2023-02-09 13:27:05 +08:00
shadow750d6andGitHub c14b353a29 Fix parse hysteria UDP message 2023-02-09 13:20:16 +08:00
世界 19d08b55c8 Update documentation 2023-02-08 17:35:50 +08:00
世界 39514b3ca0 Add v2ray user stats api 2023-02-08 16:50:15 +08:00
世界 7ea9d48987 Add DHCP DNS server support 2023-02-08 16:43:29 +08:00
lyc8503andGitHub df3a982141 Add SSH outbound host key validation 2023-02-08 16:20:48 +08:00
世界andGitHub 687b4509df Add query_type DNS rule item 2023-02-08 16:18:40 +08:00
世界 41ec2e7944 Add support for clash DNS query API 2023-02-08 14:13:33 +08:00
世界 1bd3a9144d Upgrade tfo-go 2023-02-08 14:13:33 +08:00
世界 6e852cc99b Update dependencies 2023-02-08 14:13:15 +08:00
世界 8320dd0b51 Improve vmess request 2023-02-07 14:53:08 +08:00
世界 960d04d172 Fix match geoip 2023-02-07 12:21:00 +08:00
世界 86ea035bdd Fix ipv6 redir port 2023-02-05 14:48:02 +08:00
世界 9b6449dcf4 Fix find NDK on macOS 2023-02-02 16:30:50 +08:00
世界 4e22ac1a35 Update documentation 2023-02-02 16:11:29 +08:00
世界 8a779f6e94 Update dependencies 2023-02-02 15:38:48 +08:00
世界 d461768ffb Fix build with go1.20 2023-02-02 15:25:34 +08:00
Dmitry Rand世界 5d41e328d4 ignore domain case in route rules 2023-02-02 15:25:34 +08:00
世界 fe492904e9 Fix auth_user route for naive inbound 2023-01-19 10:47:22 +08:00
世界 168253b851 Fix inbound default DF 2023-01-19 10:36:25 +08:00
HellojackandGitHub 05620a369e Fix gRPC lite header
Manually set the first byte to 0x00 (No Compression) since we can not ensure that the buffer is not polluted before.
2023-01-16 16:23:06 +08:00
世界 8e0fe55363 Fix wireguard events 2023-01-15 19:48:50 +08:00
世界 59e521c1db Fix convert netaddr 2023-01-14 20:04:15 +08:00
世界 f32c149738 Bump version 2023-01-14 16:01:07 +08:00
世界 23a35b3c06 Fix create UDP DNS transport from plain IPv6 address 2023-01-13 11:51:20 +08:00
世界 044f9c5d4f Fix write to h2 conn after closed 2023-01-08 15:43:12 +08:00
世界 54f9625bdc Fix DNS log 2023-01-03 17:04:10 +08:00
世界 ff0693be32 Bump version 2023-01-03 10:53:38 +08:00
世界 53d9ad93e3 Improve DNS log 2023-01-03 10:36:18 +08:00
世界 f5c5570bec Skip set windows system proxy bypass list 2022-12-26 12:33:08 +08:00
世界 53f19a6ead Fix override packet conn 2022-12-21 21:58:03 +08:00
世界 cfaf15f429 Fix DNS response TTL 2022-12-19 13:10:57 +08:00
世界 9e67f3b4a5 Fix user from stream packet conn 2022-12-18 16:08:49 +08:00
isnowlyand世界 4d2185a2d4 Fix http proxy auth 2022-12-18 16:08:49 +08:00
世界 33f22263ca Update dependencies 2022-12-18 15:40:19 +08:00
世界 d09aa07d21 Fix android i686 compiler 2022-12-11 15:01:54 +08:00
世界 8afb8ca7eb Update documentation 2022-12-11 14:40:03 +08:00
世界 80ed5bf8fb Fix android package 2022-12-11 14:38:01 +08:00
世界 81e7b0b320 Fix linux package 2022-12-11 11:51:25 +08:00
世界 a828c3b5da Fix acme config 2022-12-06 13:36:42 +08:00
世界 c95e4a13a1 Fix vmess packet conn 2022-12-06 13:02:28 +08:00
世界 726a7e19eb Suppress quic-go set DF error 2022-12-06 12:51:52 +08:00
世界 8953ddc6e0 Update workflow 2022-12-03 17:03:04 +08:00
世界 7ebbd58b00 Update documentation 2022-12-03 14:38:52 +08:00
世界 d0095fd0f4 Fix close clash cache 2022-12-03 13:29:37 +08:00
世界 66d8d563eb Add WorkingDirectory for systemd service 2022-11-28 18:30:50 +08:00
世界 4bf96c7eb5 Fix quic stub 2022-11-28 16:06:54 +08:00
世界 f687c25fa9 Update documentation 2022-11-28 13:11:07 +08:00
世界 a92412ecac Fix router 2022-11-28 13:11:07 +08:00
世界 8dcafa5b33 Add trojan-go multiplex support for trojan inbound 2022-11-28 12:51:23 +08:00
世界 7a02cb83a7 Revert "Fix listen packet on address"
This reverts commit d1fe17a4db.
2022-11-28 12:51:23 +08:00
世界 51ce672076 Fix crash when input bad method in shadowsocks multi-user inbound 2022-11-28 12:51:23 +08:00
世界 7734afc40c Update dependencies 2022-11-28 12:51:23 +08:00
世界 ee3cd49aa5 Fix tls config for h2 server 2022-11-26 14:55:51 +08:00
世界 bf20ff84b5 Fix lint 2022-11-26 11:21:24 +08:00
世界 c58302554c Fix documentation 2022-11-26 11:06:57 +08:00
世界 05ed88aba8 Update documentation 2022-11-25 22:59:30 +08:00
世界 9f5cc0442b Fix dockerfile 2022-11-25 22:59:30 +08:00
世界 2641a43ad8 Remove test on pull request 2022-11-25 21:12:45 +08:00
世界 4a6ab5e9fd Fix cancel on start 2022-11-25 21:12:45 +08:00
世界 d1fe17a4db Fix listen packet on address 2022-11-25 21:12:45 +08:00
世界 7c910165ef Cleanup code 2022-11-24 12:37:29 +08:00
世界 8c1fddcf8d Remove connect packet conn 2022-11-24 12:01:25 +08:00
HellojackandGitHub 01b4769852 Cleanup gun conn code 2022-11-23 14:56:31 +08:00
世界 a401828ed5 Fix shadowtls server detection 2022-11-22 22:15:38 +08:00
世界 ffd54eef6c Update documentation 2022-11-21 21:20:44 +08:00
世界 c16e4316d6 Fix shadowtls server 2022-11-21 21:20:44 +08:00
世界 8b7fe20b7f Include uTLS in release 2022-11-21 15:25:49 +08:00
世界 696c1065b6 Update stable documentation 2022-11-21 14:57:22 +08:00
世界 5d690f4147 Update documentation 2022-11-21 13:18:04 +08:00
世界 f906641a82 Add uTLS to makefile default tags 2022-11-21 13:18:04 +08:00
世界 89913dfa8c Improve shadowtls server 2022-11-21 13:18:04 +08:00
世界 468778f67f Update dependencies 2022-11-21 13:18:04 +08:00
世界 22a22aebe2 Fix default dns transport strategy 2022-11-21 13:18:04 +08:00
世界 a2d2ec9b45 Update documentation 2022-11-15 17:36:42 +08:00
世界 2695b3516e Update issue template 2022-11-13 11:45:24 +08:00
世界 3a9ef8fac0 Remove unused 2022-11-13 11:30:48 +08:00
世界 ebad363201 Fix create TLS config 2022-11-13 11:24:37 +08:00
世界 11076d52cd Fix dns buffer & quic retry 2022-11-13 11:16:10 +08:00
世界 5eb132063e Fix connect packet connection for mux client 2022-11-12 03:53:42 +08:00
世界 13ab5d3348 Remove follow in update script 2022-11-11 22:32:24 +08:00
世界 ce1ddc400f Support x/h2 v0.2.0 deadline 2022-11-11 22:08:20 +08:00
arm64v8aand世界 2c9d25e853 Fix websocket alpn 2022-11-11 20:01:49 +08:00
世界 3d76777760 Fix tor geoip 2022-11-10 22:42:05 +08:00
世界 24f4dfea04 Fix hysteria test 2022-11-10 21:10:18 +08:00
世界 2fc1a0a9dd Update documentation 2022-11-10 16:33:10 +08:00
世界 617aba84e4 Add multi user support for hysteria inbound 2022-11-09 21:00:08 +08:00
世界 5510c474c7 Fix h2c transport 2022-11-09 12:15:14 +08:00
世界 eb2e8a0b40 Add custom tls client support for std grpc 2022-11-09 11:46:29 +08:00
世界 972491c19d Fix default local DNS server behavior 2022-11-09 10:35:16 +08:00
世界 7358ca4a52 Fix vmess request buffer 2022-11-09 10:16:22 +08:00
世界 61c274045a Update install go script 2022-11-08 23:19:53 +08:00
世界 f205140b04 Fix smux keep alive 2022-11-08 16:45:38 +08:00
世界 1db8e03c86 Fix format 2022-11-08 14:54:19 +08:00
世界 2ecf86c2bc Update patched quic-go 2022-11-08 13:54:01 +08:00
世界 999a847e86 Add custom wireguard worker size option 2022-11-08 13:48:14 +08:00
世界 1f63ce5dee Fix reset outbound 2022-11-06 10:36:19 +08:00
世界 0ad1bbea11 Fix wireguard close 2022-11-06 10:20:23 +08:00
世界 b2cd78d279 Move WFP manipulation to strict route 2022-11-06 10:16:07 +08:00
世界 d5bb58a0b4 Update documentation 2022-11-06 10:16:07 +08:00
世界 7f84936050 Split bind_address 2022-11-06 10:16:07 +08:00
Dreamacroand世界 6adfea0a72 Fix macOS Ventura process name match 2022-11-06 10:16:07 +08:00
Hellojackand世界 10f213bf3d Adjust uTLS wrapper 2022-11-06 10:16:07 +08:00
世界 6e8c4f6576 Update documentation 2022-10-31 13:59:52 +08:00
世界 9779dc0154 Fix test 2022-10-31 13:59:52 +08:00
世界 a2abe31298 Fix uTLS config 2022-10-31 13:59:52 +08:00
世界 930d177dd0 Update dependencies 2022-10-31 13:59:52 +08:00
Fei1Yangand世界 f3d1b59173 Update container action 2022-10-29 18:01:32 +08:00
世界 14452f3049 Update documentation 2022-10-29 18:00:05 +08:00
世界 4119c8647b Update dependencies 2022-10-29 17:56:21 +08:00
世界 90a94a8c63 Improve local dns transport 2022-10-29 17:37:11 +08:00
世界 b0c39ac7ff Suppress no network error 2022-10-28 09:54:04 +08:00
世界 8703e1ff98 Fix decrypt xplus packet 2022-10-28 09:53:57 +08:00
世界 35886b88d7 Add option for custom wireguard reserved bytes 2022-10-28 09:53:57 +08:00
永雏塔菲and世界 d583b35717 Add s390x architecture support
* Update debug.yml

Signed-off-by: 永雏塔菲 <108621198+taffychan@users.noreply.github.com>
2022-10-28 09:53:57 +08:00
Hellojackand世界 217ffb2f95 Update uTLS usage
* Update new uTLS fingerprints

* Update documentation
2022-10-28 09:53:57 +08:00
世界 22f06f582b Fix v2ray api 2022-10-26 20:06:13 +08:00
世界 f2b5098fa0 Update documentation 2022-10-25 21:26:28 +08:00
世界 0ca3290364 Add go1.18 debug build 2022-10-25 21:25:55 +08:00
世界 43d5b8598b Fix shadowtls conn 2022-10-25 21:25:42 +08:00
世界 f3e1d1defc Fix h3 dns transport 2022-10-20 11:04:03 +08:00
世界 95c03c9373 Fix copy pipe 2022-10-20 10:57:57 +08:00
世界 7e0958b4ac Update documentation 2022-10-19 10:55:06 +08:00
Skyximand世界 6a26737508 Check destination before udp connect 2022-10-19 10:22:46 +08:00
世界 92a92f39c5 Fix naive overflow 2022-10-18 17:52:52 +08:00
世界 fc533cd38d Fix DF for hysteria 2022-10-18 17:27:50 +08:00
世界 68e286499d Update dependencies 2022-10-18 17:27:50 +08:00
世界 f5c1900aad Add message for tfo error 2022-10-18 17:27:50 +08:00
世界 6591dd58ca Remove strict route on windows
replaced by custom route
2022-10-12 16:24:45 +08:00
XYenonandGitHub 54af113363 Add custom route support (#147) 2022-10-12 16:20:17 +08:00
世界 3f1fe814ef Fix sniff fragmented quic client hello 2022-10-12 16:11:42 +08:00
世界 5a2cebebd1 Remove unused 2022-10-10 14:23:34 +08:00
世界 b8009d61b2 Fix tfo headroom 2022-10-10 13:33:48 +08:00
世界 a61a64bf9e Add shadowtls inbound test 2022-10-10 11:31:03 +08:00
世界 7d17c52fea Add more messages to darwin route error 2022-10-09 21:22:07 +08:00
世界 f5b15b392b Fix ssh outbound 2022-10-09 20:43:01 +08:00
世界 8a53846efd Fix uTLS handshake 2022-10-08 20:31:01 +08:00
世界 badc454452 Fix test 2022-10-08 20:30:52 +08:00
世界 a01bb569d1 Fix websocket headroom 2022-10-08 20:09:36 +08:00
世界 89ff9f8368 Fix interface monitor 2022-10-08 20:09:36 +08:00
世界 7f816a2ebc Add sniff_timeout 2022-10-08 20:09:36 +08:00
世界 39c141651a Update documentation 2022-10-06 23:33:57 +08:00
世界 b0ad9bb6f1 Add shadowtls v2 support 2022-10-06 22:47:11 +08:00
世界 d135d0f287 Update tfo-go usage 2022-10-06 21:58:50 +08:00
世界 b183ccf23d Fix wfp filter weight 2022-10-05 20:24:27 +08:00
世界 c2969bc186 Update documentation 2022-10-03 04:36:54 +08:00
世界 bd86bfcd22 Fix check system stack packet 2022-10-03 04:36:54 +08:00
世界 8aec64b855 Add v2ray mux support for all connections 2022-10-03 04:34:59 +08:00
世界 1445bdba37 Fix trojan fallback 2022-10-01 11:41:15 +08:00
世界 29d08e63b5 Fix clash tracker 2022-10-01 11:29:46 +08:00
世界 1173fdea64 Improve tls writer 2022-10-01 11:29:46 +08:00
世界 968430c338 Minor fixes 2022-09-30 21:08:07 +08:00
世界 3e5bee6faf Fix windows route 2022-09-30 00:36:42 +08:00
世界 aa613cba73 Fix dns close 2022-09-29 09:12:13 +08:00
世界 1e510511ae Fix random seed 2022-09-29 08:49:34 +08:00
世界 1b44faed17 Add v2ray stats api 2022-09-29 08:49:34 +08:00
世界 c7a485815c Add binary to .gitignore 2022-09-26 19:36:51 +08:00
世界 7f9c870bba Add direct io option for clash api 2022-09-26 15:31:02 +08:00
世界 b5564ef3d3 Fix bind control 2022-09-26 13:50:54 +08:00
世界 8ce244dd04 Fix documentation
Signed-off-by: 世界 <i@sekai.icu>
Signed-off-by: unknowndevQwQ <unknowndevQwQ@pm.me>
2022-09-26 12:25:18 +08:00
世界 0f57b93925 Update documentation 2022-09-25 22:29:18 +08:00
世界 c90a77a185 Refine 4in6 processing 2022-09-25 22:29:18 +08:00
世界 c6586f19fa Fix read source address from grpc-go 2022-09-25 22:29:18 +08:00
世界 cbab86ae38 Refine tproxy write back 2022-09-25 22:29:18 +08:00
世界 17b5f031f1 Fix shadowsocks plugins 2022-09-25 16:43:12 +08:00
世界 b00b6b9e25 Fix fqdn socks5 outbound connection 2022-09-25 14:42:39 +08:00
世界 fb6b3b0401 Fix missing source address from transport connection 2022-09-23 18:55:28 +08:00
世界 22ea878fe9 Improve websocket writer 2022-09-23 18:55:07 +08:00
世界 abe3dc6039 Add self sign cert support 2022-09-23 17:13:18 +08:00
世界 852829b9dc Add VMess benchmark result 2022-09-23 16:13:29 +08:00
世界 407509c985 Fix leaks and add test 2022-09-23 13:14:31 +08:00
世界 9856b73cb5 Update documentation 2022-09-23 10:30:07 +08:00
世界 f42356fbcb Fix system stack ipv4 overflow 2022-09-23 10:29:15 +08:00
世界 d0b467671a Merge VLESS to library 2022-09-23 10:28:51 +08:00
世界 c18c545798 Add stdio test 2022-09-23 10:28:24 +08:00
世界 693ef293ac Update buffer usage 2022-09-23 10:27:48 +08:00
世界 a006627795 Disable DF on direct outbound by default 2022-09-23 10:27:46 +08:00
世界 0738b184e4 Fix url test interval 2022-09-23 10:27:42 +08:00
世界 42524ba04e Fix dns sniffer 2022-09-17 16:59:28 +08:00
世界 63fc95b96d Add mux server and XUDP client for VMess 2022-09-17 11:54:04 +08:00
世界 ab436fc137 Update documentation 2022-09-16 15:48:31 +08:00
世界 1546770bfd Skip bind on local addr 2022-09-16 15:35:29 +08:00
世界 f4b2099488 Fix tun log 2022-09-16 15:32:50 +08:00
世界 a2c4d68031 Fix create UDP transport 2022-09-15 16:46:53 +08:00
世界 cfe14f2817 Suppress bad http2 error 2022-09-15 15:34:52 +08:00
世界 a5402ffb69 Add back urltest outbound 2022-09-15 15:22:08 +08:00
世界 4d24cf5ec4 Update documentation 2022-09-15 13:25:51 +08:00
世界 668d354771 Make gVisor optional 2022-09-15 12:24:08 +08:00
世界 ad14719b14 Fix clash api proxy type 2022-09-14 23:02:11 +08:00
世界 d9aa0a67d6 Fix port rule match logic 2022-09-14 22:03:26 +08:00
世界 92bf784f4f Move shadowsocksr implementation to clash 2022-09-14 21:57:40 +08:00
世界 395b13103a Fix test 2022-09-14 18:02:51 +08:00
世界 628cf56d3c Fix close grpc conn 2022-09-14 18:02:37 +08:00
世界 ac5582537f Add back test workflow 2022-09-14 18:02:37 +08:00
世界 9aa7a20d96 Print tags in version command 2022-09-14 18:02:37 +08:00
世界 189f02c802 Refactor bind control 2022-09-14 18:02:37 +08:00
世界 2373281c41 Fix clash store-selected 2022-09-13 17:34:37 +08:00
世界 e8f4c2d36f Redirect clash hello to external ui 2022-09-13 17:29:57 +08:00
世界 07b6db23c1 Update install go script 2022-09-13 16:24:44 +08:00
世界 9a3360e5d0 Fix build on go1.18 2022-09-13 16:23:20 +08:00
世界 007a278ac8 Refactor to miekg/dns 2022-09-13 16:18:39 +08:00
世界 1db7f45370 Update documentation 2022-09-13 11:24:33 +08:00
世界 b271e19a23 Fix concurrent write 2022-09-13 10:41:10 +08:00
世界andarm64v8a 79b6bdfda1 Skip wait for hysteria tcp handshake response
Co-authored-by: arm64v8a <48624112+arm64v8a@users.noreply.github.com>
2022-09-13 10:40:26 +08:00
世界 38088f28b0 Add vless outbound and xudp 2022-09-12 21:59:27 +08:00
世界 dfb8b5f2fa Fix hysteria inbound 2022-09-12 18:35:36 +08:00
世界 9913e0e025 Add shadowsocksr outbound 2022-09-12 18:35:36 +08:00
世界 ce567ffdde Add obfs-local and v2ray-plugin support for shadowsocks outbound 2022-09-12 14:55:00 +08:00
世界 5a9913eca5 Fix socks4 client 2022-09-12 11:33:38 +08:00
世界 eaf1ace681 Update documentation 2022-09-11 22:48:42 +08:00
世界 a2d1f89922 Add custom tls client support for v2ray h2/grpclite transports 2022-09-11 22:44:35 +08:00
世界 7e09beb0c3 Minor fixes 2022-09-11 22:44:35 +08:00
世界 ebf5cbf1b9 Update documentation 2022-09-10 23:31:07 +08:00
世界 d727710d60 Run build on main branch 2022-09-10 22:54:53 +08:00
世界 0e31aeea00 Fix socks4 request 2022-09-10 22:54:50 +08:00
世界 2f437a0382 Add uTLS client 2022-09-10 22:10:45 +08:00
世界 3ad4370fa5 Add ECH TLS client 2022-09-10 22:10:45 +08:00
世界 a3bb9c2877 Import cloudflare tls 2022-09-10 22:10:45 +08:00
世界 ee7e976084 Refactor TLS 2022-09-10 22:10:45 +08:00
世界 099358d3e5 Add clash persistence support 2022-09-10 14:42:14 +08:00
世界 5297273937 Add clash mode support 2022-09-10 14:15:11 +08:00
世界 80cfc9a25b Fix processing empty dns result 2022-09-10 14:15:11 +08:00
世界 2ae4da524e Fix tun documentation 2022-09-10 10:21:42 +08:00
世界 bbe7f28545 Fix system stack crash 2022-09-09 19:44:13 +08:00
世界 78ddd497ee Fix no_gvisor build 2022-09-09 19:44:13 +08:00
世界 8d044232af Update documentation 2022-09-09 15:42:33 +08:00
世界 aa7e85caa7 Update dependencies
Add half close for smux
Update gVisor to 20220905.0
2022-09-09 14:44:18 +08:00
zakuwakiand世界 46a8f24400 Optional proxyproto header 2022-09-09 14:44:18 +08:00
世界 87bc292296 Add comment filter for config 2022-09-09 14:44:18 +08:00
世界 ac539ace70 Add system tun stack 2022-09-09 14:44:18 +08:00
世界 a15b13978f Set default tun mtu to 9000 like clash
IDK why, maybe faster in a local speed test?
2022-09-09 14:44:18 +08:00
世界 0c975db0a6 Set udp dontfrag by default 2022-09-09 14:44:18 +08:00
世界 cb4fea0240 Refactor wireguard & add tun support 2022-09-09 14:44:18 +08:00
世界 8e7957d440 Add support for use with android VPNService 2022-09-09 14:44:18 +08:00
世界 f7bed32c6f Bump version 2022-09-09 14:43:42 +08:00
世界 ef7f2d82c0 Fix match 4in6 address in ip_cidr 2022-09-09 14:07:02 +08:00
世界 7aa97a332e Fix documentation 2022-09-09 13:54:02 +08:00
世界 7c30dde96b Minor fixes 2022-09-08 18:33:59 +08:00
GyDiandGitHub 9cef2a0a8f Fix clashapi log level format error 2022-09-08 18:04:06 +08:00
世界 f376683fc3 Update documentation 2022-09-07 23:10:36 +08:00
世界 4b61d6e875 Fix hysteria stream error 2022-09-07 19:16:20 +08:00
世界 7d83e350fd Refine test 2022-09-07 19:16:20 +08:00
世界 500ba69548 Fix processing vmess termination signal 2022-09-07 19:16:20 +08:00
世界 9a422549b1 Fix json format error message 2022-09-07 13:23:26 +08:00
世界 3b48fa455e Fix naive inbound temporary 2022-09-07 12:30:54 +08:00
zakuwakiand世界 ef013e0639 Suppress accept proxyproto failed #65 2022-09-06 23:16:31 +08:00
世界 8f8437a88d Fix wireguard reconnect 2022-09-06 00:11:43 +08:00
世界 1b091c9b07 Update documentation 2022-09-04 13:15:10 +08:00
世界 4801b6f057 Fix DNS routing 2022-09-04 12:49:38 +08:00
世界 9078bc2de5 Fix write trojan udp 2022-09-03 16:58:55 +08:00
世界 b69464dfe9 Update documentation for dial fields 2022-09-03 13:02:41 +08:00
世界 62fa48293a Merge dialer options 2022-09-03 12:55:10 +08:00
世界 b206d0889b Fix dial parallel in direct outbound 2022-09-03 12:01:48 +08:00
世界 ee691d81bf Fix write zero 2022-09-03 09:25:30 +08:00
void aire()and世界 56876a67cc Fix documentation typo (#60) 2022-09-02 19:04:03 +08:00
世界 4a0df713aa Add ws compatibility test 2022-09-01 20:32:47 +08:00
世界 ef801cbfbe Fix server install script 2022-09-01 20:32:47 +08:00
世界 9378fc88d2 Add with_wireguard to default server tag 2022-09-01 20:16:20 +08:00
世界 f46bfcc3d8 Move unstable branch to dev-next 2022-08-31 23:45:42 +08:00
0x7d274284andGitHub ccdb238843 Fix documentation typo (#57) 2022-08-31 23:42:36 +08:00
世界 f1f61b4e2b Fix install documentation 2022-08-31 23:37:30 +08:00
世界 a44cb745d9 Fix write log timestamp 2022-08-31 23:35:43 +08:00
世界 f5f5cb023c Update documentation 2022-08-31 14:34:32 +08:00
世界andGitHub 5813e0ce7a Add shadowtls (#49)
* Add shadowtls outbound

* Add shadowtls inbound

* Add shadowtls example

* Add shadowtls documentation
2022-08-31 14:21:53 +08:00
dyhkwongandGitHub 5a9c2b1e80 darwin pf support (#52) 2022-08-31 14:21:37 +08:00
世界 bda34fdb3b Refactor outbound documentation 2022-08-31 13:42:30 +08:00
世界 426b677eb8 Fix process_name rule item 2022-08-31 12:51:38 +08:00
世界 67c7e9fd86 Refactor inbound documetation 2022-08-31 12:50:26 +08:00
世界 d8028a8632 Fix smux session status 2022-08-31 10:00:15 +08:00
dyhkwongandGitHub 374743d022 Add process_path rule item (#51)
* process matching supports full path
* Remove strings.ToLower
2022-08-30 10:44:40 +08:00
世界 cd98ea5008 Fix socksaddr type condition 2022-08-29 19:58:58 +08:00
世界 dbda0ed98a Add chained inbound support 2022-08-29 19:50:28 +08:00
世界 f5e0ead01c Fix inject conn 2022-08-29 19:02:41 +08:00
0x7d274284andGitHub 44818701bc Fix issue template (#48)
The correct command to get the version is `sing-box version`
2022-08-29 16:52:15 +08:00
世界 e0f7387dff Fix search android package in non-owner users 2022-08-29 12:02:29 +08:00
世界 d440a01792 Add grpc compatibility test 2022-08-29 10:15:25 +08:00
世界 665c84ee42 Fix log item on document menu 2022-08-28 12:47:23 +08:00
HellojackandGitHub e0de96eb4c Minor fixes (#45)
* Cleanup code
* Fix documentation typo
2022-08-28 12:40:44 +08:00
世界 c6ef276811 Update dependencies 2022-08-28 12:21:22 +08:00
世界 1701aaf78c Add docker image 2022-08-28 00:23:41 +08:00
世界 122daa4bfb Simplify server installation 2022-08-28 00:23:41 +08:00
世界 561a9e5275 Update documentation 2022-08-28 00:23:41 +08:00
HellojackandGitHub de2453fce9 Add gun-lite gRPC implementation (#44) 2022-08-27 21:05:15 +08:00
世界 d59d40c118 Fix sniff override destination 2022-08-27 14:37:14 +08:00
rand0mgh0standGitHub 3469df001f Fix documentation for socks inbound (#42) 2022-08-27 13:16:04 +08:00
世界 0d8cfa3031 Add vmess packetaddr option 2022-08-27 11:28:01 +08:00
世界 0289586880 Add documentation for strict_route 2022-08-27 09:31:17 +08:00
rand0mgh0standGitHub e46427c7fc docs-zh-CN: use English for License section (#40) 2022-08-26 23:21:32 +08:00
世界 3ea59d9a8e Move documentation branch to main 2022-08-26 21:53:46 +08:00
世界 e85dfc6adf Add strict_route option 2022-08-26 21:53:08 +08:00
世界 d0703b78fa Fix dns hijack on android
iproute2 on android does not support port rules
2022-08-26 21:05:45 +08:00
世界 432e6adf3e Fix TLS documentation 2022-08-26 18:36:56 +08:00
世界 a057754035 Revert linux process searcher 2022-08-26 17:36:06 +08:00
世界 0348ace253 Initial release 2022-08-26 16:40:37 +08:00
世界 c5e38203eb Fix read DNS message 2022-08-26 13:35:27 +08:00
世界 9ac31d0233 Fix ipv6 route on linux 2022-08-26 12:30:31 +08:00
世界 9d8d1cd69d Update documentation 2022-08-26 11:10:02 +08:00
世界 07a0381f8b Cleanup vmessws 2022-08-26 10:22:29 +08:00
世界 f841459004 Cleanup vmesshttp 2022-08-26 08:41:45 +08:00
世界 78a26fc139 Update documentation 2022-08-25 22:49:23 +08:00
世界 9f6628445e Improve ip_cidr rule 2022-08-25 22:23:26 +08:00
世界 fa017b5977 Add contributing documentation 2022-08-25 21:08:29 +08:00
世界 58f4a970f2 Fix route connections 2022-08-25 20:48:59 +08:00
世界 021aa8faed Fix ipv6 route on linux 2022-08-25 18:57:36 +08:00
世界 83f6e037d6 Fix http proxy with compressed response 2022-08-25 18:40:13 +08:00
世界 baf153434d Fix issue template 2022-08-25 18:40:13 +08:00
世界 d481bd7993 Fix bind_address 2022-08-25 14:50:10 +08:00
Steven TangandGitHub e859c0a6ef Fix typo in features.md (#32) 2022-08-25 13:42:22 +08:00
zakuwakiand世界 59a39e66b1 Add trojan fallback for ALPN #31 2022-08-25 13:37:32 +08:00
世界 fd5ac69a35 Let vmess use zero instead of auto if TLS enabled 2022-08-25 11:51:17 +08:00
世界 a940703ae1 Suppress expected error 2022-08-25 11:02:27 +08:00
世界 350729cde8 Remove TLS requirement on gRPC server 2022-08-25 10:52:16 +08:00
世界 2e14cd6d66 Close websocket conn gracefully 2022-08-25 10:46:14 +08:00
世界 f703524f04 Add stale workflow 2022-08-25 10:24:11 +08:00
世界 aa4435c775 Update documentation 2022-08-25 10:04:51 +08:00
ReeceandGitHub 31a2e368cc Fix zh-CN document symbol and format (#29) 2022-08-25 09:45:22 +08:00
世界 97e284e65e Initial zh-CN document translation: outbound 2022-08-24 21:02:28 +08:00
世界 a6baab92f3 Fix early close on windows and catch any 2022-08-24 19:03:15 +08:00
世界 7c76e0c3ee Initial zh-CN document translation: inbound 2022-08-24 18:43:39 +08:00
世界 591a4fcf8e Initial zh-CN document translation: shared 2022-08-24 17:39:37 +08:00
世界 71dac85600 Add ACME EAB support 2022-08-24 17:06:28 +08:00
世界 ad90ddd327 Initial zh-CN document translation: route 2022-08-24 16:56:29 +08:00
世界 03f457f3d0 Initial zh-CN document translation: DNS 2022-08-24 16:37:06 +08:00
HellojackandGitHub a878256367 Fix TLS insecure (#27) 2022-08-24 16:11:41 +08:00
世界 553f78ed55 Fix close non-duplex connections 2022-08-24 14:32:18 +08:00
世界 1bc7d2237e Initial zh-CN document translation: examples 2022-08-24 13:14:12 +08:00
世界 132222013b Initial zh-CN document translation: FAQ 2022-08-24 13:04:47 +08:00
世界 2008fb552a Initial zh-CN document translation 2022-08-24 12:45:51 +08:00
世界 236c034c62 Fix unix search path 2022-08-24 12:27:36 +08:00
世界 f87baf08d3 Fix naive padding 2022-08-24 10:21:56 +08:00
世界 22aa0c2f40 Update documentation 2022-08-24 00:39:25 +08:00
世界 88469d4aaa Check configuration before reload 2022-08-23 23:44:44 +08:00
世界 1413c5022a Add proxy protocol support 2022-08-23 21:07:35 +08:00
世界 aa8cdaee22 Handle SIGHUP signal 2022-08-23 19:56:28 +08:00
世界 9f6ff54a76 Parse X-Forward-For in HTTP requests 2022-08-23 19:53:04 +08:00
世界 e750c747c6 Fix test naive inbound with nginx 2022-08-23 14:41:31 +08:00
世界 9edfe7d9d3 Accept HTTP1 in naive inbound 2022-08-23 13:25:03 +08:00
世界 c9b7acd22c Add v2ray transport to trojan 2022-08-23 13:24:52 +08:00
世界 2ba2f0298c Free memory after start 2022-08-22 23:17:08 +08:00
世界 a24a2b475a Allow http1 in v2ray HTTP transport 2022-08-22 23:02:25 +08:00
世界 4005452772 Add v2ray HTTP transport 2022-08-22 22:20:19 +08:00
世界 d4b7e221f0 Add v2ray QUIC transport 2022-08-22 22:20:19 +08:00
世界 77c98fd042 Add v2ray WebSocket transport 2022-08-22 22:20:18 +08:00
世界 082872b2f3 Prepare v2ray client/server transport 2022-08-22 18:57:05 +08:00
世界 6253e2e24c Fix clash server early close 2022-08-22 16:33:33 +08:00
世界 4216afe62f Minor fixes 2022-08-22 16:14:53 +08:00
世界 8fec78a5cd Apply bind address to udp connect 2022-08-22 14:35:05 +08:00
世界 7ba0a14e97 Add bind address to outbound options 2022-08-22 14:28:23 +08:00
世界 3a442347a5 Update documentation 2022-08-22 14:19:32 +08:00
世界 c4f4fd97d6 Fix tests 2022-08-22 12:02:16 +08:00
世界 ac0ead1473 Add strategy setting for each dns server 2022-08-22 12:01:50 +08:00
世界 83cea9475d Fix vectorised writer 2022-08-21 22:35:58 +08:00
世界 dc6bb7ab1b Add ssh outbound 2022-08-21 22:30:48 +08:00
世界 c71f6ba377 Add FAQ page 2022-08-21 22:26:08 +08:00
世界 b1b1ab5350 Update release config 2022-08-21 13:03:19 +08:00
世界 7613b8dbfe Fix gvisor udp write back 2022-08-21 11:40:04 +08:00
世界 e4cece6095 Add tor outbound 2022-08-21 01:06:34 +08:00
世界 bcefe8716f Fix typo in documentation 2022-08-20 21:16:14 +08:00
世界 746b5d8be0 Add trojan connection fallback 2022-08-20 21:08:53 +08:00
世界 f13ecbd9bb Wait a second before check route update 2022-08-20 13:42:28 +08:00
世界 e839beb73b Skip bind connection with private destination to interface 2022-08-20 13:31:15 +08:00
世界 b797cdf91e Fix write socks5 username password auth request 2022-08-20 13:26:49 +08:00
世界 84e4677a94 Improve process searcher 2022-08-20 12:11:27 +08:00
世界 0377a11719 Fix route on android 2022-08-20 10:27:13 +08:00
世界 d0fa79044a Start outbounds before router 2022-08-20 09:13:00 +08:00
世界 f381f8d35a Fix read packages in android 13 2022-08-20 03:05:50 +08:00
世界 92e1e5b893 Attempt to unwrap ip-in-fqdn socksaddr 2022-08-20 00:01:08 +08:00
世界 8e8b4dba22 Update documentation 2022-08-19 22:30:12 +08:00
世界 767cd55817 Fix acme issuer 2022-08-19 18:42:12 +08:00
世界 eb0ef439d6 Add with_acme to server scripts 2022-08-19 17:48:56 +08:00
世界 0bf78c0a8a Update gVisor to 20220815.0 2022-08-19 17:47:54 +08:00
世界 12d7e19f32 Allow read config from stdin 2022-08-19 15:43:13 +08:00
世界andGitHub d1c3dd0ee1 Add hysteria and acme TLS certificate issuer (#18)
* Add hysteria client/server
* Add acme TLS certificate issuer
2022-08-19 15:42:57 +08:00
世界 3dfa99efe1 Add back dns concurrent write lock 2022-08-19 10:51:26 +08:00
世界 d7bd221a47 Fix darwin tun 2022-08-19 08:35:08 +08:00
世界 1b7a3b4a74 Fix log to file 2022-08-19 08:26:26 +08:00
世界 c8424ed8fd Fix format 2022-08-19 08:26:26 +08:00
世界 150df1ae8e Add write lock to shadowsocks aead writer 2022-08-19 08:26:26 +08:00
世界 5ca9d77176 Fix close shadowsocks server conn 2022-08-18 23:16:05 +08:00
世界 aa89fcc29d Fix find process with lwip stack 2022-08-18 10:10:30 +08:00
Tianling ShenandGitHub 7ead0de26b Fix geosite path (#17)
`geoIPOptions` -> `geositeOptions`

Signed-off-by: Tianling Shen <i@cnsztl.eu.org>
2022-08-18 10:00:56 +08:00
世界 f22c2690ec Fix lint 2022-08-17 20:15:35 +08:00
世界 738bb0eabc Improve async dns transports 2022-08-17 20:10:59 +08:00
世界 002a519a17 Update documentation 2022-08-17 15:19:10 +08:00
世界 f51128f772 Add ip_version rule item 2022-08-16 23:47:14 +08:00
世界 d6a0aa7ccf Add wireguard outbound and test 2022-08-16 23:39:11 +08:00
世界 ca94a2ddcb Improve tproxy udp write back 2022-08-16 18:37:37 +08:00
世界 835ae1217b Update exec/control usage 2022-08-16 18:19:48 +08:00
世界 c165969399 Fix include_android_user option 2022-08-16 12:16:59 +08:00
世界 88c69a06dc Fix copy stream 2022-08-15 16:53:12 +08:00
世界 cd5e7055d2 Add android package rules support in tun routing 2022-08-15 11:44:59 +08:00
世界 3157593b6b Add uid and android user rules support in tun routing 2022-08-15 11:41:00 +08:00
世界 c8399a297e Improve cmd 2022-08-13 18:37:51 +08:00
HellojackandGitHub 529cfe2d9a Fix documentation typo (#13) 2022-08-13 11:01:22 +08:00
世界 50869c6cd2 Fix dns concurrent write 2022-08-13 11:00:15 +08:00
世界 44fcfab9aa Improve build 2022-08-12 22:58:28 +08:00
世界 340fce9f1c Add UoT option to socks outbound too 2022-08-12 17:55:52 +08:00
世界 51bbf93ff2 Improve smux write 2022-08-12 16:49:25 +08:00
HellojackandGitHub f8d13d79c7 Add CGO hint in version cmd (#12) 2022-08-12 15:46:26 +08:00
世界 b0ed1dc106 Minor fixes 2022-08-12 12:13:57 +08:00
世界 ef8dde2b70 Update dependencies 2022-08-12 10:58:16 +08:00
世界 97870c9288 Refactor bufio 2022-08-11 23:59:22 +08:00
世界 c9226aeaaf Show memory stats in debug 2022-08-11 12:42:17 +08:00
世界 7b30815938 Enable QUIC in server scripts 2022-08-11 11:45:33 +08:00
世界 517a89fa9c Add back UoT support 2022-08-11 10:36:28 +08:00
ReeceandGitHub cf80073f27 Fix documentation typo (#10) 2022-08-11 10:06:10 +08:00
世界 43353ca5a4 Update documentation 2022-08-10 21:21:02 +08:00
世界 b79b19c470 Add naive inbound and test 2022-08-10 20:36:29 +08:00
iKirbyandGitHub ccdfab378a Fix default dns server option (#9) 2022-08-10 12:18:03 +08:00
世界 0e6b4df8f1 Remove incorrect warning 2022-08-09 17:27:22 +08:00
世界 79a4b18ec7 Update dependencies 2022-08-09 15:55:16 +08:00
世界 e05ee55545 Improve cmd 2022-08-09 14:49:17 +08:00
世界 ecaddd897e Fix direct connect 2022-08-09 14:48:08 +08:00
世界 8ca6c246a8 Improve wintun read 2022-08-08 21:35:59 +08:00
世界 55d9a0ef2f Update documentation 2022-08-08 21:10:37 +08:00
世界 4067e0f25c Fix copy early conn 2022-08-08 20:56:53 +08:00
世界 6d78cf6b58 Add trojan inbound/outbound 2022-08-08 09:08:12 +08:00
世界 df6635c620 Simplify vmess test 2022-08-08 09:08:12 +08:00
世界 2c6d239525 Fix mux overflow 2022-08-08 08:09:17 +08:00
世界 0f74f6cd60 Add optional LWIP tun stack support 2022-08-07 17:21:49 +08:00
世界 6ee10c03d1 Update gVisor to 20220801.0 2022-08-07 14:58:07 +08:00
世界 587739e95c Fix linux unprivileged tun usage 2022-08-07 11:21:10 +08:00
世界 01bace7769 Fix wininet wrapper 2022-08-06 17:28:51 +08:00
世界 dfa10d4ebe Add tun support for macOS 2022-08-05 17:02:51 +08:00
世界 f691bd5ce1 Add set system proxy support for macOS 2022-08-05 16:55:59 +08:00
世界 64dbac8138 Add multiplexer for vmess 2022-08-04 10:38:20 +08:00
世界 1c3c154d6d Improve multiplex log 2022-08-04 09:12:57 +08:00
世界 32201cacda Add unsafe tag to multiplexer writer 2022-08-04 00:00:22 +08:00
世界 5f566b140f Add documentation for simple linux installation 2022-08-03 22:23:40 +08:00
世界 03890151d7 Improve multiplexer 2022-08-03 22:01:18 +08:00
世界 8e4de29409 Improve dns log 2022-08-03 20:17:05 +08:00
世界 f6f3390490 Update WriteToUDPAddrPort usage since fixed by go1.18.5 2022-08-03 17:49:04 +08:00
世界 d4cce1b5b9 Update task usage 2022-08-03 17:44:19 +08:00
世界 44068500bf Replace netlink with fork 2022-08-03 12:02:22 +08:00
世界 8ce263669e Fix windows tun leak memory 2022-08-03 10:14:00 +08:00
世界 6b4824ffba Minor fixes 2022-08-02 18:47:23 +08:00
世界 9a8918cb9e Improve mux server 2022-08-02 15:11:51 +08:00
世界 b1c2440371 Fix buffer usage 2022-08-02 13:43:25 +08:00
世界 37b11e614c Fix dns sniff 2022-08-02 13:42:31 +08:00
世界 14b6200fd8 Add documentation for vmess 2022-08-01 17:02:13 +08:00
世界 7966b80476 Add vmess legacy server and test 2022-08-01 12:23:34 +08:00
世界 b526ab2746 Fix netlink subscription leak 2022-07-31 19:58:32 +08:00
世界 0e0a892b7e Make socks request buffered 2022-07-31 19:58:32 +08:00
世界 fe3649cd27 Close tun endpoint faster 2022-07-31 19:58:32 +08:00
世界 e014220508 Add retry for mux stream open 2022-07-31 18:08:24 +08:00
世界 d06fd03dd8 Fix tcp keep alive 2022-07-31 09:53:29 +08:00
世界 0eed0ca11a Fix dns outbound 2022-07-31 08:48:56 +08:00
世界 c57ea9e47c Add omitempty for listen_port 2022-07-30 22:05:06 +08:00
世界 70b4577dbe Add TLS certificate reload 2022-07-30 22:04:01 +08:00
世界 5f1f55fbe7 Add documentation for shadowsocks multiplexer 2022-07-30 21:23:45 +08:00
世界 2d3d46eb34 Fix copy with src buffer to headroom writer 2022-07-30 21:23:45 +08:00
世界 2ce09b6ffd Minor fixes 2022-07-30 14:50:33 +08:00
世界 d3378a575c Improve error processing 2022-07-30 09:57:02 +08:00
世界 9b9b5ebb72 Add linux server scripts 2022-07-30 09:04:01 +08:00
世界 0f7f800e95 Use connect for quic/dns udp connections 2022-07-30 09:04:01 +08:00
世界 457de86819 Add multiplexer 2022-07-30 09:04:01 +08:00
世界 83154eadd3 Hide dns outbound in clash-dashboard 2022-07-28 16:40:06 +08:00
世界 c0a2f77258 Remove urltest outbound 2022-07-28 16:36:31 +08:00
世界 c240f1b359 Add shadowsocks-multiuser control api 2022-07-27 21:59:40 +08:00
世界 aa074a2063 Update documentation 2022-07-27 12:13:31 +08:00
世界 f008d0bde3 Add endpoint independent nat support for tun inbound 2022-07-27 11:59:36 +08:00
世界 0347a7c038 Remove go-json 2022-07-26 13:53:25 +08:00
世界 75508bccb5 Add optional DoT, DoH3 support 2022-07-26 12:48:10 +08:00
世界 593799a988 Fix clash tracker timeout 2022-07-26 06:56:24 +08:00
世界 816d7b734c Improve udp timeout 2022-07-25 22:15:16 +08:00
世界 5491895a60 Print stack if no context 2022-07-25 16:18:22 +08:00
世界 9394674b63 Fix format command 2022-07-25 16:18:11 +08:00
世界 146008a631 Fix direct udp outbound 2022-07-25 16:18:11 +08:00
世界 cc78f0347d Improve config struct 2022-07-25 16:18:11 +08:00
世界 1f05420745 Improve tls dialer and listener 2022-07-25 16:18:11 +08:00
世界 32e2730ec6 Add runtime warnings 2022-07-25 07:19:15 +08:00
世界 29c329dc52 Add retry for linux process search 2022-07-24 21:43:05 +08:00
世界 7d8a7c5c7d Add default tcp keep alive settings 2022-07-24 21:29:39 +08:00
世界 9e9e6f7ee6 Improve udp dns close 2022-07-24 21:25:41 +08:00
世界 fde33fbb30 Add lint workflow 2022-07-24 21:22:19 +08:00
世界 67edc163cb Add with_std_json build tag 2022-07-24 21:22:19 +08:00
世界 fe8e984608 Add route.default_mark option 2022-07-24 17:46:25 +08:00
世界 7d340e7ef9 Add source_port_range/port_range rule item 2022-07-24 16:21:35 +08:00
世界 af19ba6119 Add disable_cache option to dns rule 2022-07-24 16:21:31 +08:00
世界 8666631732 Add rcode dns transport 2022-07-24 16:21:31 +08:00
世界 ce4b7231e2 Add invert rule item 2022-07-24 16:21:31 +08:00
世界 21641be9d1 Fix direct inbound 2022-07-24 13:42:58 +08:00
世界 5f6f33c464 Add process_name/package_name/user/user_id rule item 2022-07-23 21:28:13 +08:00
世界 4abf669d09 Fix urltest log 2022-07-23 10:28:32 +08:00
世界 187de6c738 Update documentations 2022-07-23 09:29:37 +08:00
世界 884c0cf595 Deprecate dns_hijack and dns inbound 2022-07-23 09:15:47 +08:00
世界 9f8978bbcf Improve 4in6 processing 2022-07-22 17:57:23 +08:00
世界 bcdf71deb3 Fix tproxy inbound 2022-07-22 16:18:56 +08:00
世界 7bc7b72c61 Fix log format 2022-07-22 14:28:29 +08:00
世界 e531e89b4b Fix dns inbound 2022-07-22 14:25:04 +08:00
世界 e5e24ef51d Add documentation for selector/urltest outbound 2022-07-22 14:07:27 +08:00
世界 c4e46c35b5 Add urltest outbound 2022-07-22 13:51:08 +08:00
世界 139127f1e4 Expand env in clash external-ui 2022-07-22 09:49:35 +08:00
世界 3838d3070d Fix integration with clash-dashboard 2022-07-22 09:41:12 +08:00
世界 8004ff51f0 Add selector outbound 2022-07-21 21:13:16 +08:00
世界 385c42e638 Improve socksaddr 2022-07-20 22:05:11 +08:00
世界 6327c4b40c Minor fixes 2022-07-20 13:46:47 +08:00
世界 45643fbed1 Add documentation for clash_api 2022-07-20 07:37:50 +08:00
世界 6ac1b395cf Make clash api and gVisor optional 2022-07-20 07:12:40 +08:00
世界 c5b3e8b042 Add basic clash api 2022-07-19 22:45:55 +08:00
世界 c7fabe40ed Improve connection timeout 2022-07-18 20:53:13 +08:00
世界 3fb011712b Add vmess compatibility test 2022-07-18 20:14:53 +08:00
世界 6b1a68908d Add vmess inbound/outbound 2022-07-18 12:32:31 +08:00
世界 d1e83882e5 Add user rule item 2022-07-17 17:38:11 +08:00
世界 cf845d946e Exclude gVisor for unsupported arch 2022-07-17 11:16:13 +08:00
世界 4094c94971 Disable gVisor log 2022-07-17 11:15:56 +08:00
世界 ae36e35de7 Improve workflow build 2022-07-17 09:54:34 +08:00
世界 a4b5c61e25 Update dependencies 2022-07-17 09:18:36 +08:00
世界 9caa37c12a Add debug build for all arch 2022-07-17 09:11:23 +08:00
世界 9871ed955b Fix build 2022-07-17 08:48:57 +08:00
世界 afc2f509a4 Minor fixes 2022-07-16 22:03:35 +08:00
世界 fe5618c35d Add stun sniffer 2022-07-16 12:01:02 +08:00
世界 8619e07d66 Fix private addr check 2022-07-16 10:19:18 +08:00
世界 eb35d6793e Fix linux tun 2022-07-15 22:40:42 +08:00
世界 a25db09aac Fix set_system_proxy when using sudo 2022-07-15 18:30:01 +08:00
世界 8969a15858 Fix tun auto_route on android 2022-07-15 18:29:29 +08:00
世界 377f3f83a2 Add route.default_interface option 2022-07-15 15:00:54 +08:00
世界 5a3de62c50 Add ss aead tests 2022-07-15 11:18:19 +08:00
世界 2c2eb31e18 Add redir tproxy and dns inbound 2022-07-15 08:42:02 +08:00
世界 e13b72afca Improve bind interface 2022-07-14 23:11:53 +08:00
世界 b9086b31e6 Add set_system_proxy for linux and android 2022-07-14 20:32:17 +08:00
世界 de2db7c2d2 Add documentation for set_system_proxy 2022-07-14 14:41:35 +08:00
世界 238afda9da Add set_system_proxy option for windows 2022-07-14 14:41:35 +08:00
世界 e7d557fd9e Add tun inbound for windows 2022-07-13 22:41:21 +08:00
世界 4fc763cfa2 Refactor log 2022-07-12 17:44:12 +08:00
世界 b47f3adbb3 Improve copy early conn 2022-07-11 20:55:14 +08:00
世界 862e3c430c Fix tcp sniffing 2022-07-11 20:37:57 +08:00
世界 dc127e2994 Migrate components to library 2022-07-11 18:44:59 +08:00
世界 3c1190e2c3 Make dns.strategy take effect in dns exchange 2022-07-11 13:21:17 +08:00
世界 a104d18277 Fix hijack_dns 2022-07-11 12:56:57 +08:00
世界 6048b1e270 Remove ToString0[T] usage to fix golangci-lint 2022-07-10 22:00:28 +08:00
世界 0ef2e330e3 Fix create gVisor endpoint 2022-07-10 19:17:44 +08:00
世界 b417bd5be4 Add documentation and example for linux tun 2022-07-10 16:44:12 +08:00
世界 7f84191748 Minor fixes 2022-07-10 16:19:42 +08:00
世界 29f78248dc Add hijack_dns for tun 2022-07-10 10:14:45 +08:00
世界 638f8a52d1 Add auto_route and auto_detect_interface for linux 2022-07-10 08:18:52 +08:00
世界 4432cc2253 Fix quic sniff irl 2022-07-10 07:52:33 +08:00
世界 730144cc26 Add tun inbound for linux 2022-07-09 22:44:18 +08:00
世界 c463d0cf80 Fix pages 2022-07-09 15:09:50 +08:00
世界 8eecae92b2 Add benchmark page 2022-07-09 15:00:31 +08:00
世界 6832451561 Fix direct udp 2022-07-09 10:28:22 +08:00
世界 41925b6606 Add bug template 2022-07-09 09:34:16 +08:00
世界 211d97ff8a Declare required fields in the documentation 2022-07-09 09:28:54 +08:00
世界 8fa953a516 Add debug workflow 2022-07-09 09:02:06 +08:00
世界 7f8c9ffa30 Add shadowsocks tests 2022-07-09 08:59:34 +08:00
世界 f448b6b977 Update gci format 2022-07-08 23:03:57 +08:00
世界 e0cfc33fe2 Fix handle missing err on quic sniff 2022-07-08 22:49:17 +08:00
世界 76236a0b75 Add examples 2022-07-08 22:45:06 +08:00
世界 0cb9d79044 Add route documentation 2022-07-08 20:20:38 +08:00
世界 eeaee94e5e Add outbound documentation 2022-07-08 19:58:56 +08:00
世界 ddbdac7d97 Add inbound documentation 2022-07-08 18:42:29 +08:00
世界 b44a1cd823 Add README 2022-07-08 18:41:18 +08:00
世界 d6d02b9924 Add log and dns documentation 2022-07-08 18:41:18 +08:00
世界 3699a57847 Add dial parallel for outbound dialer 2022-07-08 13:08:29 +08:00
世界 d45007b501 Improve load geosite 2022-07-08 11:00:46 +08:00
世界 9c256afc1a Add resolver for inbound 2022-07-07 23:45:05 +08:00
世界 538a1f5909 Add resolver for outbound dialer 2022-07-07 21:47:21 +08:00
世界 ecac383477 Add disableCache/disableExpire option for dns client 2022-07-06 23:43:20 +08:00
世界 8a761d7e3b Add dns client 2022-07-06 23:14:19 +08:00
世界 651c4b539a Add dns transports 2022-07-06 19:01:46 +08:00
世界 81330d32e0 Remove lint action 2022-07-06 15:45:13 +08:00
世界 3696e81eb4 Update gci format 2022-07-06 15:01:09 +08:00
世界 46f28a9de9 Add protect path dialer option 2022-07-06 14:45:56 +08:00
世界 dcd7ca78fc Rename find path 2022-07-06 14:44:51 +08:00
世界 86a38a1c7e Add domain sniffer 2022-07-06 12:39:44 +08:00
世界 2d9203ee74 Refactor geo resources 2022-07-05 13:23:47 +08:00
世界 8392567962 Add geosite 2022-07-05 09:05:35 +08:00
世界 f76102dab5 Add geosite protocol 2022-07-04 19:39:58 +08:00
世界 43cf0441db Fix route 2022-07-04 19:34:45 +08:00
世界 792dc83778 Add version command 2022-07-04 17:14:15 +08:00
世界 718b4afbf3 Add check/format command 2022-07-04 16:59:27 +08:00
世界 13f41f59d6 Refine log output 2022-07-04 16:45:32 +08:00
世界 ca5b782106 Add domain_regex rule 2022-07-04 15:51:41 +08:00
世界 8e7f215514 Shadowsocks multi-user/relay inbound 2022-07-04 15:34:43 +08:00
世界 4fc4eb09b0 Add http/block outbound & Improve route 2022-07-04 08:16:25 +08:00
世界 18e3f43df3 Refactor struct & Add override dialer options 2022-07-03 20:59:25 +08:00
世界 28b865acf0 Refactor json 2022-07-03 19:43:27 +08:00
世界 dd56b2584b Add internal private geoip rule 2022-07-03 15:57:09 +08:00
世界 70c0812606 Add socks outbound 2022-07-03 13:14:49 +08:00
世界 ef5cfd59d4 Ordered json output & Disallow unknown fields 2022-07-03 11:28:15 +08:00
世界 85a695caa1 Add format config support 2022-07-03 03:42:57 +08:00
世界 30444057bd Invalid config check 2022-07-03 01:57:04 +08:00
世界 6eae8e361f Implement route rules 2022-07-02 23:19:14 +08:00
世界 7c57eb70e8 Inbound rule support 2022-07-02 14:07:50 +08:00
世界 9f4c0ff624 Refactor adapter 2022-07-01 19:37:41 +08:00
世界 60691819b1 Init commit 2022-07-01 16:58:18 +08:00
1343 changed files with 19120 additions and 153747 deletions
-31
View File
@@ -1,31 +0,0 @@
-s dir
--name sing-box
--category net
--license GPL-3.0-or-later
--description "The universal proxy platform."
--url "https://sing-box.sagernet.org/"
--maintainer "nekohasekai <contact-git@sekai.icu>"
--no-deb-generate-changes
--config-files /etc/config/sing-box
--config-files /etc/sing-box/config.json
--depends ca-bundle
--depends kmod-inet-diag
--depends kmod-tun
--depends firewall4
--depends kmod-nft-queue
--before-remove release/config/openwrt.prerm
release/config/config.json=/etc/sing-box/config.json
release/config/openwrt.conf=/etc/config/sing-box
release/config/openwrt.init=/etc/init.d/sing-box
release/config/openwrt.keep=/lib/upgrade/keep.d/sing-box
release/completions/sing-box.bash=/usr/share/bash-completion/completions/sing-box.bash
release/completions/sing-box.fish=/usr/share/fish/vendor_completions.d/sing-box.fish
release/completions/sing-box.zsh=/usr/share/zsh/site-functions/_sing-box
LICENSE=/usr/share/licenses/sing-box/LICENSE
-23
View File
@@ -1,23 +0,0 @@
-s dir
--name sing-box
--category net
--license GPL-3.0-or-later
--description "The universal proxy platform."
--url "https://sing-box.sagernet.org/"
--maintainer "nekohasekai <contact-git@sekai.icu>"
--config-files etc/sing-box/config.json
--after-install release/config/sing-box.postinst
release/config/config.json=/etc/sing-box/config.json
release/config/sing-box.service=/usr/lib/systemd/system/sing-box.service
release/config/sing-box@.service=/usr/lib/systemd/system/sing-box@.service
release/config/sing-box.sysusers=/usr/lib/sysusers.d/sing-box.conf
release/config/sing-box.rules=usr/share/polkit-1/rules.d/sing-box.rules
release/config/sing-box-split-dns.xml=/usr/share/dbus-1/system.d/sing-box-split-dns.conf
release/completions/sing-box.bash=/usr/share/bash-completion/completions/sing-box.bash
release/completions/sing-box.fish=/usr/share/fish/vendor_completions.d/sing-box.fish
release/completions/sing-box.zsh=/usr/share/zsh/site-functions/_sing-box
LICENSE=/usr/share/licenses/sing-box/LICENSE
-26
View File
@@ -1,26 +0,0 @@
-s dir
--name sing-box
--category net
--license GPL-3.0-or-later
--description "The universal proxy platform."
--url "https://sing-box.sagernet.org/"
--vendor SagerNet
--maintainer "nekohasekai <contact-git@sekai.icu>"
--deb-field "Bug: https://github.com/SagerNet/sing-box/issues"
--no-deb-generate-changes
--config-files /etc/sing-box/config.json
--after-install release/config/sing-box.postinst
release/config/config.json=/etc/sing-box/config.json
release/config/sing-box.service=/usr/lib/systemd/system/sing-box.service
release/config/sing-box@.service=/usr/lib/systemd/system/sing-box@.service
release/config/sing-box.sysusers=/usr/lib/sysusers.d/sing-box.conf
release/config/sing-box.rules=usr/share/polkit-1/rules.d/sing-box.rules
release/config/sing-box-split-dns.xml=/usr/share/dbus-1/system.d/sing-box-split-dns.conf
release/completions/sing-box.bash=/usr/share/bash-completion/completions/sing-box.bash
release/completions/sing-box.fish=/usr/share/fish/vendor_completions.d/sing-box.fish
release/completions/sing-box.zsh=/usr/share/zsh/site-functions/_sing-box
LICENSE=/usr/share/licenses/sing-box/LICENSE
-1
View File
@@ -1 +0,0 @@
2faf34666c2cc8234f10f2ab6d4c4d6104d34ae2
-94
View File
@@ -1,94 +0,0 @@
#!/usr/bin/env bash
set -e -o pipefail
prepare_apk_root() {
# apk mkpkg resolves owner/group names through --root/etc/{passwd,group}.
APK_ROOT_DIR=$(mktemp -d)
mkdir -p "$APK_ROOT_DIR/etc"
cat > "$APK_ROOT_DIR/etc/passwd" <<EOF
root:x:$(id -u):$(id -g):root:/root:/sbin/nologin
EOF
cat > "$APK_ROOT_DIR/etc/group" <<EOF
root:x:$(id -g):root
EOF
}
ARCHITECTURE="$1"
VERSION="$2"
BINARY_PATH="$3"
OUTPUT_PATH="$4"
if [ -z "$ARCHITECTURE" ] || [ -z "$VERSION" ] || [ -z "$BINARY_PATH" ] || [ -z "$OUTPUT_PATH" ]; then
echo "Usage: $0 <architecture> <version> <binary_path> <output_path>"
exit 1
fi
PROJECT=$(cd "$(dirname "$0")/.."; pwd)
# Convert version to APK format:
# 1.13.0-beta.8 -> 1.13.0_beta8-r0
# 1.13.0-rc.3 -> 1.13.0_rc3-r0
# 1.13.0 -> 1.13.0-r0
APK_VERSION=$(echo "$VERSION" | sed -E 's/-([a-z]+)\.([0-9]+)/_\1\2/')
APK_VERSION="${APK_VERSION}-r0"
ROOT_DIR=$(mktemp -d)
prepare_apk_root
trap 'rm -rf "$ROOT_DIR" "$APK_ROOT_DIR"' EXIT
# Binary
install -Dm755 "$BINARY_PATH" "$ROOT_DIR/usr/bin/sing-box"
# Config files
install -Dm644 "$PROJECT/release/config/config.json" "$ROOT_DIR/etc/sing-box/config.json"
install -Dm755 "$PROJECT/release/config/sing-box.initd" "$ROOT_DIR/etc/init.d/sing-box"
install -Dm644 "$PROJECT/release/config/sing-box.confd" "$ROOT_DIR/etc/conf.d/sing-box"
# Service files
install -Dm644 "$PROJECT/release/config/sing-box.service" "$ROOT_DIR/usr/lib/systemd/system/sing-box.service"
install -Dm644 "$PROJECT/release/config/sing-box@.service" "$ROOT_DIR/usr/lib/systemd/system/sing-box@.service"
# Completions
install -Dm644 "$PROJECT/release/completions/sing-box.bash" "$ROOT_DIR/usr/share/bash-completion/completions/sing-box.bash"
install -Dm644 "$PROJECT/release/completions/sing-box.fish" "$ROOT_DIR/usr/share/fish/vendor_completions.d/sing-box.fish"
install -Dm644 "$PROJECT/release/completions/sing-box.zsh" "$ROOT_DIR/usr/share/zsh/site-functions/_sing-box"
# License
install -Dm644 "$PROJECT/LICENSE" "$ROOT_DIR/usr/share/licenses/sing-box/LICENSE"
# APK metadata
PACKAGES_DIR="$ROOT_DIR/lib/apk/packages"
mkdir -p "$PACKAGES_DIR"
# .conffiles
cat > "$PACKAGES_DIR/.conffiles" <<'EOF'
/etc/conf.d/sing-box
/etc/init.d/sing-box
/etc/sing-box/config.json
EOF
# .conffiles_static (sha256 checksums)
while IFS= read -r conffile; do
sha256=$(sha256sum "$ROOT_DIR$conffile" | cut -d' ' -f1)
echo "$conffile $sha256"
done < "$PACKAGES_DIR/.conffiles" > "$PACKAGES_DIR/.conffiles_static"
# .list (all files, excluding lib/apk/packages/ metadata)
(cd "$ROOT_DIR" && find . -type f -o -type l) \
| sed 's|^\./|/|' \
| grep -v '^/lib/apk/packages/' \
| sort > "$PACKAGES_DIR/.list"
# Build APK
apk --root "$APK_ROOT_DIR" mkpkg \
--info "name:sing-box" \
--info "version:${APK_VERSION}" \
--info "description:The universal proxy platform." \
--info "arch:${ARCHITECTURE}" \
--info "license:GPL-3.0-or-later with name use or association addition" \
--info "origin:sing-box" \
--info "url:https://sing-box.sagernet.org/" \
--info "maintainer:nekohasekai <contact-git@sekai.icu>" \
--files "$ROOT_DIR" \
--output "$OUTPUT_PATH"
-93
View File
@@ -1,93 +0,0 @@
#!/usr/bin/env bash
set -e -o pipefail
prepare_apk_root() {
# apk mkpkg resolves owner/group names through --root/etc/{passwd,group}.
APK_ROOT_DIR=$(mktemp -d)
mkdir -p "$APK_ROOT_DIR/etc"
cat > "$APK_ROOT_DIR/etc/passwd" <<EOF
root:x:$(id -u):$(id -g):root:/root:/sbin/nologin
EOF
cat > "$APK_ROOT_DIR/etc/group" <<EOF
root:x:$(id -g):root
EOF
}
ARCHITECTURE="$1"
VERSION="$2"
BINARY_PATH="$3"
OUTPUT_PATH="$4"
if [ -z "$ARCHITECTURE" ] || [ -z "$VERSION" ] || [ -z "$BINARY_PATH" ] || [ -z "$OUTPUT_PATH" ]; then
echo "Usage: $0 <architecture> <version> <binary_path> <output_path>"
exit 1
fi
PROJECT=$(cd "$(dirname "$0")/.."; pwd)
# Convert version to APK format:
# 1.13.0-beta.8 -> 1.13.0_beta8-r0
# 1.13.0-rc.3 -> 1.13.0_rc3-r0
# 1.13.0 -> 1.13.0-r0
APK_VERSION=$(echo "$VERSION" | sed -E 's/-([a-z]+)\.([0-9]+)/_\1\2/')
APK_VERSION="${APK_VERSION}-r0"
ROOT_DIR=$(mktemp -d)
prepare_apk_root
trap 'rm -rf "$ROOT_DIR" "$APK_ROOT_DIR"' EXIT
# Binary
install -Dm755 "$BINARY_PATH" "$ROOT_DIR/usr/bin/sing-box"
# Config files
install -Dm644 "$PROJECT/release/config/config.json" "$ROOT_DIR/etc/sing-box/config.json"
install -Dm644 "$PROJECT/release/config/openwrt.conf" "$ROOT_DIR/etc/config/sing-box"
install -Dm755 "$PROJECT/release/config/openwrt.init" "$ROOT_DIR/etc/init.d/sing-box"
install -Dm644 "$PROJECT/release/config/openwrt.keep" "$ROOT_DIR/lib/upgrade/keep.d/sing-box"
# Completions
install -Dm644 "$PROJECT/release/completions/sing-box.bash" "$ROOT_DIR/usr/share/bash-completion/completions/sing-box.bash"
install -Dm644 "$PROJECT/release/completions/sing-box.fish" "$ROOT_DIR/usr/share/fish/vendor_completions.d/sing-box.fish"
install -Dm644 "$PROJECT/release/completions/sing-box.zsh" "$ROOT_DIR/usr/share/zsh/site-functions/_sing-box"
# License
install -Dm644 "$PROJECT/LICENSE" "$ROOT_DIR/usr/share/licenses/sing-box/LICENSE"
# APK metadata
PACKAGES_DIR="$ROOT_DIR/lib/apk/packages"
mkdir -p "$PACKAGES_DIR"
# .conffiles
cat > "$PACKAGES_DIR/.conffiles" <<'EOF'
/etc/config/sing-box
/etc/sing-box/config.json
EOF
# .conffiles_static (sha256 checksums)
while IFS= read -r conffile; do
sha256=$(sha256sum "$ROOT_DIR$conffile" | cut -d' ' -f1)
echo "$conffile $sha256"
done < "$PACKAGES_DIR/.conffiles" > "$PACKAGES_DIR/.conffiles_static"
# .list (all files, excluding lib/apk/packages/ metadata)
(cd "$ROOT_DIR" && find . -type f -o -type l) \
| sed 's|^\./|/|' \
| grep -v '^/lib/apk/packages/' \
| sort > "$PACKAGES_DIR/.list"
# Build APK
apk --root "$APK_ROOT_DIR" mkpkg \
--info "name:sing-box" \
--info "version:${APK_VERSION}" \
--info "description:The universal proxy platform." \
--info "arch:${ARCHITECTURE}" \
--info "license:GPL-3.0-or-later" \
--info "origin:sing-box" \
--info "url:https://sing-box.sagernet.org/" \
--info "maintainer:nekohasekai <contact-git@sekai.icu>" \
--info "depends:ca-bundle kmod-inet-diag kmod-tun firewall4 kmod-nft-queue" \
--info "provider-priority:100" \
--script "pre-deinstall:${PROJECT}/release/config/openwrt.prerm" \
--files "$ROOT_DIR" \
--output "$OUTPUT_PATH"
-28
View File
@@ -1,28 +0,0 @@
#!/usr/bin/env bash
# mod from https://gist.github.com/pldubouilh/c5703052986bfdd404005951dee54683
set -e -o pipefail
PROJECT=$(dirname "$0")/../..
TMP_PATH=`mktemp -d`
cp $2 $TMP_PATH
pushd $TMP_PATH
DEB_NAME=`ls *.deb`
ar x $DEB_NAME
mkdir control
pushd control
tar xf ../control.tar.gz
rm md5sums
sed "s/Architecture:\\ \w*/Architecture:\\ $1/g" ./control -i
cat control
tar czf ../control.tar.gz ./*
popd
DEB_NAME=${DEB_NAME%.deb}
tar czf $DEB_NAME.ipk control.tar.gz data.tar.gz debian-binary
popd
cp $TMP_PATH/$DEB_NAME.ipk $3
rm -r $TMP_PATH
-33
View File
@@ -1,33 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
branches=$(git branch -r --contains HEAD)
if echo "$branches" | grep -q 'origin/stable'; then
track=stable
elif echo "$branches" | grep -q 'origin/testing'; then
track=testing
elif echo "$branches" | grep -q 'origin/oldstable'; then
track=oldstable
else
echo "ERROR: HEAD is not on any known release branch (stable/testing/oldstable)" >&2
exit 1
fi
if [[ "$track" == "stable" ]]; then
tag=$(git describe --tags --exact-match HEAD 2>/dev/null || true)
if [[ -n "$tag" && "$tag" == *"-"* ]]; then
track=beta
fi
fi
case "$track" in
stable) name=sing-box; docker_tag=latest ;;
beta) name=sing-box-beta; docker_tag=latest-beta ;;
testing) name=sing-box-testing; docker_tag=latest-testing ;;
oldstable) name=sing-box-oldstable; docker_tag=latest-oldstable ;;
esac
echo "track=${track} name=${name} docker_tag=${docker_tag}" >&2
echo "TRACK=${track}" >> "$GITHUB_ENV"
echo "NAME=${name}" >> "$GITHUB_ENV"
echo "DOCKER_TAG=${docker_tag}" >> "$GITHUB_ENV"
+1 -1
View File
@@ -6,7 +6,7 @@
":disableRateLimiting"
],
"baseBranches": [
"unstable"
"dev-next"
],
"golang": {
"enabled": false
-45
View File
@@ -1,45 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
VERSION="1.25.9"
PATCH_COMMITS=(
"afe69d3cec1c6dcf0f1797b20546795730850070"
"1ed289b0cf87dc5aae9c6fe1aa5f200a83412938"
)
CURL_ARGS=(
-fL
--silent
--show-error
)
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
CURL_ARGS+=(-H "Authorization: Bearer ${GITHUB_TOKEN}")
fi
mkdir -p "$HOME/go"
cd "$HOME/go"
wget "https://dl.google.com/go/go${VERSION}.darwin-arm64.tar.gz"
tar -xzf "go${VERSION}.darwin-arm64.tar.gz"
#cp -a go go_bootstrap
mv go go_osx
cd go_osx
# these patch URLs only work on golang1.25.x
# that means after golang1.26 release it must be changed
# see: https://github.com/SagerNet/go/commits/release-branch.go1.25/
# revert:
# 33d3f603c1: "cmd/link/internal/ld: use 12.0.0 OS/SDK versions for macOS linking"
# 937368f84e: "crypto/x509: change how we retrieve chains on darwin"
for patch_commit in "${PATCH_COMMITS[@]}"; do
curl "${CURL_ARGS[@]}" "https://github.com/SagerNet/go/commit/${patch_commit}.diff" | patch --verbose -p 1
done
# Rebuild is not needed: we build with CGO_ENABLED=1, so Apple's external
# linker handles LC_BUILD_VERSION via MACOSX_DEPLOYMENT_TARGET, and the
# stdlib (crypto/x509) is compiled from patched src automatically.
#cd src
#GOROOT_BOOTSTRAP="$HOME/go/go_bootstrap" ./make.bash
#cd ../..
#rm -rf go_bootstrap "go${VERSION}.darwin-arm64.tar.gz"
-46
View File
@@ -1,46 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
VERSION="1.25.9"
PATCH_COMMITS=(
"466f6c7a29bc098b0d4c987b803c779222894a11"
"1bdabae205052afe1dadb2ad6f1ba612cdbc532a"
"a90777dcf692dd2168577853ba743b4338721b06"
"f6bddda4e8ff58a957462a1a09562924d5f3d05c"
"bed309eff415bcb3c77dd4bc3277b682b89a388d"
"34b899c2fb39b092db4fa67c4417e41dc046be4b"
)
CURL_ARGS=(
-fL
--silent
--show-error
)
if [[ -n "${GITHUB_TOKEN:-}" ]]; then
CURL_ARGS+=(-H "Authorization: Bearer ${GITHUB_TOKEN}")
fi
mkdir -p "$HOME/go"
cd "$HOME/go"
wget "https://dl.google.com/go/go${VERSION}.linux-amd64.tar.gz"
tar -xzf "go${VERSION}.linux-amd64.tar.gz"
mv go go_win7
cd go_win7
# modify from https://github.com/restic/restic/issues/4636#issuecomment-1896455557
# these patch URLs only work on golang1.25.x
# that means after golang1.26 release it must be changed
# see: https://github.com/MetaCubeX/go/commits/release-branch.go1.25/
# revert:
# 693def151adff1af707d82d28f55dba81ceb08e1: "crypto/rand,runtime: switch RtlGenRandom for ProcessPrng"
# 7c1157f9544922e96945196b47b95664b1e39108: "net: remove sysSocket fallback for Windows 7"
# 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround"
# a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries"
# fixes:
# bed309eff415bcb3c77dd4bc3277b682b89a388d: "Fix os.RemoveAll not working on Windows7"
# 34b899c2fb39b092db4fa67c4417e41dc046be4b: "Revert \"os: remove 5ms sleep on Windows in (*Process).Wait\""
for patch_commit in "${PATCH_COMMITS[@]}"; do
curl "${CURL_ARGS[@]}" "https://github.com/MetaCubeX/go/commit/${patch_commit}.diff" | patch --verbose -p 1
done
-13
View File
@@ -1,13 +0,0 @@
#!/usr/bin/env bash
set -e -o pipefail
SCRIPT_DIR=$(dirname "$0")
PROJECTS=$SCRIPT_DIR/../..
git -C $PROJECTS/cronet-go fetch origin main
git -C $PROJECTS/cronet-go fetch origin go
go get -x github.com/sagernet/cronet-go/all@$(git -C $PROJECTS/cronet-go rev-parse origin/go)
go get -x github.com/sagernet/cronet-go@$(git -C $PROJECTS/cronet-go rev-parse origin/go)
go mod tidy
git -C $PROJECTS/cronet-go rev-parse origin/go > "$SCRIPT_DIR/CRONET_GO_VERSION"
-13
View File
@@ -1,13 +0,0 @@
#!/usr/bin/env bash
set -e -o pipefail
SCRIPT_DIR=$(dirname "$0")
PROJECTS=$SCRIPT_DIR/../..
git -C $PROJECTS/cronet-go fetch origin dev
git -C $PROJECTS/cronet-go fetch origin go_dev
go get -x github.com/sagernet/cronet-go/all@$(git -C $PROJECTS/cronet-go rev-parse origin/go_dev)
go get -x github.com/sagernet/cronet-go@$(git -C $PROJECTS/cronet-go rev-parse origin/go_dev)
go mod tidy
git -C $PROJECTS/cronet-go rev-parse origin/dev > "$SCRIPT_DIR/CRONET_GO_VERSION"
File diff suppressed because it is too large Load Diff
+23 -185
View File
@@ -1,10 +1,6 @@
name: Publish Docker Images
on:
#push:
# branches:
# - stable
# - testing
release:
types:
- published
@@ -17,25 +13,20 @@ env:
REGISTRY_IMAGE: ghcr.io/sagernet/sing-box
jobs:
build_binary:
name: Build binary
build:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
include:
# Naive-enabled builds (musl)
- { arch: amd64, naive: true, docker_platform: "linux/amd64" }
- { arch: arm64, naive: true, docker_platform: "linux/arm64" }
- { arch: "386", naive: true, docker_platform: "linux/386" }
- { arch: arm, goarm: "7", naive: true, docker_platform: "linux/arm/v7" }
- { arch: mipsle, gomips: softfloat, naive: true, docker_platform: "linux/mipsle" }
- { arch: riscv64, naive: true, docker_platform: "linux/riscv64" }
- { arch: loong64, naive: true, docker_platform: "linux/loong64" }
# Non-naive builds
- { arch: arm, goarm: "6", docker_platform: "linux/arm/v6" }
- { arch: ppc64le, docker_platform: "linux/ppc64le" }
- { arch: s390x, docker_platform: "linux/s390x" }
platform:
- linux/amd64
- linux/arm/v6
- linux/arm/v7
- linux/arm64
- linux/386
- linux/ppc64le
- linux/riscv64
- linux/s390x
steps:
- name: Get commit to build
id: ref
@@ -48,146 +39,7 @@ jobs:
echo "ref=$ref"
echo "ref=$ref" >> $GITHUB_OUTPUT
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
with:
ref: ${{ steps.ref.outputs.ref }}
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ~1.25.9
- name: Clone cronet-go
if: matrix.naive
run: |
set -xeuo pipefail
CRONET_GO_VERSION=$(cat .github/CRONET_GO_VERSION)
git init ~/cronet-go
git -C ~/cronet-go remote add origin https://github.com/sagernet/cronet-go.git
git -C ~/cronet-go fetch --depth=1 origin "$CRONET_GO_VERSION"
git -C ~/cronet-go checkout FETCH_HEAD
git -C ~/cronet-go submodule update --init --recursive --depth=1
- name: Regenerate Debian keyring
if: matrix.naive
run: |
set -xeuo pipefail
rm -f ~/cronet-go/naiveproxy/src/build/linux/sysroot_scripts/keyring.gpg
cd ~/cronet-go
GPG_TTY=/dev/null ./naiveproxy/src/build/linux/sysroot_scripts/generate_keyring.sh
- name: Cache Chromium toolchain
if: matrix.naive
id: cache-chromium-toolchain
uses: actions/cache@v4
with:
path: |
~/cronet-go/naiveproxy/src/third_party/llvm-build/
~/cronet-go/naiveproxy/src/gn/out/
~/cronet-go/naiveproxy/src/chrome/build/pgo_profiles/
~/cronet-go/naiveproxy/src/out/sysroot-build/
key: chromium-toolchain-${{ matrix.arch }}-musl-${{ hashFiles('.github/CRONET_GO_VERSION') }}
- name: Download Chromium toolchain
if: matrix.naive
run: |
set -xeuo pipefail
cd ~/cronet-go
go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl download-toolchain
- name: Set version
run: |
set -xeuo pipefail
VERSION=$(go run ./cmd/internal/read_tag)
echo "VERSION=${VERSION}" >> "${GITHUB_ENV}"
- name: Set Chromium toolchain environment
if: matrix.naive
run: |
set -xeuo pipefail
cd ~/cronet-go
go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl env >> $GITHUB_ENV
- name: Set build tags
run: |
set -xeuo pipefail
if [[ "${{ matrix.naive }}" == "true" ]]; then
TAGS="$(cat release/DEFAULT_BUILD_TAGS),with_musl"
else
TAGS=$(cat release/DEFAULT_BUILD_TAGS_OTHERS)
fi
echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}"
- name: Set shared ldflags
run: |
echo "LDFLAGS_SHARED=$(cat release/LDFLAGS)" >> "${GITHUB_ENV}"
- name: Build (naive)
if: matrix.naive
run: |
set -xeuo pipefail
go build -v -trimpath -o sing-box -tags "${BUILD_TAGS}" \
-ldflags "-X 'github.com/sagernet/sing-box/constant.Version=${VERSION}' ${LDFLAGS_SHARED} -s -w -buildid=" \
./cmd/sing-box
env:
CGO_ENABLED: "1"
GOOS: linux
GOARCH: ${{ matrix.arch }}
GOARM: ${{ matrix.goarm }}
GOMIPS: ${{ matrix.gomips }}
- name: Build (non-naive)
if: ${{ ! matrix.naive }}
run: |
set -xeuo pipefail
go build -v -trimpath -o sing-box -tags "${BUILD_TAGS}" \
-ldflags "-X 'github.com/sagernet/sing-box/constant.Version=${VERSION}' ${LDFLAGS_SHARED} -s -w -buildid=" \
./cmd/sing-box
env:
CGO_ENABLED: "0"
GOOS: linux
GOARCH: ${{ matrix.arch }}
GOARM: ${{ matrix.goarm }}
- name: Prepare artifact
run: |
platform=${{ matrix.docker_platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
# Rename binary to include arch info for Dockerfile.binary
BINARY_NAME="sing-box-${{ matrix.arch }}"
if [[ -n "${{ matrix.goarm }}" ]]; then
BINARY_NAME="${BINARY_NAME}v${{ matrix.goarm }}"
fi
mv sing-box "${BINARY_NAME}"
echo "BINARY_NAME=${BINARY_NAME}" >> $GITHUB_ENV
- name: Upload binary
uses: actions/upload-artifact@v4
with:
name: binary-${{ env.PLATFORM_PAIR }}
path: ${{ env.BINARY_NAME }}
if-no-files-found: error
retention-days: 1
build_docker:
name: Build Docker image
runs-on: ubuntu-latest
needs:
- build_binary
strategy:
fail-fast: true
matrix:
include:
- { platform: "linux/amd64" }
- { platform: "linux/arm/v6" }
- { platform: "linux/arm/v7" }
- { platform: "linux/arm64" }
- { platform: "linux/386" }
# mipsle: no base Docker image available for this platform
- { platform: "linux/ppc64le" }
- { platform: "linux/riscv64" }
- { platform: "linux/s390x" }
- { platform: "linux/loong64", base_image: "ghcr.io/loong64/alpine:edge" }
steps:
- name: Get commit to build
id: ref
run: |-
if [[ -z "${{ github.event.inputs.tag }}" ]]; then
ref="${{ github.ref_name }}"
else
ref="${{ github.event.inputs.tag }}"
fi
echo "ref=$ref"
echo "ref=$ref" >> $GITHUB_OUTPUT
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
ref: ${{ steps.ref.outputs.ref }}
fetch-depth: 0
@@ -195,16 +47,6 @@ jobs:
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Download binary
uses: actions/download-artifact@v5
with:
name: binary-${{ env.PLATFORM_PAIR }}
path: .
- name: Prepare binary
run: |
# Find and make the binary executable
chmod +x sing-box-*
ls -la sing-box-*
- name: Setup QEMU
uses: docker/setup-qemu-action@v3
- name: Setup Docker Buildx
@@ -226,9 +68,8 @@ jobs:
with:
platforms: ${{ matrix.platform }}
context: .
file: Dockerfile.binary
build-args: |
BASE_IMAGE=${{ matrix.base_image || 'alpine' }}
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
labels: ${{ steps.meta.outputs.labels }}
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
- name: Export digest
@@ -244,10 +85,9 @@ jobs:
if-no-files-found: error
retention-days: 1
merge:
if: github.event_name != 'push'
runs-on: ubuntu-latest
needs:
- build_docker
- build
steps:
- name: Get commit to build
id: ref
@@ -259,15 +99,15 @@ jobs:
fi
echo "ref=$ref"
echo "ref=$ref" >> $GITHUB_OUTPUT
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
with:
ref: ${{ steps.ref.outputs.ref }}
fetch-depth: 0
- name: Detect track
run: bash .github/detect_track.sh
if [[ $ref == *"-"* ]]; then
latest=latest-beta
else
latest=latest
fi
echo "latest=$latest"
echo "latest=$latest" >> $GITHUB_OUTPUT
- name: Download digests
uses: actions/download-artifact@v5
uses: actions/download-artifact@v4
with:
path: /tmp/digests
pattern: digests-*
@@ -281,15 +121,13 @@ jobs:
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create manifest list and push
if: github.event_name != 'push'
working-directory: /tmp/digests
run: |
docker buildx imagetools create \
-t "${{ env.REGISTRY_IMAGE }}:${{ env.DOCKER_TAG }}" \
-t "${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.latest }}" \
-t "${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.ref }}" \
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
- name: Inspect image
if: github.event_name != 'push'
run: |
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ env.DOCKER_TAG }}
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.latest }}
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.ref }}
+11 -53
View File
@@ -3,77 +3,35 @@ name: Lint
on:
push:
branches:
- oldstable
- stable
- testing
- unstable
- stable-next
- main-next
- dev-next
paths-ignore:
- '**.md'
- '.github/**'
- '!.github/workflows/lint.yml'
pull_request:
branches:
- oldstable
- stable
- testing
- unstable
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}-${{ inputs.build }}
cancel-in-progress: true
- stable-next
- main-next
- dev-next
jobs:
build:
name: Lint ${{ matrix.goos }}/${{ matrix.goarch }}
name: Build
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- goos: windows
goarch: amd64
- goos: windows
goarch: '386'
- goos: windows
goarch: arm64
- goos: linux
goarch: amd64
- goos: linux
goarch: arm64
- goos: linux
goarch: arm
- goos: linux
goarch: '386'
- goos: darwin
goarch: amd64
- goos: darwin
goarch: arm64
- goos: android
goarch: arm64
# - goos: freebsd
# goarch: amd64
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ^1.25
- name: Cache go module
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
key: go-${{ hashFiles('**/go.sum') }}
go-version: ^1.23
- name: golangci-lint
uses: golangci/golangci-lint-action@v8
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
uses: golangci/golangci-lint-action@v6
with:
version: latest
args: --timeout=30m
install-mode: binary
verify: false
install-mode: binary
+18 -223
View File
@@ -1,243 +1,38 @@
name: Build Linux Packages
name: Release to Linux repository
on:
#push:
# branches:
# - stable
# - testing
workflow_dispatch:
inputs:
version:
description: "Version name"
required: true
type: string
release:
types:
- published
jobs:
calculate_version:
name: Calculate version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.outputs.outputs.version }}
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ~1.25.9
- name: Check input version
if: github.event_name == 'workflow_dispatch'
run: |-
echo "version=${{ inputs.version }}"
echo "version=${{ inputs.version }}" >> "$GITHUB_ENV"
- name: Calculate version
if: github.event_name != 'workflow_dispatch'
run: |-
go run -v ./cmd/internal/read_tag --ci --nightly
- name: Set outputs
id: outputs
run: |-
echo "version=$version" >> "$GITHUB_OUTPUT"
build:
name: Build binary
runs-on: ubuntu-latest
needs:
- calculate_version
strategy:
matrix:
include:
# Naive-enabled builds (musl)
- { os: linux, arch: amd64, naive: true, debian: amd64, rpm: x86_64, pacman: x86_64 }
- { os: linux, arch: arm64, naive: true, debian: arm64, rpm: aarch64, pacman: aarch64 }
- { os: linux, arch: "386", naive: true, debian: i386, rpm: i386 }
- { os: linux, arch: arm, goarm: "7", naive: true, debian: armhf, rpm: armv7hl, pacman: armv7hl }
- { os: linux, arch: mipsle, gomips: softfloat, naive: true, debian: mipsel, rpm: mipsel }
- { os: linux, arch: riscv64, naive: true, debian: riscv64, rpm: riscv64 }
- { os: linux, arch: loong64, naive: true, debian: loongarch64, rpm: loongarch64 }
# Non-naive builds (unsupported architectures)
- { os: linux, arch: arm, goarm: "6", debian: armel, rpm: armv6hl }
- { os: linux, arch: mips64le, debian: mips64el, rpm: mips64el }
- { os: linux, arch: s390x, debian: s390x, rpm: s390x }
- { os: linux, arch: ppc64le, debian: ppc64el, rpm: ppc64le }
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4
with:
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ~1.25.9
- name: Clone cronet-go
if: matrix.naive
run: |
set -xeuo pipefail
CRONET_GO_VERSION=$(cat .github/CRONET_GO_VERSION)
git init ~/cronet-go
git -C ~/cronet-go remote add origin https://github.com/sagernet/cronet-go.git
git -C ~/cronet-go fetch --depth=1 origin "$CRONET_GO_VERSION"
git -C ~/cronet-go checkout FETCH_HEAD
git -C ~/cronet-go submodule update --init --recursive --depth=1
- name: Regenerate Debian keyring
if: matrix.naive
run: |
set -xeuo pipefail
rm -f ~/cronet-go/naiveproxy/src/build/linux/sysroot_scripts/keyring.gpg
cd ~/cronet-go
GPG_TTY=/dev/null ./naiveproxy/src/build/linux/sysroot_scripts/generate_keyring.sh
- name: Cache Chromium toolchain
if: matrix.naive
id: cache-chromium-toolchain
uses: actions/cache@v4
with:
path: |
~/cronet-go/naiveproxy/src/third_party/llvm-build/
~/cronet-go/naiveproxy/src/gn/out/
~/cronet-go/naiveproxy/src/chrome/build/pgo_profiles/
~/cronet-go/naiveproxy/src/out/sysroot-build/
key: chromium-toolchain-${{ matrix.arch }}-musl-${{ hashFiles('.github/CRONET_GO_VERSION') }}
- name: Download Chromium toolchain
if: matrix.naive
run: |
set -xeuo pipefail
cd ~/cronet-go
go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl download-toolchain
- name: Set Chromium toolchain environment
if: matrix.naive
run: |
set -xeuo pipefail
cd ~/cronet-go
go run ./cmd/build-naive --target=linux/${{ matrix.arch }} --libc=musl env >> $GITHUB_ENV
- name: Set tag
go-version: ^1.23
- name: Extract signing key
run: |-
git ls-remote --exit-code --tags origin v${{ needs.calculate_version.outputs.version }} || echo "PUBLISHED=false" >> "$GITHUB_ENV"
git tag v${{ needs.calculate_version.outputs.version }} -f
- name: Set build tags
run: |
set -xeuo pipefail
if [[ "${{ matrix.naive }}" == "true" ]]; then
TAGS="$(cat release/DEFAULT_BUILD_TAGS),with_musl"
else
TAGS=$(cat release/DEFAULT_BUILD_TAGS_OTHERS)
fi
echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}"
- name: Set shared ldflags
run: |
echo "LDFLAGS_SHARED=$(cat release/LDFLAGS)" >> "${GITHUB_ENV}"
- name: Build (naive)
if: matrix.naive
run: |
set -xeuo pipefail
mkdir -p dist
go build -v -trimpath -o dist/sing-box -tags "${BUILD_TAGS}" \
-ldflags "-X 'github.com/sagernet/sing-box/constant.Version=${{ needs.calculate_version.outputs.version }}' ${LDFLAGS_SHARED} -s -w -buildid=" \
./cmd/sing-box
env:
CGO_ENABLED: "1"
GOOS: linux
GOARCH: ${{ matrix.arch }}
GOARM: ${{ matrix.goarm }}
GOMIPS: ${{ matrix.gomips }}
GOMIPS64: ${{ matrix.gomips }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build (non-naive)
if: ${{ ! matrix.naive }}
run: |
set -xeuo pipefail
mkdir -p dist
go build -v -trimpath -o dist/sing-box -tags "${BUILD_TAGS}" \
-ldflags "-X 'github.com/sagernet/sing-box/constant.Version=${{ needs.calculate_version.outputs.version }}' ${LDFLAGS_SHARED} -s -w -buildid=" \
./cmd/sing-box
env:
CGO_ENABLED: "0"
GOOS: ${{ matrix.os }}
GOARCH: ${{ matrix.arch }}
GOARM: ${{ matrix.goarm }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Set mtime
run: |-
TZ=UTC touch -t '197001010000' dist/sing-box
- name: Detect track
run: bash .github/detect_track.sh
- name: Set version
run: |-
PKG_VERSION="${{ needs.calculate_version.outputs.version }}"
PKG_VERSION="${PKG_VERSION//-/\~}"
echo "PKG_VERSION=${PKG_VERSION}" >> "${GITHUB_ENV}"
- name: Package DEB
if: matrix.debian != ''
run: |
set -xeuo pipefail
sudo gem install fpm
sudo apt-get install -y debsigs
cp .fpm_systemd .fpm
fpm -t deb \
--name "${NAME}" \
-v "$PKG_VERSION" \
-p "dist/${NAME}_${{ needs.calculate_version.outputs.version }}_linux_${{ matrix.debian }}.deb" \
--architecture ${{ matrix.debian }} \
dist/sing-box=/usr/bin/sing-box
curl -Lo '/tmp/debsigs.diff' 'https://gitlab.com/debsigs/debsigs/-/commit/160138f5de1ec110376d3c807b60a37388bc7c90.diff'
sudo patch /usr/bin/debsigs < '/tmp/debsigs.diff'
rm -rf $HOME/.gnupg
gpg --pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}" --import <<EOF
mkdir -p $HOME/.gnupg
cat > $HOME/.gnupg/sagernet.key <<EOF
${{ secrets.GPG_KEY }}
EOF
debsigs --sign=origin -k ${{ secrets.GPG_KEY_ID }} --gpgopts '--pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}"' dist/*.deb
- name: Package RPM
if: matrix.rpm != ''
run: |-
set -xeuo pipefail
sudo gem install fpm
cp .fpm_systemd .fpm
fpm -t rpm \
--name "${NAME}" \
-v "$PKG_VERSION" \
-p "dist/${NAME}_${{ needs.calculate_version.outputs.version }}_linux_${{ matrix.rpm }}.rpm" \
--architecture ${{ matrix.rpm }} \
dist/sing-box=/usr/bin/sing-box
cat > $HOME/.rpmmacros <<EOF
%_gpg_name ${{ secrets.GPG_KEY_ID }}
%_gpg_sign_cmd_extra_args --pinentry-mode loopback --passphrase ${{ secrets.GPG_PASSPHRASE }}
EOF
gpg --pinentry-mode loopback --passphrase "${{ secrets.GPG_PASSPHRASE }}" --import <<EOF
${{ secrets.GPG_KEY }}
EOF
rpmsign --addsign dist/*.rpm
- name: Cleanup
run: rm dist/sing-box
- name: Upload artifact
uses: actions/upload-artifact@v4
echo "HOME=$HOME" >> "$GITHUB_ENV"
- name: Publish release
uses: goreleaser/goreleaser-action@v6
with:
name: binary-${{ matrix.os }}_${{ matrix.arch }}${{ matrix.goarm && format('v{0}', matrix.goarm) }}${{ matrix.legacy_go && '-legacy' || '' }}
path: "dist"
upload:
name: Upload builds
runs-on: ubuntu-latest
needs:
- calculate_version
- build
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
with:
fetch-depth: 0
- name: Set tag
run: |-
git ls-remote --exit-code --tags origin v${{ needs.calculate_version.outputs.version }} || echo "PUBLISHED=false" >> "$GITHUB_ENV"
git tag v${{ needs.calculate_version.outputs.version }} -f
echo "VERSION=${{ needs.calculate_version.outputs.version }}" >> "$GITHUB_ENV"
- name: Download builds
uses: actions/download-artifact@v5
with:
path: dist
merge-multiple: true
- name: Publish packages
if: github.event_name != 'push'
run: |-
ls dist | xargs -I {} curl -F "package=@dist/{}" https://${{ secrets.FURY_TOKEN }}@push.fury.io/sagernet/
distribution: goreleaser-pro
version: latest
args: release -f .goreleaser.fury.yaml --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
NFPM_KEY_PATH: ${{ env.HOME }}/.gnupg/sagernet.key
NFPM_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
+1 -15
View File
@@ -12,21 +12,7 @@
/*.jar
/*.aar
/*.xcframework/
/experimental/libbox/*.aar
/experimental/libbox/*.xcframework/
/experimental/libbox/*.nupkg
.DS_Store
/config.d/
/venv/
CLAUDE.md
AGENTS.md
/.claude/
dist
logs
/*.so
/*.log
/*.db-shm
/*.db-wal
/*.db.backup.*
/test_download.bin
/wget-log
+6
View File
@@ -0,0 +1,6 @@
[submodule "clients/apple"]
path = clients/apple
url = https://github.com/SagerNet/sing-box-for-apple.git
[submodule "clients/android"]
path = clients/android
url = https://github.com/SagerNet/sing-box-for-android.git
+29 -47
View File
@@ -1,56 +1,38 @@
version: "2"
linters:
disable-all: true
enable:
- gofumpt
- govet
- gci
- staticcheck
- paralleltest
- ineffassign
linters-settings:
gci:
custom-order: true
sections:
- standard
- prefix(github.com/sagernet/)
- default
staticcheck:
checks:
- all
- -SA1003
run:
go: "1.24"
go: "1.23"
build-tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_ech
- with_utls
- with_reality_server
- with_acme
- with_clash_api
- with_tailscale
- with_ccm
- with_ocm
- badlinkname
- tfogo_checklinkname0
linters:
default: none
enable:
- ineffassign
- paralleltest
- staticcheck
- unused
- modernize
settings:
modernize:
disable:
- omitzero # nested struct omitempty -> omitzero changes JSON output semantics
staticcheck:
checks:
- all
- -QF1008 # could remove embedded field "<interface>" from selector
- -ST1003 # should not use ALL_CAPS in Go names; use CamelCase instead
- -QF1001 # could apply De Morgan's law
exclusions:
generated: lax
presets:
- comments
- common-false-positives
paths:
- transport/simple-obfs
- \.pb\.go$
- third_party$
- builtin$
- examples$
formatters:
enable:
- gci
- gofumpt
settings:
gci:
sections:
- standard
- prefix(github.com/sagernet/)
- default
custom-order: true
issues:
exclude-dirs:
- transport/simple-obfs
+96
View File
@@ -0,0 +1,96 @@
project_name: sing-box
builds:
- id: main
main: ./cmd/sing-box
flags:
- -v
- -trimpath
ldflags:
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }} -s -w -buildid=
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_ech
- with_utls
- with_reality_server
- with_acme
- with_clash_api
env:
- CGO_ENABLED=0
targets:
- linux_386
- linux_amd64_v1
- linux_arm64
- linux_arm_7
- linux_s390x
- linux_riscv64
- linux_mips64le
mod_timestamp: '{{ .CommitTimestamp }}'
snapshot:
name_template: "{{ .Version }}.{{ .ShortCommit }}"
nfpms:
- &template
id: package
package_name: sing-box
file_name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
builds:
- main
homepage: https://sing-box.sagernet.org/
maintainer: nekohasekai <contact-git@sekai.icu>
description: The universal proxy platform.
license: GPLv3 or later
formats:
- deb
- rpm
priority: extra
contents:
- src: release/config/config.json
dst: /etc/sing-box/config.json
type: config
- src: release/config/sing-box.service
dst: /usr/lib/systemd/system/sing-box.service
- src: release/config/sing-box@.service
dst: /usr/lib/systemd/system/sing-box@.service
- src: release/completions/sing-box.bash
dst: /usr/share/bash-completion/completions/sing-box.bash
- src: release/completions/sing-box.fish
dst: /usr/share/fish/vendor_completions.d/sing-box.fish
- src: release/completions/sing-box.zsh
dst: /usr/share/zsh/site-functions/_sing-box
- src: LICENSE
dst: /usr/share/licenses/sing-box/LICENSE
deb:
signature:
key_file: "{{ .Env.NFPM_KEY_PATH }}"
fields:
Bugs: https://github.com/SagerNet/sing-box/issues
rpm:
signature:
key_file: "{{ .Env.NFPM_KEY_PATH }}"
conflicts:
- sing-box-beta
- id: package_beta
<<: *template
package_name: sing-box-beta
file_name_template: '{{ .ProjectName }}-beta_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
formats:
- deb
- rpm
conflicts:
- sing-box
release:
disable: true
furies:
- account: sagernet
ids:
- package
disable: "{{ not (not .Prerelease) }}"
- account: sagernet
ids:
- package_beta
disable: "{{ not .Prerelease }}"
+94 -389
View File
@@ -11,28 +11,18 @@ builds:
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }}
- -s
- -buildid=
- -checklinkname=0
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_ech
- with_utls
- with_reality_server
- with_acme
- with_clash_api
- with_tailscale
- with_masque
- with_mtproxy
- with_openvpn
- with_trusttunnel
- with_sudoku
- with_manager
- with_admin_panel
- badlinkname
- tfogo_checklinkname0
env:
- CGO_ENABLED=0
- GOTOOLCHAIN=local
targets:
- linux_386
- linux_amd64_v1
@@ -41,13 +31,14 @@ builds:
- linux_arm_7
- linux_s390x
- linux_riscv64
- linux_mips64le
- windows_amd64_v1
- windows_386
- windows_arm64
- darwin_amd64_v1
- darwin_arm64
mod_timestamp: '{{ .CommitTimestamp }}'
- id: mips
- id: legacy
<<: *template
tags:
- with_gvisor
@@ -55,28 +46,21 @@ builds:
- with_dhcp
- with_wireguard
- with_utls
- with_reality_server
- with_acme
- with_clash_api
- with_tailscale
- with_masque
- with_mtproxy
- with_openvpn
- with_trusttunnel
- with_sudoku
- badlinkname
- tfogo_checklinkname0
env:
- CGO_ENABLED=0
- GOROOT={{ .Env.GOPATH }}/go1.20.14
gobinary: "{{ .Env.GOPATH }}/go1.20.14/bin/go"
targets:
- linux_mips
- linux_mips_softfloat
- linux_mipsle
- linux_mipsle_softfloat
- linux_mips64
- linux_mips64le
- windows_amd64_v1
- windows_386
- darwin_amd64_v1
- id: android
<<: *template
env:
- CGO_ENABLED=1
- GOTOOLCHAIN=local
overrides:
- goos: android
goarch: arm
@@ -105,372 +89,98 @@ builds:
- android_arm64
- android_386
- android_amd64
- id: naive-purego-linux-amd64
<<: *template
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_utls
- with_acme
- with_clash_api
- with_tailscale
- with_masque
- with_mtproxy
- with_openvpn
- with_trusttunnel
- with_sudoku
- with_manager
- with_admin_panel
- badlinkname
- tfogo_checklinkname0
- with_naive_outbound
- with_purego
env:
- CGO_ENABLED=0
- GOTOOLCHAIN=local
hooks:
post:
- cmd: go run -C {{ .Env.CRONET_GO_PATH }} ./cmd/build-naive extract-lib --target {{ .Os }}/{{ .Arch }} -o {{ dir .Path }}
env:
- CGO_ENABLED=0
targets:
- linux_amd64_v1
- id: naive-purego-linux-arm64
<<: *template
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_utls
- with_acme
- with_clash_api
- with_tailscale
- with_masque
- with_mtproxy
- with_openvpn
- with_trusttunnel
- with_sudoku
- with_manager
- with_admin_panel
- badlinkname
- tfogo_checklinkname0
- with_naive_outbound
- with_purego
env:
- CGO_ENABLED=0
- GOTOOLCHAIN=local
hooks:
post:
- cmd: go run -C {{ .Env.CRONET_GO_PATH }} ./cmd/build-naive extract-lib --target {{ .Os }}/{{ .Arch }} -o {{ dir .Path }}
env:
- CGO_ENABLED=0
targets:
- linux_arm64
- id: naive-purego-windows-amd64
<<: *template
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_utls
- with_acme
- with_clash_api
- with_tailscale
- with_masque
- with_mtproxy
- with_openvpn
- with_trusttunnel
- with_sudoku
- with_manager
- with_admin_panel
- badlinkname
- tfogo_checklinkname0
- with_naive_outbound
- with_purego
env:
- CGO_ENABLED=0
- GOTOOLCHAIN=local
hooks:
post:
- cmd: go run -C {{ .Env.CRONET_GO_PATH }} ./cmd/build-naive extract-lib --target {{ .Os }}/{{ .Arch }} -o {{ dir .Path }}
env:
- CGO_ENABLED=0
targets:
- windows_amd64_v1
- id: naive-purego-windows-arm64
<<: *template
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_utls
- with_acme
- with_clash_api
- with_tailscale
- with_masque
- with_mtproxy
- with_openvpn
- with_trusttunnel
- with_sudoku
- with_manager
- with_admin_panel
- badlinkname
- tfogo_checklinkname0
- with_naive_outbound
- with_purego
env:
- CGO_ENABLED=0
- GOTOOLCHAIN=local
hooks:
post:
- cmd: go run -C {{ .Env.CRONET_GO_PATH }} ./cmd/build-naive extract-lib --target {{ .Os }}/{{ .Arch }} -o {{ dir .Path }}
env:
- CGO_ENABLED=0
targets:
- windows_arm64
- id: naive-glibc
<<: *template
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_utls
- with_acme
- with_clash_api
- with_tailscale
- with_masque
- with_mtproxy
- with_openvpn
- with_trusttunnel
- with_sudoku
- with_manager
- with_admin_panel
- badlinkname
- tfogo_checklinkname0
- with_naive_outbound
env:
- CGO_ENABLED=1
- GOTOOLCHAIN=local
- CGO_LDFLAGS=-fuse-ld=lld -Wl,-z,notext -Wl,-z,execstack
- CC_linux_amd64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=x86_64-linux-gnu --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/bullseye/bullseye_amd64_staging
- CXX_linux_amd64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=x86_64-linux-gnu --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/bullseye/bullseye_amd64_staging
- CC_linux_arm64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=aarch64-linux-gnu --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/bullseye/bullseye_arm64_staging
- CXX_linux_arm64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=aarch64-linux-gnu --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/bullseye/bullseye_arm64_staging
- CC_linux_386={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=i686-linux-gnu --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/bullseye/bullseye_i386_staging
- CXX_linux_386={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=i686-linux-gnu --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/bullseye/bullseye_i386_staging
- CC_linux_arm={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=arm-linux-gnueabihf --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/bullseye/bullseye_armhf_staging
- CXX_linux_arm={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=arm-linux-gnueabihf --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/bullseye/bullseye_armhf_staging
- CC_linux_mips64le={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=mips64el-linux-gnuabi64 --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/bullseye/bullseye_mips64el_staging
- CXX_linux_mips64le={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=mips64el-linux-gnuabi64 --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/bullseye/bullseye_mips64el_staging
- CC_linux_riscv64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=riscv64-linux-gnu --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/trixie/trixie_riscv64_staging
- CXX_linux_riscv64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=riscv64-linux-gnu --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/trixie/trixie_riscv64_staging
- CC_linux_loong64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=loongarch64-linux-gnu --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/sid/sid_loong64_staging
- CXX_linux_loong64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=loongarch64-linux-gnu --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/sid/sid_loong64_staging
- 'CC={{ index .Env (print "CC_" .Os "_" .Arch) }}'
- 'CXX={{ index .Env (print "CXX_" .Os "_" .Arch) }}'
targets:
- linux_amd64_v1
- linux_arm64
- linux_386
- linux_arm_7
- linux_riscv64
- linux_loong64
- id: naive-musl
<<: *template
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_utls
- with_acme
- with_clash_api
- with_tailscale
- with_masque
- with_mtproxy
- with_openvpn
- with_trusttunnel
- with_sudoku
- with_manager
- with_admin_panel
- badlinkname
- tfogo_checklinkname0
- with_naive_outbound
- with_musl
env:
- CGO_ENABLED=1
- GOTOOLCHAIN=local
- CGO_LDFLAGS=-fuse-ld=lld -Wl,-z,notext -Wl,-z,execstack
- CC_linux_amd64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=x86_64-openwrt-linux-musl --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/23.05.5/x86_64
- CXX_linux_amd64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=x86_64-openwrt-linux-musl --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/23.05.5/x86_64
- CC_linux_arm64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=aarch64-openwrt-linux-musl --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/23.05.5/aarch64
- CXX_linux_arm64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=aarch64-openwrt-linux-musl --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/23.05.5/aarch64
- CC_linux_386={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=i486-openwrt-linux-musl --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/23.05.5/i386_pentium4
- CXX_linux_386={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=i486-openwrt-linux-musl --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/23.05.5/i386_pentium4
- CC_linux_arm={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=arm-openwrt-linux-musleabi --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/23.05.5/arm_cortex-a15_neon-vfpv4
- CXX_linux_arm={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=arm-openwrt-linux-musleabi --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/23.05.5/arm_cortex-a15_neon-vfpv4
- CC_linux_riscv64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=riscv64-openwrt-linux-musl --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/23.05.5/riscv64
- CXX_linux_riscv64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=riscv64-openwrt-linux-musl --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/23.05.5/riscv64
- CC_linux_loong64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang --target=loongarch64-openwrt-linux-musl --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/24.10.5/loongarch64
- CXX_linux_loong64={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/third_party/llvm-build/Release+Asserts/bin/clang++ --target=loongarch64-openwrt-linux-musl --sysroot={{ .Env.CRONET_GO_PATH }}/naiveproxy/src/out/sysroot-build/openwrt/24.10.5/loongarch64
- 'CC={{ index .Env (print "CC_" .Os "_" .Arch) }}'
- 'CXX={{ index .Env (print "CXX_" .Os "_" .Arch) }}'
targets:
- linux_amd64_v1
- linux_arm64
- linux_386
- linux_arm_7
- linux_riscv64
- linux_loong64
- id: compressed
<<: *template
targets:
- linux_386
- linux_amd64_v1
- linux_arm64
- linux_arm_6
- linux_arm_7
- linux_riscv64
- id: compressed-mips
<<: *template
tags:
- with_gvisor
- with_quic
- with_dhcp
- with_wireguard
- with_utls
- with_acme
- with_clash_api
- with_tailscale
- with_masque
- with_mtproxy
- with_openvpn
- with_trusttunnel
- with_sudoku
- badlinkname
- tfogo_checklinkname0
targets:
- linux_mips
- linux_mips_softfloat
- linux_mipsle
- linux_mipsle_softfloat
- id: compressed-android
<<: *template
env:
- CGO_ENABLED=1
- GOTOOLCHAIN=local
overrides:
- goos: android
goarch: arm
goarm: 7
env:
- CC=armv7a-linux-androideabi21-clang
- CXX=armv7a-linux-androideabi21-clang++
- goos: android
goarch: arm64
env:
- CC=aarch64-linux-android21-clang
- CXX=aarch64-linux-android21-clang++
- goos: android
goarch: 386
env:
- CC=i686-linux-android21-clang
- CXX=i686-linux-android21-clang++
- goos: android
goarch: amd64
goamd64: v1
env:
- CC=x86_64-linux-android21-clang
- CXX=x86_64-linux-android21-clang++
targets:
- android_arm_7
- android_arm64
- android_386
- android_amd64
upx:
- enabled: true
ids:
- compressed
- compressed-mips
- compressed-android
compress: best
lzma: true
archives:
- &template
id: archive
builds:
- main
- mips
- android
formats:
- tar.gz
format: tar.gz
format_overrides:
- goos: windows
formats:
- zip
format: zip
wrap_in_directory: true
files:
- LICENSE
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ if and .Mips (not (eq .Mips "hardfloat")) }}-{{ .Mips }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
- id: archive-naive-purego-linux-amd64
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ if and .Mips (not (eq .Mips "hardfloat")) }}_{{ .Mips }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
- id: archive-legacy
<<: *template
builds:
- naive-purego-linux-amd64
files:
- LICENSE
- src: dist/naive-purego-linux-amd64_*/libcronet*
strip_parent: true
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-purego'
- id: archive-naive-purego-linux-arm64
<<: *template
- legacy
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-legacy'
nfpms:
- id: package
package_name: sing-box
file_name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ if and .Mips (not (eq .Mips "hardfloat")) }}_{{ .Mips }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
builds:
- naive-purego-linux-arm64
files:
- LICENSE
- src: dist/naive-purego-linux-arm64_*/libcronet*
strip_parent: true
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-purego'
- id: archive-naive-purego-windows-amd64
<<: *template
builds:
- naive-purego-windows-amd64
files:
- LICENSE
- src: dist/naive-purego-windows-amd64_*/libcronet*
strip_parent: true
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-purego'
- id: archive-naive-purego-windows-arm64
<<: *template
builds:
- naive-purego-windows-arm64
files:
- LICENSE
- src: dist/naive-purego-windows-arm64_*/libcronet*
strip_parent: true
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}-purego'
- id: archive-naive-glibc
<<: *template
builds:
- naive-glibc
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ if and .Mips (not (eq .Mips "hardfloat")) }}-{{ .Mips }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}-glibc'
- id: archive-naive-musl
<<: *template
builds:
- naive-musl
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ if and .Mips (not (eq .Mips "hardfloat")) }}-{{ .Mips }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}-musl'
- id: archive-compressed
<<: *template
builds:
- compressed
- compressed-mips
- compressed-android
name_template: '{{ .ProjectName }}-{{ .Version }}-{{ .Os }}-{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ if and .Mips (not (eq .Mips "hardfloat")) }}-{{ .Mips }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}-compressed'
- main
homepage: https://sing-box.sagernet.org/
maintainer: nekohasekai <contact-git@sekai.icu>
description: The universal proxy platform.
license: GPLv3 or later
formats:
- deb
- rpm
- archlinux
# - apk
# - ipk
priority: extra
contents:
- src: release/config/config.json
dst: /etc/sing-box/config.json
type: config
- src: release/config/sing-box.service
dst: /usr/lib/systemd/system/sing-box.service
- src: release/config/sing-box@.service
dst: /usr/lib/systemd/system/sing-box@.service
- src: release/completions/sing-box.bash
dst: /usr/share/bash-completion/completions/sing-box.bash
- src: release/completions/sing-box.fish
dst: /usr/share/fish/vendor_completions.d/sing-box.fish
- src: release/completions/sing-box.zsh
dst: /usr/share/zsh/site-functions/_sing-box
- src: LICENSE
dst: /usr/share/licenses/sing-box/LICENSE
deb:
signature:
key_file: "{{ .Env.NFPM_KEY_PATH }}"
fields:
Bugs: https://github.com/SagerNet/sing-box/issues
rpm:
signature:
key_file: "{{ .Env.NFPM_KEY_PATH }}"
overrides:
apk:
contents:
- src: release/config/config.json
dst: /etc/sing-box/config.json
type: config
- src: release/config/sing-box.initd
dst: /etc/init.d/sing-box
- src: release/completions/sing-box.bash
dst: /usr/share/bash-completion/completions/sing-box.bash
- src: release/completions/sing-box.fish
dst: /usr/share/fish/vendor_completions.d/sing-box.fish
- src: release/completions/sing-box.zsh
dst: /usr/share/zsh/site-functions/_sing-box
- src: LICENSE
dst: /usr/share/licenses/sing-box/LICENSE
ipk:
contents:
- src: release/config/config.json
dst: /etc/sing-box/config.json
type: config
- src: release/config/openwrt.init
dst: /etc/init.d/sing-box
- src: release/config/openwrt.conf
dst: /etc/config/sing-box
source:
enabled: false
name_template: '{{ .ProjectName }}-{{ .Version }}.source'
@@ -482,19 +192,14 @@ signs:
- artifacts: checksum
release:
github:
owner: shtorm-7
name: sing-box-extended
owner: SagerNet
name: sing-box
draft: true
prerelease: auto
mode: replace
ids:
- archive
- archive-naive-glibc
- archive-naive-musl
- archive-naive-purego-linux-amd64
- archive-naive-purego-linux-arm64
- archive-naive-purego-windows-amd64
- archive-naive-purego-windows-arm64
- archive-compressed
- package
skip_upload: true
partial:
by: target
-24
View File
@@ -1,24 +0,0 @@
# Support the project
If you want to support the project, you can donate to the following addresses.
### TRX (Tron)
```
TSWU6VUZ4FcUghYDmbbhK15gRVvhvBgW3F
```
### TON
```
UQAyD2UuT5kCP6lZQlhFL0hyNibDXNE4nIo_RSLVSYAtD7N1
```
### Solana
```
CJu8ickwRCwNE71uVFjYf1UveyCkRp9Xo44rhPcQpeFL
```
### Bitcoin
```
bc1qqx97p8k4dchqkyd47s4vf74hrqdfnmhqvcja7x
```
### Ethereum
```
0xAcc5919C22F2B3fAa0ec7E8BaD142da5B375FBF6
```
+9 -8
View File
@@ -1,5 +1,5 @@
FROM --platform=$BUILDPLATFORM golang:1.26-alpine AS builder
LABEL maintainer="shtorm-7"
FROM --platform=$BUILDPLATFORM golang:1.23-alpine AS builder
LABEL maintainer="nekohasekai <contact-git@sekai.icu>"
COPY . /go/src/github.com/sagernet/sing-box
WORKDIR /go/src/github.com/sagernet/sing-box
ARG TARGETOS TARGETARCH
@@ -12,15 +12,16 @@ RUN set -ex \
&& apk add git build-base \
&& export COMMIT=$(git rev-parse --short HEAD) \
&& export VERSION=$(go run ./cmd/internal/read_tag) \
&& export TAGS=$(cat release/DEFAULT_BUILD_TAGS_OTHERS) \
&& export LDFLAGS_SHARED=$(cat release/LDFLAGS) \
&& go build -v -trimpath -tags "$TAGS" \
&& go build -v -trimpath -tags \
"with_gvisor,with_quic,with_dhcp,with_wireguard,with_ech,with_utls,with_reality_server,with_acme,with_clash_api" \
-o /go/bin/sing-box \
-ldflags "-X \"github.com/sagernet/sing-box/constant.Version=$VERSION\" $LDFLAGS_SHARED -s -w -buildid=" \
-ldflags "-X \"github.com/sagernet/sing-box/constant.Version=$VERSION\" -s -w -buildid=" \
./cmd/sing-box
FROM --platform=$TARGETPLATFORM alpine AS dist
LABEL maintainer="shtorm-7"
LABEL maintainer="nekohasekai <contact-git@sekai.icu>"
RUN set -ex \
&& apk add --no-cache --upgrade bash tzdata ca-certificates nftables
&& apk upgrade \
&& apk add bash tzdata ca-certificates nftables \
&& rm -rf /var/cache/apk/*
COPY --from=builder /go/bin/sing-box /usr/local/bin/sing-box
ENTRYPOINT ["sing-box"]
-14
View File
@@ -1,14 +0,0 @@
ARG BASE_IMAGE=alpine
FROM ${BASE_IMAGE}
ARG TARGETARCH
ARG TARGETVARIANT
LABEL maintainer="nekohasekai <contact-git@sekai.icu>"
RUN set -ex \
&& if command -v apk > /dev/null; then \
apk add --no-cache --upgrade bash tzdata ca-certificates nftables; \
else \
apt-get update && apt-get install -y --no-install-recommends bash tzdata ca-certificates nftables \
&& rm -rf /var/lib/apt/lists/*; \
fi
COPY sing-box-${TARGETARCH}${TARGETVARIANT} /usr/local/bin/sing-box
ENTRYPOINT ["sing-box"]
+81 -150
View File
@@ -1,81 +1,56 @@
NAME = sing-box
COMMIT = $(shell git rev-parse --short HEAD)
TAGS ?= $(shell cat release/DEFAULT_BUILD_TAGS_OTHERS)
TAGS_GO120 = with_gvisor,with_dhcp,with_wireguard,with_reality_server,with_clash_api,with_quic,with_utls
TAGS_GO121 = with_ech
TAGS ?= $(TAGS_GO118),$(TAGS_GO120),$(TAGS_GO121)
TAGS_TEST ?= with_gvisor,with_quic,with_wireguard,with_grpc,with_ech,with_utls,with_reality_server
GOHOSTOS = $(shell go env GOHOSTOS)
GOHOSTARCH = $(shell go env GOHOSTARCH)
VERSION=$(shell CGO_ENABLED=0 GOOS=$(GOHOSTOS) GOARCH=$(GOHOSTARCH) go run github.com/sagernet/sing-box/cmd/internal/read_tag@latest)
VERSION=$(shell CGO_ENABLED=0 GOOS=$(GOHOSTOS) GOARCH=$(GOHOSTARCH) go run ./cmd/internal/read_tag)
LDFLAGS_SHARED = $(shell cat release/LDFLAGS)
PARAMS = -v -trimpath -ldflags "-X 'github.com/sagernet/sing-box/constant.Version=$(VERSION)' $(LDFLAGS_SHARED) -s -w -buildid="
MAIN_PARAMS = $(PARAMS) -tags "$(TAGS)"
PARAMS = -v -trimpath -ldflags "-X 'github.com/sagernet/sing-box/constant.Version=$(VERSION)' -s -w -buildid="
MAIN_PARAMS = $(PARAMS) -tags $(TAGS)
MAIN = ./cmd/sing-box
PREFIX ?= $(shell go env GOPATH)
SING_FFI ?= sing-ffi
LIBBOX_FFI_CONFIG ?= ./experimental/libbox/ffi.json
ADMIN_PANEL_DIR = service/admin_panel
ADMIN_PANEL_WEB = $(ADMIN_PANEL_DIR)/web
ADMIN_PANEL_DIST = $(ADMIN_PANEL_DIR)/dist
ADMIN_PANEL_TAGS = $(TAGS),with_admin_panel
DOCKER_IMAGE ?= shtorm7/sing-box-extended
DOCKER_PLATFORMS ?= linux/amd64,linux/arm64
CRONET_GO_PATH ?= $(shell pwd)/cronet-go
.PHONY: test release docs build
build:
export GOTOOLCHAIN=local && \
go build $(MAIN_PARAMS) $(MAIN)
build_admin_panel:
cd $(ADMIN_PANEL_WEB) && \
npm install --no-fund --no-audit && \
npm run build
go run ./cmd/internal/admin_panel_pack \
-dir $(ADMIN_PANEL_DIST)
build_naive:
cd $(CRONET_GO_PATH) && \
for arch in amd64 arm64 386 arm mipsle mips64le riscv64 loong64; do \
go run ./cmd/build-naive --target=linux/$$arch download-toolchain; \
done && \
for arch in amd64 arm64 386 arm mipsle riscv64 loong64; do \
go run ./cmd/build-naive --target=linux/$$arch --libc=musl download-toolchain; \
done
race:
export GOTOOLCHAIN=local && \
go build -race $(MAIN_PARAMS) $(MAIN)
ci_build_go120:
go build $(PARAMS) $(MAIN)
go build $(PARAMS) -tags "$(TAGS_GO120)" $(MAIN)
ci_build:
export GOTOOLCHAIN=local && \
go build $(PARAMS) $(MAIN) && \
go build $(PARAMS) $(MAIN)
go build $(MAIN_PARAMS) $(MAIN)
generate_completions:
go run -v --tags "$(TAGS),generate,generate_completions" $(MAIN)
go run -v --tags generate,generate_completions $(MAIN)
install:
go build -o $(PREFIX)/bin/$(NAME) $(MAIN_PARAMS) $(MAIN)
fmt:
@golangci-lint fmt
@gofumpt -l -w .
@gofmt -s -w .
@gci write --custom-order -s standard -s "prefix(github.com/sagernet/)" -s "default" .
fmt_docs:
go run ./cmd/internal/format_docs
fmt_install:
go install -v mvdan.cc/gofumpt@latest
go install -v github.com/daixiang0/gci@latest
lint:
GOOS=linux golangci-lint run ./...
GOOS=android golangci-lint run ./...
GOOS=windows golangci-lint run ./...
GOOS=darwin golangci-lint run ./...
# GOOS=freebsd golangci-lint run ./...
GOOS=freebsd golangci-lint run ./...
lint_install:
go install -v github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
go install -v github.com/golangci/golangci-lint/cmd/golangci-lint@latest
proto:
@go run ./cmd/internal/protogen
@@ -86,17 +61,17 @@ proto_install:
go install -v google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install -v google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
update_certificates:
go run ./cmd/internal/update_certificates
release: build_admin_panel build_naive
CRONET_GO_PATH=$(CRONET_GO_PATH) go run ./cmd/internal/build goreleaser release --skip=validate --clean -p 3 --skip publish
release:
go run ./cmd/internal/build goreleaser release --clean --skip publish
mkdir dist/release
mv dist/*.tar.gz \
dist/*.zip \
dist/*.deb \
dist/*.rpm \
dist/*_amd64.pkg.tar.zst \
dist/*_arm64.pkg.tar.zst \
dist/release
ghr --replace --draft --prerelease -p 5 "v${VERSION}" dist/release
./codeberg-release.sh --replace --draft --prerelease -p 5 "v${VERSION}" dist/release
rm -r dist/release
release_repo:
@@ -105,26 +80,17 @@ release_repo:
release_install:
go install -v github.com/tcnksm/ghr@latest
release_docker:
sudo docker buildx build \
--platform $(DOCKER_PLATFORMS) \
-t $(DOCKER_IMAGE):latest \
-t $(DOCKER_IMAGE):$(VERSION) \
--push \
--network=host \
.
update_android_version:
go run ./cmd/internal/update_android_version
build_android:
cd ../sing-box-for-android && ./gradlew :app:clean :app:assembleOtherRelease && ./gradlew --stop
cd ../sing-box-for-android && ./gradlew :app:clean :app:assemblePlayRelease :app:assembleOtherRelease && ./gradlew --stop
upload_android:
mkdir -p dist/release_android
cp ../sing-box-for-android/app/build/outputs/apk/other/release/*.apk dist/release_android
cp ../sing-box-for-android/app/build/outputs/apk/play/release/*.apk dist/release_android
cp ../sing-box-for-android/app/build/outputs/apk/other/release/*-universal.apk dist/release_android
ghr --replace --draft --prerelease -p 5 "v${VERSION}" dist/release_android
./codeberg-release.sh --replace --draft --prerelease -p 5 "v${VERSION}" dist/release_android
rm -rf dist/release_android
release_android: lib_android update_android_version build_android upload_android
@@ -138,28 +104,18 @@ build_ios:
cd ../sing-box-for-apple && \
rm -rf build/SFI.xcarchive && \
xcodebuild clean -scheme SFI && \
xcodebuild archive -scheme SFI -configuration Release -destination 'generic/platform=iOS' -archivePath build/SFI.xcarchive -allowProvisioningUpdates | xcbeautify | grep -A 10 -e "Archive Succeeded" -e "ARCHIVE FAILED" -e "❌"
xcodebuild archive -scheme SFI -configuration Release -destination 'generic/platform=iOS' -archivePath build/SFI.xcarchive -allowProvisioningUpdates
upload_ios_app_store:
cd ../sing-box-for-apple && \
xcodebuild -exportArchive -archivePath build/SFI.xcarchive -exportOptionsPlist SFI/Upload.plist -allowProvisioningUpdates
export_ios_ipa:
cd ../sing-box-for-apple && \
xcodebuild -exportArchive -archivePath build/SFI.xcarchive -exportOptionsPlist SFI/Export.plist -allowProvisioningUpdates -exportPath build/SFI && \
cp build/SFI/sing-box.ipa dist/SFI.ipa
upload_ios_ipa:
cd dist && \
cp SFI.ipa "SFI-${VERSION}.ipa" && \
ghr --replace --draft --prerelease "v${VERSION}" "SFI-${VERSION}.ipa"
release_ios: build_ios upload_ios_app_store
build_macos:
cd ../sing-box-for-apple && \
rm -rf build/SFM.xcarchive && \
xcodebuild archive -scheme SFM -configuration Release -archivePath build/SFM.xcarchive -allowProvisioningUpdates | xcbeautify | grep -A 10 -e "Archive Succeeded" -e "ARCHIVE FAILED" -e "❌"
xcodebuild archive -scheme SFM -configuration Release -archivePath build/SFM.xcarchive -allowProvisioningUpdates
upload_macos_app_store:
cd ../sing-box-for-apple && \
@@ -168,82 +124,59 @@ upload_macos_app_store:
release_macos: build_macos upload_macos_app_store
build_macos_standalone:
$(MAKE) -C ../sing-box-for-apple archive_macos_standalone
cd ../sing-box-for-apple && \
rm -rf build/SFM.System.xcarchive && \
xcodebuild archive -scheme SFM.System -configuration Release -archivePath build/SFM.System.xcarchive -allowProvisioningUpdates
build_macos_dmg:
$(MAKE) -C ../sing-box-for-apple build_macos_dmg
build_macos_pkg:
$(MAKE) -C ../sing-box-for-apple build_macos_pkg
rm -rf dist/SFM
mkdir -p dist/SFM
cd ../sing-box-for-apple && \
rm -rf build/SFM.System && \
rm -rf build/SFM.dmg && \
xcodebuild -exportArchive \
-archivePath "build/SFM.System.xcarchive" \
-exportOptionsPlist SFM.System/Export.plist -allowProvisioningUpdates \
-exportPath "build/SFM.System" && \
create-dmg \
--volname "sing-box" \
--volicon "build/SFM.System/SFM.app/Contents/Resources/AppIcon.icns" \
--icon "SFM.app" 0 0 \
--hide-extension "SFM.app" \
--app-drop-link 0 0 \
--skip-jenkins \
"../sing-box/dist/SFM/SFM.dmg" "build/SFM.System/SFM.app"
notarize_macos_dmg:
$(MAKE) -C ../sing-box-for-apple notarize_macos_dmg
notarize_macos_pkg:
$(MAKE) -C ../sing-box-for-apple notarize_macos_pkg
xcrun notarytool submit "dist/SFM/SFM.dmg" --wait \
--keychain-profile "notarytool-password" \
--no-s3-acceleration
upload_macos_dmg:
mkdir -p dist/SFM
cp ../sing-box-for-apple/build/SFM-Apple.dmg "dist/SFM/SFM-${VERSION}-Apple.dmg"
cp ../sing-box-for-apple/build/SFM-Intel.dmg "dist/SFM/SFM-${VERSION}-Intel.dmg"
cp ../sing-box-for-apple/build/SFM-Universal.dmg "dist/SFM/SFM-${VERSION}-Universal.dmg"
ghr --replace --draft --prerelease "v${VERSION}" "dist/SFM/SFM-${VERSION}-Apple.dmg"
ghr --replace --draft --prerelease "v${VERSION}" "dist/SFM/SFM-${VERSION}-Intel.dmg"
ghr --replace --draft --prerelease "v${VERSION}" "dist/SFM/SFM-${VERSION}-Universal.dmg"
upload_macos_pkg:
mkdir -p dist/SFM
cp ../sing-box-for-apple/build/SFM-Apple.pkg "dist/SFM/SFM-${VERSION}-Apple.pkg"
cp ../sing-box-for-apple/build/SFM-Intel.pkg "dist/SFM/SFM-${VERSION}-Intel.pkg"
cp ../sing-box-for-apple/build/SFM-Universal.pkg "dist/SFM/SFM-${VERSION}-Universal.pkg"
ghr --replace --draft --prerelease "v${VERSION}" "dist/SFM/SFM-${VERSION}-Apple.pkg"
ghr --replace --draft --prerelease "v${VERSION}" "dist/SFM/SFM-${VERSION}-Intel.pkg"
ghr --replace --draft --prerelease "v${VERSION}" "dist/SFM/SFM-${VERSION}-Universal.pkg"
replace_macos_pkg:
mkdir -p dist/SFM
cp ../sing-box-for-apple/build/SFM-Apple.pkg "dist/SFM/SFM-${VERSION}-Apple.pkg"
cp ../sing-box-for-apple/build/SFM-Intel.pkg "dist/SFM/SFM-${VERSION}-Intel.pkg"
cp ../sing-box-for-apple/build/SFM-Universal.pkg "dist/SFM/SFM-${VERSION}-Universal.pkg"
ghr --replace "v${VERSION}" "dist/SFM/SFM-${VERSION}-Apple.pkg"
ghr --replace "v${VERSION}" "dist/SFM/SFM-${VERSION}-Intel.pkg"
ghr --replace "v${VERSION}" "dist/SFM/SFM-${VERSION}-Universal.pkg"
cd dist/SFM && \
cp SFM.dmg "SFM-${VERSION}-universal.dmg" && \
ghr --replace --draft --prerelease "v${VERSION}" "SFM-${VERSION}-universal.dmg"
upload_macos_dsyms:
mkdir -p dist/SFM
cd ../sing-box-for-apple/build/SFM.System-universal.xcarchive && zip -r SFM.dSYMs.zip dSYMs
cp ../sing-box-for-apple/build/SFM.System-universal.xcarchive/SFM.dSYMs.zip "dist/SFM/SFM-${VERSION}.dSYMs.zip"
ghr --replace --draft --prerelease "v${VERSION}" "dist/SFM/SFM-${VERSION}.dSYMs.zip"
pushd ../sing-box-for-apple/build/SFM.System.xcarchive && \
zip -r SFM.dSYMs.zip dSYMs && \
mv SFM.dSYMs.zip ../../../sing-box/dist/SFM && \
popd && \
cd dist/SFM && \
cp SFM.dSYMs.zip "SFM-${VERSION}-universal.dSYMs.zip" && \
ghr --replace --draft --prerelease "v${VERSION}" "SFM-${VERSION}-universal.dSYMs.zip"
replace_macos_dsyms:
mkdir -p dist/SFM
cd ../sing-box-for-apple/build/SFM.System-universal.xcarchive && zip -r SFM.dSYMs.zip dSYMs
cp ../sing-box-for-apple/build/SFM.System-universal.xcarchive/SFM.dSYMs.zip "dist/SFM/SFM-${VERSION}.dSYMs.zip"
ghr --replace "v${VERSION}" "dist/SFM/SFM-${VERSION}.dSYMs.zip"
release_macos_standalone: build_macos_pkg notarize_macos_pkg upload_macos_pkg upload_macos_dsyms
replace_macos_standalone: build_macos_pkg notarize_macos_pkg upload_macos_pkg upload_macos_dsyms
release_macos_standalone: build_macos_standalone build_macos_dmg notarize_macos_dmg upload_macos_dmg upload_macos_dsyms
build_tvos:
cd ../sing-box-for-apple && \
rm -rf build/SFT.xcarchive && \
xcodebuild archive -scheme SFT -configuration Release -archivePath build/SFT.xcarchive -allowProvisioningUpdates | xcbeautify | grep -A 10 -e "Archive Succeeded" -e "ARCHIVE FAILED" -e "❌"
xcodebuild archive -scheme SFT -configuration Release -archivePath build/SFT.xcarchive -allowProvisioningUpdates
upload_tvos_app_store:
cd ../sing-box-for-apple && \
xcodebuild -exportArchive -archivePath "build/SFT.xcarchive" -exportOptionsPlist SFI/Upload.plist -allowProvisioningUpdates
export_tvos_ipa:
cd ../sing-box-for-apple && \
xcodebuild -exportArchive -archivePath "build/SFT.xcarchive" -exportOptionsPlist SFI/Export.plist -allowProvisioningUpdates -exportPath build/SFT && \
cp build/SFT/sing-box.ipa dist/SFT.ipa
upload_tvos_ipa:
cd dist && \
cp SFT.ipa "SFT-${VERSION}.ipa" && \
ghr --replace --draft --prerelease "v${VERSION}" "SFT-${VERSION}.ipa"
release_tvos: build_tvos upload_tvos_app_store
update_apple_version:
@@ -252,12 +185,12 @@ update_apple_version:
update_macos_version:
MACOS_PROJECT_VERSION=$(shell go run -v ./cmd/internal/app_store_connect next_macos_project_version) go run ./cmd/internal/update_apple_version
release_apple: lib_apple update_apple_version release_ios release_macos release_tvos release_macos_standalone
release_apple: lib_ios update_apple_version release_ios release_macos release_tvos release_macos_standalone
release_apple_beta: update_apple_version release_ios release_macos release_tvos
publish_testflight:
go run -v ./cmd/internal/app_store_connect publish_testflight $(filter-out $@,$(MAKECMDGOALS))
go run -v ./cmd/internal/app_store_connect publish_testflight
prepare_app_store:
go run -v ./cmd/internal/app_store_connect prepare_app_store
@@ -280,21 +213,22 @@ test_stdio:
lib_android:
go run ./cmd/internal/build_libbox -target android
lib_android_debug:
go run ./cmd/internal/build_libbox -target android -debug
lib_apple:
go run ./cmd/internal/build_libbox -target apple
lib_windows:
$(SING_FFI) generate --config $(LIBBOX_FFI_CONFIG) --platform-type csharp
lib_ios:
go run ./cmd/internal/build_libbox -target apple -platform ios -debug
lib_android_new:
$(SING_FFI) generate --config $(LIBBOX_FFI_CONFIG) --platform-type android
lib_apple_new:
$(SING_FFI) generate --config $(LIBBOX_FFI_CONFIG) --platform-type apple
lib:
go run ./cmd/internal/build_libbox -target android
go run ./cmd/internal/build_libbox -target ios
lib_install:
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.12
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.12
go install -v github.com/sagernet/gomobile/cmd/gomobile@v0.1.4
go install -v github.com/sagernet/gomobile/cmd/gobind@v0.1.4
docs:
venv/bin/mkdocs serve
@@ -303,8 +237,8 @@ publish_docs:
venv/bin/mkdocs gh-deploy -m "Update" --force --ignore-version --no-history
docs_install:
python3 -m venv venv
source ./venv/bin/activate && pip install --force-reinstall mkdocs-material=="9.7.2" mkdocs-static-i18n=="1.2.*"
python -m venv venv
source ./venv/bin/activate && pip install --force-reinstall mkdocs-material=="9.*" mkdocs-static-i18n=="1.2.*"
clean:
rm -rf bin dist sing-box
@@ -313,7 +247,4 @@ clean:
update:
git fetch
git reset FETCH_HEAD --hard
git clean -fdx
%:
@:
git clean -fdx
+6 -88
View File
@@ -1,94 +1,12 @@
# sing-box-extended
# sing-box
[![license](https://img.shields.io/badge/license-GPLv3-blue.svg)](LICENSE)
[![go](https://img.shields.io/badge/go-1.26-00ADD8.svg)](go.mod)
[![codeberg](https://img.shields.io/badge/mirror-codeberg-2185D0.svg)](https://codeberg.org/shtorm-7/sing-box-extended)
The universal proxy platform.
Sing-box with extended features.
[![Packaging status](https://repology.org/badge/vertical-allrepos/sing-box.svg)](https://repology.org/project/sing-box/versions)
## 🔥 Features
## Documentation
### Protocols
- **WARP** — Cloudflare WARP integration through WireGuard
- **MASQUE** — Cloudflare MASQUE proxy over QUIC / HTTP-2
- **MTProxy** — Telegram MTProxy server with FakeTLS and domain fronting
- **Mieru** — Secure, hard to classify, hard to probe network protocol
- **OpenVPN** — OpenVPN client with tls-auth, tls-crypt, and tls-crypt-v2 support
- **TrustTunnel** — AdGuard's obfuscated VPN protocol, indistinguishable from HTTPS traffic
- **Sudoku** — Traffic obfuscation protocol based on 4×4 Sudoku puzzles with low-entropy fingerprints
- **VPN** — Routed tunnel over any TCP sing-box protocol
- **Bond** — Link aggregation for increasing throughput
- **Fallback** — Outbound group with priority-based switching
- **Failover** — Automatic outbound switching with session recovery for high availability
### DNS
- **SDNS (DNSCrypt)** — Encrypted DNS queries for enhanced privacy
- **DNS Fallback** — Sequential / parallel queries across upstream resolvers
### Limiters
- **Bandwidth Limiter** — Upload / download / bidirectional rate limiting
- **Connection Limiter** — Concurrent connection control
- **Traffic Limiter** — Per-user traffic quotas
- **Rate Limiter** — Request rate limiting
### Encryption & Obfuscation
- **Amnezia 2.0** — WireGuard traffic obfuscation
- **VLESS encryption** — XRAY encryption for VLESS protocol
### Transports
- **mKCP** — Reliable UDP-based transport
- **XHTTP** — Modern XRAY transport
### Services
- **Admin Panel** — Web-based management interface
- **Manager** — Management service for configuring users, nodes, limiters
- **Manager API (HTTP/gRPC)** — HTTP and gRPC API for the Manager
- **Node Manager API** — Service for connecting nodes to remote manager
### Miscellaneous
- **Providers** — Outbound subscriptions from local files, inline lists, or remote URLs (sing-box JSON, Clash YAML, SIP008, share links)
- **Link Parser** — Outbound configured from a share link (VLESS, VMess, Shadowsocks, Trojan, Hysteria, Hysteria2, TUIC)
- **Extended WireGuard options** — Advanced configuration capabilities
- **Unified Delay** — Unified latency measurement
## 📚 Examples
Configuration examples are available here:
https://github.com/shtorm-7/sing-box-extended/tree/extended/examples
## Support the Project
If you want to support the project, you can donate to the following addresses.
#### Tribute
**[RUB Donate](https://web.tribute.tg/d/JxY)**
**[EUR Donate](https://web.tribute.tg/d/JxZ)**
**[USD Donate](https://web.tribute.tg/d/Jy1)**
#### TRX (Tron)
```
TSWU6VUZ4FcUghYDmbbhK15gRVvhvBgW3F
```
#### TON
```
UQAyD2UuT5kCP6lZQlhFL0hyNibDXNE4nIo_RSLVSYAtD7N1
```
#### Solana
```
CJu8ickwRCwNE71uVFjYf1UveyCkRp9Xo44rhPcQpeFL
```
#### Bitcoin
```
bc1qqx97p8k4dchqkyd47s4vf74hrqdfnmhqvcja7x
```
#### Ethereum
```
0xAcc5919C22F2B3fAa0ec7E8BaD142da5B375FBF6
```
https://sing-box.sagernet.org
## License
@@ -110,4 +28,4 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
In addition, no derivative work may use the name or imply association
with this application without prior consent.
```
```
-21
View File
@@ -1,21 +0,0 @@
package adapter
import (
"context"
"crypto/x509"
"github.com/sagernet/sing/service"
)
type CertificateStore interface {
LifecycleService
Pool() *x509.CertPool
}
func RootPoolFromContext(ctx context.Context) *x509.CertPool {
store := service.FromContext[CertificateStore](ctx)
if store == nil {
return nil
}
return store.Pool()
}
+104
View File
@@ -0,0 +1,104 @@
package adapter
import (
"context"
"net"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
type ConnectionRouter interface {
RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
}
func NewRouteHandler(
metadata InboundContext,
router ConnectionRouter,
logger logger.ContextLogger,
) UpstreamHandlerAdapter {
return &routeHandlerWrapper{
metadata: metadata,
router: router,
logger: logger,
}
}
func NewRouteContextHandler(
router ConnectionRouter,
logger logger.ContextLogger,
) UpstreamHandlerAdapter {
return &routeContextHandlerWrapper{
router: router,
logger: logger,
}
}
var _ UpstreamHandlerAdapter = (*routeHandlerWrapper)(nil)
type routeHandlerWrapper struct {
metadata InboundContext
router ConnectionRouter
logger logger.ContextLogger
}
func (w *routeHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
myMetadata := w.metadata
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RouteConnection(ctx, conn, myMetadata)
}
func (w *routeHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
myMetadata := w.metadata
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RoutePacketConnection(ctx, conn, myMetadata)
}
func (w *routeHandlerWrapper) NewError(ctx context.Context, err error) {
w.logger.ErrorContext(ctx, err)
}
var _ UpstreamHandlerAdapter = (*routeContextHandlerWrapper)(nil)
type routeContextHandlerWrapper struct {
router ConnectionRouter
logger logger.ContextLogger
}
func (w *routeContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
myMetadata := ContextFrom(ctx)
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RouteConnection(ctx, conn, *myMetadata)
}
func (w *routeContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
myMetadata := ContextFrom(ctx)
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RoutePacketConnection(ctx, conn, *myMetadata)
}
func (w *routeContextHandlerWrapper) NewError(ctx context.Context, err error) {
w.logger.ErrorContext(ctx, err)
}
-18
View File
@@ -1,18 +0,0 @@
package adapter
import (
"context"
"net"
N "github.com/sagernet/sing/common/network"
)
type ConnectionManager interface {
Lifecycle
Count() int
CloseAll()
TrackConn(conn net.Conn) net.Conn
TrackPacketConn(conn net.PacketConn) net.PacketConn
NewConnection(ctx context.Context, this N.Dialer, conn net.Conn, metadata InboundContext, onClose N.CloseHandlerFunc)
NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn, metadata InboundContext, onClose N.CloseHandlerFunc)
}
-95
View File
@@ -1,95 +0,0 @@
package adapter
import (
"context"
"net/netip"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
"github.com/sagernet/sing/service"
"github.com/miekg/dns"
)
type DNSRouter interface {
Lifecycle
Exchange(ctx context.Context, message *dns.Msg, options DNSQueryOptions) (*dns.Msg, error)
Lookup(ctx context.Context, domain string, options DNSQueryOptions) ([]netip.Addr, error)
ClearCache()
LookupReverseMapping(ip netip.Addr) (string, bool)
ResetNetwork()
}
type DNSClient interface {
Start()
Exchange(ctx context.Context, transport DNSTransport, message *dns.Msg, options DNSQueryOptions, responseChecker func(responseAddrs []netip.Addr) bool) (*dns.Msg, error)
Lookup(ctx context.Context, transport DNSTransport, domain string, options DNSQueryOptions, responseChecker func(responseAddrs []netip.Addr) bool) ([]netip.Addr, error)
ClearCache()
}
type DNSQueryOptions struct {
Transport DNSTransport
Strategy C.DomainStrategy
LookupStrategy C.DomainStrategy
DisableCache bool
RewriteTTL *uint32
ClientSubnet netip.Prefix
}
func DNSQueryOptionsFrom(ctx context.Context, options *option.DomainResolveOptions) (*DNSQueryOptions, error) {
if options == nil {
return &DNSQueryOptions{}, nil
}
transportManager := service.FromContext[DNSTransportManager](ctx)
transport, loaded := transportManager.Transport(options.Server)
if !loaded {
return nil, E.New("domain resolver not found: " + options.Server)
}
return &DNSQueryOptions{
Transport: transport,
Strategy: C.DomainStrategy(options.Strategy),
DisableCache: options.DisableCache,
RewriteTTL: options.RewriteTTL,
ClientSubnet: options.ClientSubnet.Build(netip.Prefix{}),
}, nil
}
type RDRCStore interface {
LoadRDRC(transportName string, qName string, qType uint16) (rejected bool)
SaveRDRC(transportName string, qName string, qType uint16) error
SaveRDRCAsync(transportName string, qName string, qType uint16, logger logger.Logger)
}
type DNSTransport interface {
Lifecycle
Type() string
Tag() string
Dependencies() []string
// Reset closes the transport's existing connections so later requests use fresh connections.
// Exchanges that are currently using those connections may fail.
Reset()
Exchange(ctx context.Context, message *dns.Msg) (*dns.Msg, error)
}
type LegacyDNSTransport interface {
LegacyStrategy() C.DomainStrategy
LegacyClientSubnet() netip.Prefix
}
type DNSTransportRegistry interface {
option.DNSTransportOptionsRegistry
CreateDNSTransport(ctx context.Context, logger log.ContextLogger, tag string, transportType string, options any) (DNSTransport, error)
}
type DNSTransportManager interface {
Lifecycle
Transports() []DNSTransport
Transport(tag string) (DNSTransport, bool)
Default() DNSTransport
FakeIP() FakeIPTransport
Remove(tag string) error
Create(ctx context.Context, logger log.ContextLogger, tag string, outboundType string, options any) error
}
-28
View File
@@ -1,28 +0,0 @@
package adapter
import (
"context"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
)
type Endpoint interface {
Lifecycle
Type() string
Tag() string
Outbound
}
type EndpointRegistry interface {
option.EndpointOptionsRegistry
Create(ctx context.Context, router Router, logger log.ContextLogger, tag string, endpointType string, options any) (Endpoint, error)
}
type EndpointManager interface {
Lifecycle
Endpoints() []Endpoint
Get(tag string) (Endpoint, bool)
Remove(tag string) error
Create(ctx context.Context, router Router, logger log.ContextLogger, tag string, endpointType string, options any) error
}
-43
View File
@@ -1,43 +0,0 @@
package endpoint
import "github.com/sagernet/sing-box/option"
type Adapter struct {
endpointType string
endpointTag string
network []string
dependencies []string
}
func NewAdapter(endpointType string, endpointTag string, network []string, dependencies []string) Adapter {
return Adapter{
endpointType: endpointType,
endpointTag: endpointTag,
network: network,
dependencies: dependencies,
}
}
func NewAdapterWithDialerOptions(endpointType string, endpointTag string, network []string, dialOptions option.DialerOptions) Adapter {
var dependencies []string
if dialOptions.Detour != "" {
dependencies = []string{dialOptions.Detour}
}
return NewAdapter(endpointType, endpointTag, network, dependencies)
}
func (a *Adapter) Type() string {
return a.endpointType
}
func (a *Adapter) Tag() string {
return a.endpointTag
}
func (a *Adapter) Network() []string {
return a.network
}
func (a *Adapter) Dependencies() []string {
return a.dependencies
}
-158
View File
@@ -1,158 +0,0 @@
package endpoint
import (
"context"
"os"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/taskmonitor"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
)
var _ adapter.EndpointManager = (*Manager)(nil)
type Manager struct {
logger log.ContextLogger
registry adapter.EndpointRegistry
access sync.Mutex
started bool
stage adapter.StartStage
endpoints []adapter.Endpoint
endpointByTag map[string]adapter.Endpoint
}
func NewManager(logger log.ContextLogger, registry adapter.EndpointRegistry) *Manager {
return &Manager{
logger: logger,
registry: registry,
endpointByTag: make(map[string]adapter.Endpoint),
}
}
func (m *Manager) Start(stage adapter.StartStage) error {
m.access.Lock()
if m.started && m.stage >= stage {
panic("already started")
}
m.started = true
m.stage = stage
if stage == adapter.StartStateStart {
// started with outbound manager
m.access.Unlock()
return nil
}
endpoints := m.endpoints
m.access.Unlock()
for _, endpoint := range endpoints {
name := "endpoint/" + endpoint.Type() + "[" + endpoint.Tag() + "]"
done := adapter.LogElapsed(m.logger, stage, " ", name)
err := adapter.LegacyStart(endpoint, stage)
done()
if err != nil {
return E.Cause(err, stage, " ", name)
}
}
return nil
}
func (m *Manager) Close() error {
m.access.Lock()
defer m.access.Unlock()
if !m.started {
return nil
}
m.started = false
endpoints := m.endpoints
m.endpoints = nil
monitor := taskmonitor.New(m.logger, C.StopTimeout)
var err error
for _, endpoint := range endpoints {
name := "endpoint/" + endpoint.Type() + "[" + endpoint.Tag() + "]"
done := adapter.LogElapsed(m.logger, "close ", name)
monitor.Start("close ", name)
err = E.Append(err, endpoint.Close(), func(err error) error {
return E.Cause(err, "close ", name)
})
monitor.Finish()
done()
}
return nil
}
func (m *Manager) Endpoints() []adapter.Endpoint {
m.access.Lock()
defer m.access.Unlock()
return m.endpoints
}
func (m *Manager) Get(tag string) (adapter.Endpoint, bool) {
m.access.Lock()
defer m.access.Unlock()
endpoint, found := m.endpointByTag[tag]
return endpoint, found
}
func (m *Manager) Remove(tag string) error {
m.access.Lock()
endpoint, found := m.endpointByTag[tag]
if !found {
m.access.Unlock()
return os.ErrInvalid
}
delete(m.endpointByTag, tag)
index := common.Index(m.endpoints, func(it adapter.Endpoint) bool {
return it == endpoint
})
if index == -1 {
panic("invalid endpoint index")
}
m.endpoints = append(m.endpoints[:index], m.endpoints[index+1:]...)
started := m.started
m.access.Unlock()
if started {
return endpoint.Close()
}
return nil
}
func (m *Manager) Create(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, outboundType string, options any) error {
endpoint, err := m.registry.Create(ctx, router, logger, tag, outboundType, options)
if err != nil {
return err
}
m.access.Lock()
defer m.access.Unlock()
if m.started {
name := "endpoint/" + endpoint.Type() + "[" + endpoint.Tag() + "]"
for _, stage := range adapter.ListStartStages {
done := adapter.LogElapsed(m.logger, stage, " ", name)
err = adapter.LegacyStart(endpoint, stage)
done()
if err != nil {
return E.Cause(err, stage, " ", name)
}
}
}
if existsEndpoint, loaded := m.endpointByTag[tag]; loaded {
if m.started {
err = existsEndpoint.Close()
if err != nil {
return E.Cause(err, "close endpoint/", existsEndpoint.Type(), "[", existsEndpoint.Tag(), "]")
}
}
existsIndex := common.Index(m.endpoints, func(it adapter.Endpoint) bool {
return it == existsEndpoint
})
if existsIndex == -1 {
panic("invalid endpoint index")
}
m.endpoints = append(m.endpoints[:existsIndex], m.endpoints[existsIndex+1:]...)
}
m.endpoints = append(m.endpoints, endpoint)
m.endpointByTag[tag] = endpoint
return nil
}
-72
View File
@@ -1,72 +0,0 @@
package endpoint
import (
"context"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
)
type ConstructorFunc[T any] func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options T) (adapter.Endpoint, error)
func Register[Options any](registry *Registry, outboundType string, constructor ConstructorFunc[Options]) {
registry.register(outboundType, func() any {
return new(Options)
}, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, rawOptions any) (adapter.Endpoint, error) {
var options *Options
if rawOptions != nil {
options = rawOptions.(*Options)
}
return constructor(ctx, router, logger, tag, common.PtrValueOrDefault(options))
})
}
var _ adapter.EndpointRegistry = (*Registry)(nil)
type (
optionsConstructorFunc func() any
constructorFunc func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options any) (adapter.Endpoint, error)
)
type Registry struct {
access sync.Mutex
optionsType map[string]optionsConstructorFunc
constructor map[string]constructorFunc
}
func NewRegistry() *Registry {
return &Registry{
optionsType: make(map[string]optionsConstructorFunc),
constructor: make(map[string]constructorFunc),
}
}
func (m *Registry) CreateOptions(outboundType string) (any, bool) {
m.access.Lock()
defer m.access.Unlock()
optionsConstructor, loaded := m.optionsType[outboundType]
if !loaded {
return nil, false
}
return optionsConstructor(), true
}
func (m *Registry) Create(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, outboundType string, options any) (adapter.Endpoint, error) {
m.access.Lock()
defer m.access.Unlock()
constructor, loaded := m.constructor[outboundType]
if !loaded {
return nil, E.New("outbound type not found: " + outboundType)
}
return constructor(ctx, router, logger, tag, options)
}
func (m *Registry) register(outboundType string, optionsConstructor optionsConstructorFunc, constructor constructorFunc) {
m.access.Lock()
defer m.access.Unlock()
m.optionsType[outboundType] = optionsConstructor
m.constructor[outboundType] = constructor
}
+35 -63
View File
@@ -4,51 +4,34 @@ import (
"bytes"
"context"
"encoding/binary"
"io"
"net"
"time"
"github.com/sagernet/sing/common/observable"
"github.com/sagernet/sing-box/common/urltest"
"github.com/sagernet/sing-dns"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/varbin"
)
type ClashServer interface {
LifecycleService
ConnectionTracker
Service
PreStarter
Mode() string
ModeList() []string
SetModeUpdateHook(hook *observable.Subscriber[struct{}])
HistoryStorage() URLTestHistoryStorage
}
type URLTestHistory struct {
Time time.Time `json:"time"`
Delay uint16 `json:"delay"`
}
type URLTestHistoryStorage interface {
SetHook(hook *observable.Subscriber[struct{}])
LoadURLTestHistory(tag string) *URLTestHistory
DeleteURLTestHistory(tag string)
StoreURLTestHistory(tag string, history *URLTestHistory)
Close() error
}
type V2RayServer interface {
LifecycleService
StatsService() ConnectionTracker
HistoryStorage() *urltest.HistoryStorage
RoutedConnection(ctx context.Context, conn net.Conn, metadata InboundContext, matchedRule Rule) (net.Conn, Tracker)
RoutedPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext, matchedRule Rule) (N.PacketConn, Tracker)
}
type CacheFile interface {
LifecycleService
Service
PreStarter
StoreFakeIP() bool
FakeIPStorage
StoreRDRC() bool
RDRCStore
StoreWARPConfig() bool
StoreMASQUEConfig() bool
dns.RDRCStore
LoadMode() string
StoreMode(mode string) error
@@ -56,33 +39,23 @@ type CacheFile interface {
StoreSelected(group string, selected string) error
LoadGroupExpand(group string) (isExpand bool, loaded bool)
StoreGroupExpand(group string, expand bool) error
LoadRuleSet(tag string) *SavedBinary
SaveRuleSet(tag string, set *SavedBinary) error
LoadWARPConfig(tag string) *SavedBinary
SaveWARPConfig(tag string, set *SavedBinary) error
LoadMASQUEConfig(tag string) *SavedBinary
SaveMASQUEConfig(tag string, set *SavedBinary) error
LoadSubscription(tag string) *SavedBinary
SaveSubscription(tag string, sub *SavedBinary) error
LoadRuleSet(tag string) *SavedRuleSet
SaveRuleSet(tag string, set *SavedRuleSet) error
}
type SavedBinary struct {
type SavedRuleSet struct {
Content []byte
LastUpdated time.Time
LastEtag string
}
func (s *SavedBinary) MarshalBinary() ([]byte, error) {
func (s *SavedRuleSet) MarshalBinary() ([]byte, error) {
var buffer bytes.Buffer
err := binary.Write(&buffer, binary.BigEndian, uint8(1))
if err != nil {
return nil, err
}
_, err = varbin.WriteUvarint(&buffer, uint64(len(s.Content)))
if err != nil {
return nil, err
}
_, err = buffer.Write(s.Content)
err = varbin.Write(&buffer, binary.BigEndian, s.Content)
if err != nil {
return nil, err
}
@@ -90,30 +63,21 @@ func (s *SavedBinary) MarshalBinary() ([]byte, error) {
if err != nil {
return nil, err
}
_, err = varbin.WriteUvarint(&buffer, uint64(len(s.LastEtag)))
if err != nil {
return nil, err
}
_, err = buffer.WriteString(s.LastEtag)
err = varbin.Write(&buffer, binary.BigEndian, s.LastEtag)
if err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
func (s *SavedBinary) UnmarshalBinary(data []byte) error {
func (s *SavedRuleSet) UnmarshalBinary(data []byte) error {
reader := bytes.NewReader(data)
var version uint8
err := binary.Read(reader, binary.BigEndian, &version)
if err != nil {
return err
}
contentLength, err := binary.ReadUvarint(reader)
if err != nil {
return err
}
s.Content = make([]byte, contentLength)
_, err = io.ReadFull(reader, s.Content)
err = varbin.Read(reader, binary.BigEndian, &s.Content)
if err != nil {
return err
}
@@ -123,19 +87,17 @@ func (s *SavedBinary) UnmarshalBinary(data []byte) error {
return err
}
s.LastUpdated = time.Unix(lastUpdated, 0)
etagLength, err := binary.ReadUvarint(reader)
err = varbin.Read(reader, binary.BigEndian, &s.LastEtag)
if err != nil {
return err
}
etagBytes := make([]byte, etagLength)
_, err = io.ReadFull(reader, etagBytes)
if err != nil {
return err
}
s.LastEtag = string(etagBytes)
return nil
}
type Tracker interface {
Leave()
}
type OutboundGroup interface {
Outbound
Now() string
@@ -153,3 +115,13 @@ func OutboundTag(detour Outbound) string {
}
return detour.Tag()
}
type V2RayServer interface {
Service
StatsService() V2RayStatsService
}
type V2RayStatsService interface {
RoutedConnection(inbound string, outbound string, user string, conn net.Conn) net.Conn
RoutedPacketConnection(inbound string, outbound string, user string, conn N.PacketConn) N.PacketConn
}
+3 -2
View File
@@ -3,11 +3,12 @@ package adapter
import (
"net/netip"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing/common/logger"
)
type FakeIPStore interface {
SimpleLifecycle
Service
Contains(address netip.Addr) bool
Create(domain string, isIPv6 bool) (netip.Addr, error)
Lookup(address netip.Addr) (string, bool)
@@ -26,6 +27,6 @@ type FakeIPStorage interface {
}
type FakeIPTransport interface {
DNSTransport
dns.Transport
Store() FakeIPStore
}
-29
View File
@@ -6,56 +6,27 @@ import (
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
// Deprecated
type ConnectionHandler interface {
NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
}
type ConnectionHandlerEx interface {
NewConnectionEx(ctx context.Context, conn net.Conn, metadata InboundContext, onClose N.CloseHandlerFunc)
}
// Deprecated: use PacketHandlerEx instead
type PacketHandler interface {
NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, metadata InboundContext) error
}
type PacketHandlerEx interface {
NewPacketEx(buffer *buf.Buffer, source M.Socksaddr)
}
// Deprecated: use OOBPacketHandlerEx instead
type OOBPacketHandler interface {
NewPacket(ctx context.Context, conn N.PacketConn, buffer *buf.Buffer, oob []byte, metadata InboundContext) error
}
type OOBPacketHandlerEx interface {
NewPacketEx(buffer *buf.Buffer, oob []byte, source M.Socksaddr)
}
// Deprecated
type PacketConnectionHandler interface {
NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
}
type PacketConnectionHandlerEx interface {
NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata InboundContext, onClose N.CloseHandlerFunc)
}
// Deprecated: use TCPConnectionHandlerEx instead
//
//nolint:staticcheck
type UpstreamHandlerAdapter interface {
N.TCPConnectionHandler
N.UDPConnectionHandler
E.Handler
}
type UpstreamHandlerAdapterEx interface {
N.TCPConnectionHandlerEx
N.UDPConnectionHandlerEx
}
+15 -51
View File
@@ -2,43 +2,26 @@ package adapter
import (
"context"
"net"
"net/netip"
"time"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/common/process"
"github.com/sagernet/sing-box/option"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
type Inbound interface {
Lifecycle
Service
Type() string
Tag() string
}
type TCPInjectableInbound interface {
type InjectableInbound interface {
Inbound
ConnectionHandlerEx
}
type UDPInjectableInbound interface {
Inbound
PacketConnectionHandlerEx
}
type InboundRegistry interface {
option.InboundOptionsRegistry
Create(ctx context.Context, router Router, logger log.ContextLogger, tag string, inboundType string, options any) (Inbound, error)
UnsafeCreate(ctx context.Context, router Router, logger log.ContextLogger, tag string, inboundType string, options any) (Inbound, error)
}
type InboundManager interface {
Lifecycle
Inbounds() []Inbound
Get(tag string) (Inbound, bool)
Remove(tag string) error
Create(ctx context.Context, router Router, logger log.ContextLogger, tag string, inboundType string, options any) error
Network() []string
NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
}
type InboundContext struct {
@@ -48,7 +31,6 @@ type InboundContext struct {
Network string
Source M.Socksaddr
Destination M.Socksaddr
Gateway *netip.Addr
User string
Outbound string
@@ -58,32 +40,17 @@ type InboundContext struct {
Domain string
Client string
SniffContext any
SnifferNames []string
SniffError error
// cache
// Deprecated: implement in rule action
InboundDetour string
LastInbound string
OriginDestination M.Socksaddr
RouteOriginalDestination M.Socksaddr
UDPDisableDomainUnmapping bool
UDPConnect bool
UDPTimeout time.Duration
TLSFragment bool
TLSFragmentFallbackDelay time.Duration
TLSRecordFragment bool
NetworkStrategy *C.NetworkStrategy
NetworkType []C.InterfaceType
FallbackNetworkType []C.InterfaceType
FallbackDelay time.Duration
InboundDetour string
LastInbound string
OriginDestination M.Socksaddr
InboundOptions option.InboundOptions
DestinationAddresses []netip.Addr
SourceGeoIPCode string
GeoIPCode string
ProcessInfo *ConnectionOwner
ProcessInfo *process.Info
QueryType uint16
FakeIP bool
@@ -103,10 +70,6 @@ type InboundContext struct {
func (c *InboundContext) ResetRuleCache() {
c.IPCIDRMatchSource = false
c.IPCIDRAcceptEmpty = false
c.ResetRuleMatchCache()
}
func (c *InboundContext) ResetRuleMatchCache() {
c.SourceAddressMatch = false
c.SourcePortMatch = false
c.DestinationAddressMatch = false
@@ -138,7 +101,8 @@ func ExtendContext(ctx context.Context) (context.Context, *InboundContext) {
func OverrideContext(ctx context.Context) context.Context {
if metadata := ContextFrom(ctx); metadata != nil {
newMetadata := *metadata
var newMetadata InboundContext
newMetadata = *metadata
return WithContext(ctx, &newMetadata)
}
return ctx
-21
View File
@@ -1,21 +0,0 @@
package inbound
type Adapter struct {
inboundType string
inboundTag string
}
func NewAdapter(inboundType string, inboundTag string) Adapter {
return Adapter{
inboundType: inboundType,
inboundTag: inboundTag,
}
}
func (a *Adapter) Type() string {
return a.inboundType
}
func (a *Adapter) Tag() string {
return a.inboundTag
}
-158
View File
@@ -1,158 +0,0 @@
package inbound
import (
"context"
"os"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/taskmonitor"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
)
var _ adapter.InboundManager = (*Manager)(nil)
type Manager struct {
logger log.ContextLogger
registry adapter.InboundRegistry
endpoint adapter.EndpointManager
access sync.Mutex
started bool
stage adapter.StartStage
inbounds []adapter.Inbound
inboundByTag map[string]adapter.Inbound
}
func NewManager(logger log.ContextLogger, registry adapter.InboundRegistry, endpoint adapter.EndpointManager) *Manager {
return &Manager{
logger: logger,
registry: registry,
endpoint: endpoint,
inboundByTag: make(map[string]adapter.Inbound),
}
}
func (m *Manager) Start(stage adapter.StartStage) error {
m.access.Lock()
if m.started && m.stage >= stage {
panic("already started")
}
m.started = true
m.stage = stage
inbounds := m.inbounds
m.access.Unlock()
for _, inbound := range inbounds {
name := "inbound/" + inbound.Type() + "[" + inbound.Tag() + "]"
done := adapter.LogElapsed(m.logger, stage, " ", name)
err := adapter.LegacyStart(inbound, stage)
done()
if err != nil {
return E.Cause(err, stage, " ", name)
}
}
return nil
}
func (m *Manager) Close() error {
m.access.Lock()
defer m.access.Unlock()
if !m.started {
return nil
}
m.started = false
inbounds := m.inbounds
m.inbounds = nil
monitor := taskmonitor.New(m.logger, C.StopTimeout)
var err error
for _, inbound := range inbounds {
name := "inbound/" + inbound.Type() + "[" + inbound.Tag() + "]"
done := adapter.LogElapsed(m.logger, "close ", name)
monitor.Start("close ", name)
err = E.Append(err, inbound.Close(), func(err error) error {
return E.Cause(err, "close ", name)
})
monitor.Finish()
done()
}
return nil
}
func (m *Manager) Inbounds() []adapter.Inbound {
m.access.Lock()
defer m.access.Unlock()
return m.inbounds
}
func (m *Manager) Get(tag string) (adapter.Inbound, bool) {
m.access.Lock()
inbound, found := m.inboundByTag[tag]
m.access.Unlock()
if found {
return inbound, true
}
return m.endpoint.Get(tag)
}
func (m *Manager) Remove(tag string) error {
m.access.Lock()
inbound, found := m.inboundByTag[tag]
if !found {
m.access.Unlock()
return os.ErrInvalid
}
delete(m.inboundByTag, tag)
index := common.Index(m.inbounds, func(it adapter.Inbound) bool {
return it == inbound
})
if index == -1 {
panic("invalid inbound index")
}
m.inbounds = append(m.inbounds[:index], m.inbounds[index+1:]...)
started := m.started
m.access.Unlock()
if started {
return inbound.Close()
}
return nil
}
func (m *Manager) Create(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, outboundType string, options any) error {
inbound, err := m.registry.Create(ctx, router, logger, tag, outboundType, options)
if err != nil {
return err
}
m.access.Lock()
defer m.access.Unlock()
if m.started {
name := "inbound/" + inbound.Type() + "[" + inbound.Tag() + "]"
for _, stage := range adapter.ListStartStages {
done := adapter.LogElapsed(m.logger, stage, " ", name)
err = adapter.LegacyStart(inbound, stage)
done()
if err != nil {
return E.Cause(err, stage, " ", name)
}
}
}
if existsInbound, loaded := m.inboundByTag[tag]; loaded {
if m.started {
err = existsInbound.Close()
if err != nil {
return E.Cause(err, "close inbound/", existsInbound.Type(), "[", existsInbound.Tag(), "]")
}
}
existsIndex := common.Index(m.inbounds, func(it adapter.Inbound) bool {
return it == existsInbound
})
if existsIndex == -1 {
panic("invalid inbound index")
}
m.inbounds = append(m.inbounds[:existsIndex], m.inbounds[existsIndex+1:]...)
}
m.inbounds = append(m.inbounds, inbound)
m.inboundByTag[tag] = inbound
return nil
}
-76
View File
@@ -1,76 +0,0 @@
package inbound
import (
"context"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
)
type ConstructorFunc[T any] func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options T) (adapter.Inbound, error)
func Register[Options any](registry *Registry, outboundType string, constructor ConstructorFunc[Options]) {
registry.register(outboundType, func() any {
return new(Options)
}, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, rawOptions any) (adapter.Inbound, error) {
var options *Options
if rawOptions != nil {
options = rawOptions.(*Options)
}
return constructor(ctx, router, logger, tag, common.PtrValueOrDefault(options))
})
}
var _ adapter.InboundRegistry = (*Registry)(nil)
type (
optionsConstructorFunc func() any
constructorFunc func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options any) (adapter.Inbound, error)
)
type Registry struct {
access sync.Mutex
optionsType map[string]optionsConstructorFunc
constructor map[string]constructorFunc
}
func NewRegistry() *Registry {
return &Registry{
optionsType: make(map[string]optionsConstructorFunc),
constructor: make(map[string]constructorFunc),
}
}
func (m *Registry) CreateOptions(outboundType string) (any, bool) {
m.access.Lock()
defer m.access.Unlock()
optionsConstructor, loaded := m.optionsType[outboundType]
if !loaded {
return nil, false
}
return optionsConstructor(), true
}
func (m *Registry) Create(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, outboundType string, options any) (adapter.Inbound, error) {
m.access.Lock()
defer m.access.Unlock()
return m.UnsafeCreate(ctx, router, logger, tag, outboundType, options)
}
func (m *Registry) UnsafeCreate(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, outboundType string, options any) (adapter.Inbound, error) {
constructor, loaded := m.constructor[outboundType]
if !loaded {
return nil, E.New("outbound type not found: " + outboundType)
}
return constructor(ctx, router, logger, tag, options)
}
func (m *Registry) register(outboundType string, optionsConstructor optionsConstructorFunc, constructor constructorFunc) {
m.access.Lock()
defer m.access.Unlock()
m.optionsType[outboundType] = optionsConstructor
m.constructor[outboundType] = constructor
}
-114
View File
@@ -1,114 +0,0 @@
package adapter
import (
"reflect"
"strings"
"time"
"github.com/sagernet/sing-box/log"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
)
type SimpleLifecycle interface {
Start() error
Close() error
}
type StartStage uint8
const (
StartStateInitialize StartStage = iota
StartStateStart
StartStatePostStart
StartStateStarted
)
var ListStartStages = []StartStage{
StartStateInitialize,
StartStateStart,
StartStatePostStart,
StartStateStarted,
}
func (s StartStage) String() string {
switch s {
case StartStateInitialize:
return "initialize"
case StartStateStart:
return "start"
case StartStatePostStart:
return "post-start"
case StartStateStarted:
return "finish-start"
default:
panic("unknown stage")
}
}
type Lifecycle interface {
Start(stage StartStage) error
Close() error
}
type LifecycleService interface {
Name() string
Lifecycle
}
func getServiceName(service any) string {
if named, ok := service.(interface {
Type() string
Tag() string
}); ok {
tag := named.Tag()
if tag != "" {
return named.Type() + "[" + tag + "]"
}
return named.Type()
}
t := reflect.TypeOf(service)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
return strings.ToLower(t.Name())
}
func Start(logger log.ContextLogger, stage StartStage, services ...Lifecycle) error {
for _, service := range services {
name := getServiceName(service)
done := LogElapsed(logger, stage, " ", name)
err := service.Start(stage)
done()
if err != nil {
return err
}
}
return nil
}
func StartNamed(logger log.ContextLogger, stage StartStage, services []LifecycleService) error {
for _, service := range services {
done := LogElapsed(logger, stage, " ", service.Name())
err := service.Start(stage)
done()
if err != nil {
return E.Cause(err, stage.String(), " ", service.Name())
}
}
return nil
}
func LogElapsed(logger log.ContextLogger, description ...any) func() {
prefix := F.ToString(description...)
startTime := time.Now()
timer := time.AfterFunc(time.Second, func() {
logger.Trace(prefix, "...")
})
return func() {
if timer.Stop() {
return
}
logger.Trace(prefix, " completed (", F.Seconds(time.Since(startTime).Seconds()), "s)")
}
}
-52
View File
@@ -1,52 +0,0 @@
package adapter
func LegacyStart(starter any, stage StartStage) error {
if lifecycle, isLifecycle := starter.(Lifecycle); isLifecycle {
return lifecycle.Start(stage)
}
switch stage {
case StartStateInitialize:
if preStarter, isPreStarter := starter.(interface {
PreStart() error
}); isPreStarter {
return preStarter.PreStart()
}
case StartStateStart:
if starter, isStarter := starter.(interface {
Start() error
}); isStarter {
return starter.Start()
}
case StartStateStarted:
if postStarter, isPostStarter := starter.(interface {
PostStart() error
}); isPostStarter {
return postStarter.PostStart()
}
}
return nil
}
type lifecycleServiceWrapper struct {
SimpleLifecycle
name string
}
func NewLifecycleService(service SimpleLifecycle, name string) LifecycleService {
return &lifecycleServiceWrapper{
SimpleLifecycle: service,
name: name,
}
}
func (l *lifecycleServiceWrapper) Name() string {
return l.name
}
func (l *lifecycleServiceWrapper) Start(stage StartStage) error {
return LegacyStart(l.SimpleLifecycle, stage)
}
func (l *lifecycleServiceWrapper) Close() error {
return l.SimpleLifecycle.Close()
}
-81
View File
@@ -1,81 +0,0 @@
package adapter
import (
"encoding/hex"
"net"
"strings"
"time"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/control"
)
type NetworkManager interface {
Lifecycle
Initialize(ruleSets []RuleSet)
InterfaceFinder() control.InterfaceFinder
UpdateInterfaces() error
DefaultNetworkInterface() *NetworkInterface
NetworkInterfaces() []NetworkInterface
AutoDetectInterface() bool
AutoDetectInterfaceFunc() control.Func
ProtectFunc() control.Func
DefaultOptions() NetworkOptions
RegisterAutoRedirectOutputMark(mark uint32) error
AutoRedirectOutputMark() uint32
AutoRedirectOutputMarkFunc() control.Func
NetworkMonitor() tun.NetworkUpdateMonitor
InterfaceMonitor() tun.DefaultInterfaceMonitor
PackageManager() tun.PackageManager
NeedWIFIState() bool
WIFIState() WIFIState
UpdateWIFIState()
ResetNetwork()
}
type NetworkOptions struct {
BindInterface string
RoutingMark uint32
DomainResolver string
DomainResolveOptions DNSQueryOptions
NetworkStrategy *C.NetworkStrategy
NetworkType []C.InterfaceType
FallbackNetworkType []C.InterfaceType
FallbackDelay time.Duration
}
type InterfaceUpdateListener interface {
InterfaceUpdated()
}
type WIFIState struct {
SSID string
BSSID string
}
func NormalizeWIFIBSSID(bssid string) string {
bssid = strings.TrimSpace(bssid)
if bssid == "" {
return ""
}
parsed, err := net.ParseMAC(bssid)
if err == nil && len(parsed) == 6 {
return parsed.String()
}
if len(bssid) == 12 {
decoded, err := hex.DecodeString(bssid)
if err == nil {
return net.HardwareAddr(decoded).String()
}
}
return bssid
}
type NetworkInterface struct {
control.Interface
Type C.InterfaceType
DNSServers []string
Expensive bool
Constrained bool
}
+3 -31
View File
@@ -2,12 +2,8 @@ package adapter
import (
"context"
"net/netip"
"time"
"net"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-tun"
N "github.com/sagernet/sing/common/network"
)
@@ -19,30 +15,6 @@ type Outbound interface {
Network() []string
Dependencies() []string
N.Dialer
}
type OutboundWithPreferredRoutes interface {
Outbound
PreferredDomain(domain string) bool
PreferredAddress(address netip.Addr) bool
}
type DirectRouteOutbound interface {
Outbound
NewDirectRouteConnection(metadata InboundContext, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error)
}
type OutboundRegistry interface {
option.OutboundOptionsRegistry
CreateOutbound(ctx context.Context, router Router, logger log.ContextLogger, tag string, outboundType string, options any) (Outbound, error)
UnsafeCreateOutbound(ctx context.Context, router Router, logger log.ContextLogger, tag string, outboundType string, options any) (Outbound, error)
}
type OutboundManager interface {
Lifecycle
Outbounds() []Outbound
Outbound(tag string) (Outbound, bool)
Default() Outbound
Remove(tag string) error
Create(ctx context.Context, router Router, logger log.ContextLogger, tag string, outboundType string, options any) error
NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
}
-45
View File
@@ -1,45 +0,0 @@
package outbound
import (
"github.com/sagernet/sing-box/option"
)
type Adapter struct {
outboundType string
outboundTag string
network []string
dependencies []string
}
func NewAdapter(outboundType string, outboundTag string, network []string, dependencies []string) Adapter {
return Adapter{
outboundType: outboundType,
outboundTag: outboundTag,
network: network,
dependencies: dependencies,
}
}
func NewAdapterWithDialerOptions(outboundType string, outboundTag string, network []string, dialOptions option.DialerOptions) Adapter {
var dependencies []string
if dialOptions.Detour != "" {
dependencies = []string{dialOptions.Detour}
}
return NewAdapter(outboundType, outboundTag, network, dependencies)
}
func (a *Adapter) Type() string {
return a.outboundType
}
func (a *Adapter) Tag() string {
return a.outboundTag
}
func (a *Adapter) Network() []string {
return a.network
}
func (a *Adapter) Dependencies() []string {
return a.dependencies
}
-310
View File
@@ -1,310 +0,0 @@
package outbound
import (
"context"
"io"
"os"
"strings"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/taskmonitor"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
)
var _ adapter.OutboundManager = (*Manager)(nil)
type Manager struct {
logger log.ContextLogger
registry adapter.OutboundRegistry
endpoint adapter.EndpointManager
defaultTag string
access sync.RWMutex
started bool
stage adapter.StartStage
outbounds []adapter.Outbound
outboundByTag map[string]adapter.Outbound
dependByTag map[string][]string
defaultOutbound adapter.Outbound
defaultOutboundFallback func() (adapter.Outbound, error)
}
func NewManager(logger logger.ContextLogger, registry adapter.OutboundRegistry, endpoint adapter.EndpointManager, defaultTag string) *Manager {
return &Manager{
logger: logger,
registry: registry,
endpoint: endpoint,
defaultTag: defaultTag,
outboundByTag: make(map[string]adapter.Outbound),
dependByTag: make(map[string][]string),
}
}
func (m *Manager) Initialize(defaultOutboundFallback func() (adapter.Outbound, error)) {
m.defaultOutboundFallback = defaultOutboundFallback
}
func (m *Manager) Start(stage adapter.StartStage) error {
m.access.Lock()
if m.started && m.stage >= stage {
panic("already started")
}
m.started = true
m.stage = stage
if stage == adapter.StartStateStart {
if m.defaultTag != "" && m.defaultOutbound == nil {
defaultEndpoint, loaded := m.endpoint.Get(m.defaultTag)
if !loaded {
m.access.Unlock()
return E.New("default outbound not found: ", m.defaultTag)
}
m.defaultOutbound = defaultEndpoint
}
if m.defaultOutbound == nil {
directOutbound, err := m.defaultOutboundFallback()
if err != nil {
m.access.Unlock()
return E.Cause(err, "create direct outbound for fallback")
}
m.outbounds = append(m.outbounds, directOutbound)
m.outboundByTag[directOutbound.Tag()] = directOutbound
m.defaultOutbound = directOutbound
}
outbounds := m.outbounds
m.access.Unlock()
return m.startOutbounds(append(outbounds, common.Map(m.endpoint.Endpoints(), func(it adapter.Endpoint) adapter.Outbound { return it })...))
} else {
outbounds := m.outbounds
m.access.Unlock()
for _, outbound := range outbounds {
name := "outbound/" + outbound.Type() + "[" + outbound.Tag() + "]"
done := adapter.LogElapsed(m.logger, stage, " ", name)
err := adapter.LegacyStart(outbound, stage)
done()
if err != nil {
return E.Cause(err, stage, " ", name)
}
}
}
return nil
}
func (m *Manager) startOutbounds(outbounds []adapter.Outbound) error {
monitor := taskmonitor.New(m.logger, C.StartTimeout)
started := make(map[string]bool)
for {
canContinue := false
startOne:
for _, outboundToStart := range outbounds {
outboundTag := outboundToStart.Tag()
if started[outboundTag] {
continue
}
dependencies := outboundToStart.Dependencies()
for _, dependency := range dependencies {
if !started[dependency] {
continue startOne
}
}
started[outboundTag] = true
canContinue = true
name := "outbound/" + outboundToStart.Type() + "[" + outboundTag + "]"
if starter, isStarter := outboundToStart.(adapter.Lifecycle); isStarter {
done := adapter.LogElapsed(m.logger, "start ", name)
monitor.Start("start ", name)
err := starter.Start(adapter.StartStateStart)
monitor.Finish()
done()
if err != nil {
return E.Cause(err, "start ", name)
}
} else if starter, isStarter := outboundToStart.(interface {
Start() error
}); isStarter {
done := adapter.LogElapsed(m.logger, "start ", name)
monitor.Start("start ", name)
err := starter.Start()
monitor.Finish()
done()
if err != nil {
return E.Cause(err, "start ", name)
}
}
}
if len(started) == len(outbounds) {
break
}
if canContinue {
continue
}
currentOutbound := common.Find(outbounds, func(it adapter.Outbound) bool {
return !started[it.Tag()]
})
var lintOutbound func(oTree []string, oCurrent adapter.Outbound) error
lintOutbound = func(oTree []string, oCurrent adapter.Outbound) error {
problemOutboundTag := common.Find(oCurrent.Dependencies(), func(it string) bool {
return !started[it]
})
if common.Contains(oTree, problemOutboundTag) {
return E.New("circular outbound dependency: ", strings.Join(oTree, " -> "), " -> ", problemOutboundTag)
}
m.access.Lock()
problemOutbound := m.outboundByTag[problemOutboundTag]
m.access.Unlock()
if problemOutbound == nil {
return E.New("dependency[", problemOutboundTag, "] not found for outbound[", oCurrent.Tag(), "]")
}
return lintOutbound(append(oTree, problemOutboundTag), problemOutbound)
}
return lintOutbound([]string{currentOutbound.Tag()}, currentOutbound)
}
return nil
}
func (m *Manager) Close() error {
monitor := taskmonitor.New(m.logger, C.StopTimeout)
m.access.Lock()
if !m.started {
m.access.Unlock()
return nil
}
m.started = false
outbounds := m.outbounds
m.outbounds = nil
m.access.Unlock()
var err error
for _, outbound := range outbounds {
if closer, isCloser := outbound.(io.Closer); isCloser {
name := "outbound/" + outbound.Type() + "[" + outbound.Tag() + "]"
done := adapter.LogElapsed(m.logger, "close ", name)
monitor.Start("close ", name)
err = E.Append(err, closer.Close(), func(err error) error {
return E.Cause(err, "close ", name)
})
monitor.Finish()
done()
}
}
return nil
}
func (m *Manager) Outbounds() []adapter.Outbound {
m.access.RLock()
defer m.access.RUnlock()
return m.outbounds
}
func (m *Manager) Outbound(tag string) (adapter.Outbound, bool) {
m.access.RLock()
outbound, found := m.outboundByTag[tag]
m.access.RUnlock()
if found {
return outbound, true
}
return m.endpoint.Get(tag)
}
func (m *Manager) Default() adapter.Outbound {
m.access.RLock()
defer m.access.RUnlock()
return m.defaultOutbound
}
func (m *Manager) Remove(tag string) error {
m.access.Lock()
defer m.access.Unlock()
outbound, found := m.outboundByTag[tag]
if !found {
return os.ErrInvalid
}
delete(m.outboundByTag, tag)
index := common.Index(m.outbounds, func(it adapter.Outbound) bool {
return it == outbound
})
if index == -1 {
panic("invalid inbound index")
}
m.outbounds = append(m.outbounds[:index], m.outbounds[index+1:]...)
started := m.started
if m.defaultOutbound == outbound {
if len(m.outbounds) > 0 {
m.defaultOutbound = m.outbounds[0]
m.logger.Info("updated default outbound to ", m.defaultOutbound.Tag())
} else {
m.defaultOutbound = nil
}
}
dependBy := m.dependByTag[tag]
if len(dependBy) > 0 {
return E.New("outbound[", tag, "] is depended by ", strings.Join(dependBy, ", "))
}
dependencies := outbound.Dependencies()
for _, dependency := range dependencies {
if len(m.dependByTag[dependency]) == 1 {
delete(m.dependByTag, dependency)
} else {
m.dependByTag[dependency] = common.Filter(m.dependByTag[dependency], func(it string) bool {
return it != tag
})
}
}
if started {
return common.Close(outbound)
}
return nil
}
func (m *Manager) Create(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, inboundType string, options any) error {
if tag == "" {
return os.ErrInvalid
}
outbound, err := m.registry.CreateOutbound(ctx, router, logger, tag, inboundType, options)
if err != nil {
return err
}
if m.started {
name := "outbound/" + outbound.Type() + "[" + outbound.Tag() + "]"
for _, stage := range adapter.ListStartStages {
done := adapter.LogElapsed(m.logger, stage, " ", name)
err = adapter.LegacyStart(outbound, stage)
done()
if err != nil {
return E.Cause(err, stage, " ", name)
}
}
}
m.access.Lock()
defer m.access.Unlock()
if existsOutbound, loaded := m.outboundByTag[tag]; loaded {
if m.started {
err = common.Close(existsOutbound)
if err != nil {
return E.Cause(err, "close outbound/", existsOutbound.Type(), "[", existsOutbound.Tag(), "]")
}
}
existsIndex := common.Index(m.outbounds, func(it adapter.Outbound) bool {
return it == existsOutbound
})
if existsIndex == -1 {
panic("invalid inbound index")
}
m.outbounds = append(m.outbounds[:existsIndex], m.outbounds[existsIndex+1:]...)
}
m.outbounds = append(m.outbounds, outbound)
m.outboundByTag[tag] = outbound
dependencies := outbound.Dependencies()
for _, dependency := range dependencies {
m.dependByTag[dependency] = append(m.dependByTag[dependency], tag)
}
if tag == m.defaultTag || (m.defaultTag == "" && m.defaultOutbound == nil) {
m.defaultOutbound = outbound
if m.started {
m.logger.Info("updated default outbound to ", outbound.Tag())
}
}
return nil
}
-76
View File
@@ -1,76 +0,0 @@
package outbound
import (
"context"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
)
type ConstructorFunc[T any] func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options T) (adapter.Outbound, error)
func Register[Options any](registry *Registry, outboundType string, constructor ConstructorFunc[Options]) {
registry.register(outboundType, func() any {
return new(Options)
}, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, rawOptions any) (adapter.Outbound, error) {
var options *Options
if rawOptions != nil {
options = rawOptions.(*Options)
}
return constructor(ctx, router, logger, tag, common.PtrValueOrDefault(options))
})
}
var _ adapter.OutboundRegistry = (*Registry)(nil)
type (
optionsConstructorFunc func() any
constructorFunc func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options any) (adapter.Outbound, error)
)
type Registry struct {
access sync.Mutex
optionsType map[string]optionsConstructorFunc
constructors map[string]constructorFunc
}
func NewRegistry() *Registry {
return &Registry{
optionsType: make(map[string]optionsConstructorFunc),
constructors: make(map[string]constructorFunc),
}
}
func (r *Registry) CreateOptions(outboundType string) (any, bool) {
r.access.Lock()
defer r.access.Unlock()
optionsConstructor, loaded := r.optionsType[outboundType]
if !loaded {
return nil, false
}
return optionsConstructor(), true
}
func (r *Registry) CreateOutbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, outboundType string, options any) (adapter.Outbound, error) {
r.access.Lock()
defer r.access.Unlock()
return r.UnsafeCreateOutbound(ctx, router, logger, tag, outboundType, options)
}
func (r *Registry) UnsafeCreateOutbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, outboundType string, options any) (adapter.Outbound, error) {
constructor, loaded := r.constructors[outboundType]
if !loaded {
return nil, E.New("outbound type not found: " + outboundType)
}
return constructor(ctx, router, logger, tag, options)
}
func (r *Registry) register(outboundType string, optionsConstructor optionsConstructorFunc, constructor constructorFunc) {
r.access.Lock()
defer r.access.Unlock()
r.optionsType[outboundType] = optionsConstructor
r.constructors[outboundType] = constructor
}
-74
View File
@@ -1,74 +0,0 @@
package adapter
import (
"net/netip"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/logger"
)
type PlatformInterface interface {
Initialize(networkManager NetworkManager) error
UsePlatformAutoDetectInterfaceControl() bool
AutoDetectInterfaceControl(fd int) error
UsePlatformInterface() bool
OpenInterface(options *tun.Options, platformOptions option.TunPlatformOptions) (tun.Tun, error)
UsePlatformDefaultInterfaceMonitor() bool
CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor
UsePlatformNetworkInterfaces() bool
NetworkInterfaces() ([]NetworkInterface, error)
UnderNetworkExtension() bool
NetworkExtensionIncludeAllNetworks() bool
ClearDNSCache()
RequestPermissionForWIFIState() error
ReadWIFIState() WIFIState
SystemCertificates() []string
UsePlatformConnectionOwnerFinder() bool
FindConnectionOwner(request *FindConnectionOwnerRequest) (*ConnectionOwner, error)
UsePlatformWIFIMonitor() bool
UsePlatformNotification() bool
SendNotification(notification *Notification) error
MyInterfaceAddress() []netip.Addr
}
type FindConnectionOwnerRequest struct {
IpProtocol int32
SourceAddress string
SourcePort int32
DestinationAddress string
DestinationPort int32
}
type ConnectionOwner struct {
ProcessID uint32
UserId int32
UserName string
ProcessPath string
AndroidPackageNames []string
}
type Notification struct {
Identifier string
TypeName string
TypeID int32
Title string
Subtitle string
Body string
OpenURL string
}
type SystemProxyStatus struct {
Available bool
Enabled bool
}
+8
View File
@@ -1 +1,9 @@
package adapter
type PreStarter interface {
PreStart() error
}
type PostStarter interface {
PostStart() error
}
-51
View File
@@ -1,51 +0,0 @@
package adapter
import (
"context"
"time"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common/x/list"
)
type Provider interface {
Type() string
Tag() string
Outbounds() []Outbound
Outbound(tag string) (Outbound, bool)
UpdatedAt() time.Time
HealthCheck(ctx context.Context) (map[string]uint16, error)
RegisterCallback(callback ProviderUpdateCallback) *list.Element[ProviderUpdateCallback]
UnregisterCallback(element *list.Element[ProviderUpdateCallback])
}
type ProviderUpdater interface {
Update() error
}
type ProviderSubscriptionInfo interface {
SubscriptionInfo() SubscriptionInfo
}
type ProviderRegistry interface {
option.ProviderOptionsRegistry
CreateProvider(ctx context.Context, router Router, logFactory log.Factory, tag string, providerType string, options any) (Provider, error)
}
type ProviderManager interface {
Lifecycle
Providers() []Provider
Get(tag string) (Provider, bool)
Remove(tag string) error
Create(ctx context.Context, router Router, logFactory log.Factory, tag string, providerType string, options any) error
}
type SubscriptionInfo struct {
Upload int64
Download int64
Total int64
Expire int64
}
type ProviderUpdateCallback = func(tag string) error
-299
View File
@@ -1,299 +0,0 @@
package provider
import (
"context"
"reflect"
"regexp"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/urltest"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common/batch"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
"github.com/sagernet/sing/common/x/list"
"github.com/sagernet/sing/service"
)
type Adapter struct {
ctx context.Context
outbound adapter.OutboundManager
router adapter.Router
logFactory log.Factory
logger log.ContextLogger
providerType string
providerTag string
outbounds []adapter.Outbound
outboundsByTag map[string]adapter.Outbound
ticker *time.Ticker
checking atomic.Bool
history adapter.URLTestHistoryStorage
callbackAccess sync.Mutex
callbacks list.List[adapter.ProviderUpdateCallback]
link string
enabled bool
removeEmojis bool
timeout time.Duration
interval time.Duration
}
func NewAdapter(ctx context.Context, router adapter.Router, outbound adapter.OutboundManager, logFactory log.Factory, logger log.ContextLogger, providerTag string, providerType string, options option.ProviderHealthCheckOptions) Adapter {
timeout := time.Duration(options.Timeout)
if timeout == 0 {
timeout = 3 * time.Second
}
interval := time.Duration(options.Interval)
if interval == 0 {
interval = 10 * time.Minute
}
if interval < time.Minute {
interval = time.Minute
}
return Adapter{
ctx: ctx,
outbound: outbound,
router: router,
logFactory: logFactory,
logger: logger,
providerType: providerType,
providerTag: providerTag,
enabled: options.Enabled,
link: options.URL,
timeout: timeout,
interval: interval,
}
}
func (a *Adapter) SetRemoveEmojis(remove bool) {
a.removeEmojis = remove
}
func (a *Adapter) Start() error {
a.history = service.FromContext[adapter.URLTestHistoryStorage](a.ctx)
if a.history == nil {
if clashServer := service.FromContext[adapter.ClashServer](a.ctx); clashServer != nil {
a.history = clashServer.HistoryStorage()
} else {
a.history = urltest.NewHistoryStorage()
}
}
go a.loopCheck()
return nil
}
func (a *Adapter) Type() string {
return a.providerType
}
func (a *Adapter) Tag() string {
return a.providerTag
}
func (a *Adapter) Outbounds() []adapter.Outbound {
return a.outbounds
}
func (a *Adapter) Outbound(tag string) (adapter.Outbound, bool) {
if a.outboundsByTag == nil {
return nil, false
}
detour, ok := a.outboundsByTag[tag]
return detour, ok
}
func (a *Adapter) UpdateOutbounds(oldOpts []option.Outbound, newOpts []option.Outbound) {
if a.removeEmojis {
removeEmojisFromTags(newOpts)
}
uniquifyTags(newOpts)
a.removeUseless(newOpts)
var (
oldOptByTag = make(map[string]option.Outbound)
outbounds = make([]adapter.Outbound, 0, len(newOpts))
outboundsByTag = make(map[string]adapter.Outbound)
)
for _, opt := range oldOpts {
oldOptByTag[opt.Tag] = opt
}
for i, opt := range newOpts {
var tag string
if opt.Tag != "" {
tag = F.ToString(a.providerTag, "/", opt.Tag)
} else {
tag = F.ToString(a.providerTag, "/", i)
}
outbound, exist := a.outbound.Outbound(tag)
if !exist || !reflect.DeepEqual(opt, oldOptByTag[opt.Tag]) {
err := a.outbound.Create(
adapter.WithContext(a.ctx, &adapter.InboundContext{
Outbound: tag,
}),
a.router,
a.logFactory.NewLogger(F.ToString("outbound/", opt.Type, "[", tag, "]")),
tag,
opt.Type,
opt.Options,
)
if err != nil {
a.logger.Warn(err, " in ", tag, ", skip create this outbound")
continue
}
outbound, _ = a.outbound.Outbound(tag)
}
outbounds = append(outbounds, outbound)
outboundsByTag[tag] = outbound
}
if a.enabled && a.history != nil {
go a.HealthCheck(a.ctx)
}
a.outbounds = outbounds
a.outboundsByTag = outboundsByTag
}
func (a *Adapter) HealthCheck(ctx context.Context) (map[string]uint16, error) {
if a.ticker != nil {
a.ticker.Reset(a.interval)
}
return a.healthcheck(ctx)
}
func (a *Adapter) RegisterCallback(callback adapter.ProviderUpdateCallback) *list.Element[adapter.ProviderUpdateCallback] {
a.callbackAccess.Lock()
defer a.callbackAccess.Unlock()
return a.callbacks.PushBack(callback)
}
func (a *Adapter) UnregisterCallback(element *list.Element[adapter.ProviderUpdateCallback]) {
a.callbackAccess.Lock()
defer a.callbackAccess.Unlock()
a.callbacks.Remove(element)
}
func (a *Adapter) UpdateGroups() {
for element := a.callbacks.Front(); element != nil; element = element.Next() {
element.Value(a.providerTag)
}
}
func (a *Adapter) Close() error {
if a.ticker != nil {
a.ticker.Stop()
}
outbounds := a.outbounds
a.outbounds = nil
var err error
for _, ob := range outbounds {
if err2 := a.outbound.Remove(ob.Tag()); err2 != nil {
err = E.Append(err, err2, func(err error) error {
return E.Cause(err, "close outbound [", ob.Tag(), "]")
})
}
}
return err
}
func (a *Adapter) loopCheck() {
if !a.enabled {
return
}
a.ticker = time.NewTicker(a.interval)
a.healthcheck(a.ctx)
for {
select {
case <-a.ctx.Done():
return
case <-a.ticker.C:
a.healthcheck(a.ctx)
}
}
}
func (a *Adapter) healthcheck(ctx context.Context) (map[string]uint16, error) {
result := make(map[string]uint16)
if a.checking.Swap(true) {
return result, nil
}
defer a.checking.Store(false)
b, _ := batch.New(ctx, batch.WithConcurrencyNum[any](10))
var resultAccess sync.Mutex
checked := make(map[string]bool)
for _, detour := range a.outbounds {
tag := detour.Tag()
if checked[tag] {
continue
}
checked[tag] = true
b.Go(tag, func() (any, error) {
ctx, cancel := context.WithTimeout(a.ctx, a.timeout)
defer cancel()
t, err := urltest.URLTest(ctx, a.link, detour)
if err != nil {
a.logger.Debug("outbound ", tag, " unavailable: ", err)
a.history.DeleteURLTestHistory(tag)
} else {
a.logger.Debug("outbound ", tag, " available: ", t, "ms")
a.history.StoreURLTestHistory(tag, &adapter.URLTestHistory{
Time: time.Now(),
Delay: t,
})
resultAccess.Lock()
result[tag] = t
resultAccess.Unlock()
}
return nil, nil
})
}
b.Wait()
return result, nil
}
func (a *Adapter) removeUseless(newOpts []option.Outbound) {
if len(a.outbounds) == 0 {
return
}
exists := make(map[string]bool)
for i, opt := range newOpts {
var tag string
if opt.Tag != "" {
tag = F.ToString(a.providerTag, "/", opt.Tag)
} else {
tag = F.ToString(a.providerTag, "/", i)
}
exists[tag] = true
}
for _, opt := range a.outbounds {
if !exists[opt.Tag()] {
if err := a.outbound.Remove(opt.Tag()); err != nil {
a.logger.Error(err, "close outbound [", opt.Tag(), "]")
}
}
}
}
func uniquifyTags(opts []option.Outbound) {
count := make(map[string]int)
for i, opt := range opts {
count[opt.Tag]++
if count[opt.Tag] > 1 {
opts[i].Tag = F.ToString(opt.Tag, " #", count[opt.Tag])
}
}
}
func removeEmojisFromTags(opts []option.Outbound) {
for i, opt := range opts {
cleaned := emojiRegex.ReplaceAllString(opt.Tag, "")
cleaned = multiSpaceRegex.ReplaceAllString(cleaned, " ")
opts[i].Tag = strings.TrimSpace(cleaned)
}
}
var emojiRegex = regexp.MustCompile(`[\x{1F1E0}-\x{1F1FF}\x{1F300}-\x{1F9FF}\x{2600}-\x{27BF}\x{FE00}-\x{FE0F}\x{200D}]+`)
var multiSpaceRegex = regexp.MustCompile(`\s{2,}`)
-157
View File
@@ -1,157 +0,0 @@
package provider
import (
"context"
"io"
"os"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/taskmonitor"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
)
var _ adapter.ProviderManager = (*Manager)(nil)
type Manager struct {
logger log.ContextLogger
registry adapter.ProviderRegistry
access sync.Mutex
started bool
stage adapter.StartStage
providers []adapter.Provider
providerByTag map[string]adapter.Provider
wg sync.WaitGroup
}
func NewManager(logger logger.ContextLogger, registry adapter.ProviderRegistry) *Manager {
return &Manager{
logger: logger,
registry: registry,
providerByTag: make(map[string]adapter.Provider),
}
}
func (m *Manager) Initialize() {
}
func (m *Manager) Start(stage adapter.StartStage) error {
m.access.Lock()
if m.started && m.stage >= stage {
panic("already started")
}
m.started = true
m.stage = stage
providers := m.providers
m.access.Unlock()
for _, provider := range providers {
err := adapter.LegacyStart(provider, stage)
if err != nil {
return E.Cause(err, stage, " provider/", provider.Type(), "[", provider.Tag(), "]")
}
}
return nil
}
func (m *Manager) Close() error {
monitor := taskmonitor.New(m.logger, C.StopTimeout)
m.access.Lock()
if !m.started {
m.access.Unlock()
return nil
}
m.started = false
providers := m.providers
m.providers = nil
m.access.Unlock()
var err error
for _, provider := range providers {
if closer, isCloser := provider.(io.Closer); isCloser {
monitor.Start("close provider/", provider.Type(), "[", provider.Tag(), "]")
err = E.Append(err, closer.Close(), func(err error) error {
return E.Cause(err, "close provider/", provider.Type(), "[", provider.Tag(), "]")
})
monitor.Finish()
}
}
return nil
}
func (m *Manager) Providers() []adapter.Provider {
m.access.Lock()
defer m.access.Unlock()
return m.providers
}
func (m *Manager) Get(tag string) (adapter.Provider, bool) {
m.access.Lock()
provider, found := m.providerByTag[tag]
m.access.Unlock()
return provider, found
}
func (m *Manager) Remove(tag string) error {
m.access.Lock()
provider, found := m.providerByTag[tag]
if !found {
m.access.Unlock()
return os.ErrInvalid
}
delete(m.providerByTag, tag)
index := common.Index(m.providers, func(it adapter.Provider) bool {
return it == provider
})
if index == -1 {
panic("invalid provider index")
}
m.providers = append(m.providers[:index], m.providers[index+1:]...)
started := m.started
m.access.Unlock()
if started {
return common.Close(provider)
}
return nil
}
func (m *Manager) Create(ctx context.Context, router adapter.Router, logFactory log.Factory, tag string, providerType string, options any) error {
if tag == "" {
return os.ErrInvalid
}
provider, err := m.registry.CreateProvider(ctx, router, logFactory, tag, providerType, options)
if err != nil {
return err
}
m.access.Lock()
defer m.access.Unlock()
if m.started {
for _, stage := range adapter.ListStartStages {
err = adapter.LegacyStart(provider, stage)
if err != nil {
return E.Cause(err, stage, " provider/", provider.Type(), "[", provider.Tag(), "]")
}
}
}
if existsProvider, loaded := m.providerByTag[tag]; loaded {
if m.started {
err = common.Close(existsProvider)
if err != nil {
return E.Cause(err, "close provider", provider.Type(), "[", existsProvider.Tag(), "]")
}
}
existsIndex := common.Index(m.providers, func(it adapter.Provider) bool {
return it == existsProvider
})
if existsIndex == -1 {
panic("invalid provider index")
}
m.providers = append(m.providers[:existsIndex], m.providers[existsIndex+1:]...)
}
m.providers = append(m.providers, provider)
m.providerByTag[tag] = provider
return nil
}
-72
View File
@@ -1,72 +0,0 @@
package provider
import (
"context"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
)
type ConstructorFunc[T any] func(ctx context.Context, router adapter.Router, logFactory log.Factory, tag string, options T) (adapter.Provider, error)
func Register[Options any](registry *Registry, providerType string, constructor ConstructorFunc[Options]) {
registry.register(providerType, func() any {
return new(Options)
}, func(ctx context.Context, router adapter.Router, logFactory log.Factory, tag string, rawOptions any) (adapter.Provider, error) {
var options *Options
if rawOptions != nil {
options = rawOptions.(*Options)
}
return constructor(ctx, router, logFactory, tag, common.PtrValueOrDefault(options))
})
}
var _ adapter.ProviderRegistry = (*Registry)(nil)
type (
optionsConstructorFunc func() any
constructorFunc func(ctx context.Context, router adapter.Router, logFactory log.Factory, tag string, options any) (adapter.Provider, error)
)
type Registry struct {
access sync.Mutex
optionsType map[string]optionsConstructorFunc
constructors map[string]constructorFunc
}
func NewRegistry() *Registry {
return &Registry{
optionsType: make(map[string]optionsConstructorFunc),
constructors: make(map[string]constructorFunc),
}
}
func (r *Registry) CreateOptions(providerType string) (any, bool) {
r.access.Lock()
defer r.access.Unlock()
optionsConstructor, loaded := r.optionsType[providerType]
if !loaded {
return nil, false
}
return optionsConstructor(), true
}
func (r *Registry) CreateProvider(ctx context.Context, router adapter.Router, logFactory log.Factory, tag string, providerType string, options any) (adapter.Provider, error) {
r.access.Lock()
defer r.access.Unlock()
constructor, loaded := r.constructors[providerType]
if !loaded {
return nil, E.New("provider type not found: '" + providerType + "'")
}
return constructor(ctx, router, logFactory, tag, options)
}
func (r *Registry) register(providerType string, optionsConstructor optionsConstructorFunc, constructor constructorFunc) {
r.access.Lock()
defer r.access.Unlock()
r.optionsType[providerType] = optionsConstructor
r.constructors[providerType] = constructor
}
+83 -27
View File
@@ -2,49 +2,102 @@ package adapter
import (
"context"
"crypto/tls"
"net"
"net/http"
"net/netip"
"sync"
"time"
"github.com/sagernet/sing-box/common/geoip"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing-tun"
"github.com/sagernet/sing/common/control"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/ntp"
"github.com/sagernet/sing/common/x/list"
"github.com/sagernet/sing/service"
mdns "github.com/miekg/dns"
"go4.org/netipx"
)
type Router interface {
Lifecycle
Service
PreStarter
PostStarter
Cleanup() error
Outbounds() []Outbound
Outbound(tag string) (Outbound, bool)
DefaultOutbound(network string) (Outbound, error)
FakeIPStore() FakeIPStore
ConnectionRouter
PreMatch(metadata InboundContext, context tun.DirectRouteContext, timeout time.Duration, supportBypass bool) (tun.DirectRouteDestination, error)
ConnectionRouterEx
GeoIPReader() *geoip.Reader
LoadGeosite(code string) (Rule, error)
RuleSet(tag string) (RuleSet, bool)
NeedWIFIState() bool
Exchange(ctx context.Context, message *mdns.Msg) (*mdns.Msg, error)
Lookup(ctx context.Context, domain string, strategy dns.DomainStrategy) ([]netip.Addr, error)
LookupDefault(ctx context.Context, domain string) ([]netip.Addr, error)
ClearDNSCache()
InterfaceFinder() control.InterfaceFinder
UpdateInterfaces() error
DefaultInterface() string
AutoDetectInterface() bool
AutoDetectInterfaceFunc() control.Func
DefaultMark() uint32
RegisterAutoRedirectOutputMark(mark uint32) error
AutoRedirectOutputMark() uint32
NetworkMonitor() tun.NetworkUpdateMonitor
InterfaceMonitor() tun.DefaultInterfaceMonitor
PackageManager() tun.PackageManager
WIFIState() WIFIState
Rules() []Rule
NeedFindProcess() bool
AppendTracker(tracker ConnectionTracker)
ResetNetwork()
ClashServer() ClashServer
SetClashServer(server ClashServer)
V2RayServer() V2RayServer
SetV2RayServer(server V2RayServer)
ResetNetwork() error
}
type ConnectionTracker interface {
RoutedConnection(ctx context.Context, conn net.Conn, metadata InboundContext, matchedRule Rule, matchOutbound Outbound) net.Conn
RoutedPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext, matchedRule Rule, matchOutbound Outbound) N.PacketConn
func ContextWithRouter(ctx context.Context, router Router) context.Context {
return service.ContextWith(ctx, router)
}
// Deprecated: Use ConnectionRouterEx instead.
type ConnectionRouter interface {
RouteConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
func RouterFromContext(ctx context.Context) Router {
return service.FromContext[Router](ctx)
}
type ConnectionRouterEx interface {
ConnectionRouter
RouteConnectionEx(ctx context.Context, conn net.Conn, metadata InboundContext, onClose N.CloseHandlerFunc)
RoutePacketConnectionEx(ctx context.Context, conn N.PacketConn, metadata InboundContext, onClose N.CloseHandlerFunc)
type HeadlessRule interface {
Match(metadata *InboundContext) bool
String() string
}
type Rule interface {
HeadlessRule
Service
Type() string
UpdateGeosite() error
Outbound() string
}
type DNSRule interface {
Rule
DisableCache() bool
RewriteTTL() *uint32
ClientSubnet() *netip.Prefix
WithAddressLimit() bool
MatchAddressLimit(metadata *InboundContext) bool
}
type RuleSet interface {
@@ -70,14 +123,12 @@ type RuleSetMetadata struct {
ContainsIPCIDRRule bool
}
type HTTPStartContext struct {
ctx context.Context
access sync.Mutex
httpClientCache map[string]*http.Client
}
func NewHTTPStartContext(ctx context.Context) *HTTPStartContext {
func NewHTTPStartContext() *HTTPStartContext {
return &HTTPStartContext{
ctx: ctx,
httpClientCache: make(map[string]*http.Client),
}
}
@@ -95,10 +146,6 @@ func (c *HTTPStartContext) HTTPClient(detour string, dialer N.Dialer) *http.Clie
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
return dialer.DialContext(ctx, network, M.ParseSocksaddr(addr))
},
TLSClientConfig: &tls.Config{
Time: ntp.TimeFuncFromContext(c.ctx),
RootCAs: RootPoolFromContext(c.ctx),
},
},
}
c.httpClientCache[detour] = httpClient
@@ -112,3 +159,12 @@ func (c *HTTPStartContext) Close() {
client.CloseIdleConnections()
}
}
type InterfaceUpdateListener interface {
InterfaceUpdated()
}
type WIFIState struct {
SSID string
BSSID string
}
-37
View File
@@ -1,37 +0,0 @@
package adapter
import (
C "github.com/sagernet/sing-box/constant"
)
type HeadlessRule interface {
Match(metadata *InboundContext) bool
String() string
}
type Rule interface {
HeadlessRule
SimpleLifecycle
Type() string
Action() RuleAction
}
type DNSRule interface {
Rule
WithAddressLimit() bool
MatchAddressLimit(metadata *InboundContext) bool
}
type RuleAction interface {
Type() string
String() string
}
func IsFinalAction(action RuleAction) bool {
switch action.Type() {
case C.RuleActionTypeSniff, C.RuleActionTypeResolve:
return false
default:
return true
}
}
+2 -23
View File
@@ -1,27 +1,6 @@
package adapter
import (
"context"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
)
type Service interface {
Lifecycle
Type() string
Tag() string
}
type ServiceRegistry interface {
option.ServiceOptionsRegistry
Create(ctx context.Context, logger log.ContextLogger, tag string, serviceType string, options any) (Service, error)
}
type ServiceManager interface {
Lifecycle
Services() []Service
Get(tag string) (Service, bool)
Remove(tag string) error
Create(ctx context.Context, logger log.ContextLogger, tag string, serviceType string, options any) error
Start() error
Close() error
}
-21
View File
@@ -1,21 +0,0 @@
package service
type Adapter struct {
serviceType string
serviceTag string
}
func NewAdapter(serviceType string, serviceTag string) Adapter {
return Adapter{
serviceType: serviceType,
serviceTag: serviceTag,
}
}
func (a *Adapter) Type() string {
return a.serviceType
}
func (a *Adapter) Tag() string {
return a.serviceTag
}
-153
View File
@@ -1,153 +0,0 @@
package service
import (
"context"
"os"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/taskmonitor"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
)
var _ adapter.ServiceManager = (*Manager)(nil)
type Manager struct {
logger log.ContextLogger
registry adapter.ServiceRegistry
access sync.Mutex
started bool
stage adapter.StartStage
services []adapter.Service
serviceByTag map[string]adapter.Service
}
func NewManager(logger log.ContextLogger, registry adapter.ServiceRegistry) *Manager {
return &Manager{
logger: logger,
registry: registry,
serviceByTag: make(map[string]adapter.Service),
}
}
func (m *Manager) Start(stage adapter.StartStage) error {
m.access.Lock()
if m.started && m.stage >= stage {
panic("already started")
}
m.started = true
m.stage = stage
services := m.services
m.access.Unlock()
for _, service := range services {
name := "service/" + service.Type() + "[" + service.Tag() + "]"
done := adapter.LogElapsed(m.logger, stage, " ", name)
err := adapter.LegacyStart(service, stage)
done()
if err != nil {
return E.Cause(err, stage, " ", name)
}
}
return nil
}
func (m *Manager) Close() error {
m.access.Lock()
defer m.access.Unlock()
if !m.started {
return nil
}
m.started = false
services := m.services
m.services = nil
monitor := taskmonitor.New(m.logger, C.StopTimeout)
var err error
for _, service := range services {
name := "service/" + service.Type() + "[" + service.Tag() + "]"
done := adapter.LogElapsed(m.logger, "close ", name)
monitor.Start("close ", name)
err = E.Append(err, service.Close(), func(err error) error {
return E.Cause(err, "close ", name)
})
monitor.Finish()
done()
}
return nil
}
func (m *Manager) Services() []adapter.Service {
m.access.Lock()
defer m.access.Unlock()
return m.services
}
func (m *Manager) Get(tag string) (adapter.Service, bool) {
m.access.Lock()
service, found := m.serviceByTag[tag]
m.access.Unlock()
return service, found
}
func (m *Manager) Remove(tag string) error {
m.access.Lock()
service, found := m.serviceByTag[tag]
if !found {
m.access.Unlock()
return os.ErrInvalid
}
delete(m.serviceByTag, tag)
index := common.Index(m.services, func(it adapter.Service) bool {
return it == service
})
if index == -1 {
panic("invalid service index")
}
m.services = append(m.services[:index], m.services[index+1:]...)
started := m.started
m.access.Unlock()
if started {
return service.Close()
}
return nil
}
func (m *Manager) Create(ctx context.Context, logger log.ContextLogger, tag string, serviceType string, options any) error {
service, err := m.registry.Create(ctx, logger, tag, serviceType, options)
if err != nil {
return err
}
m.access.Lock()
defer m.access.Unlock()
if m.started {
name := "service/" + service.Type() + "[" + service.Tag() + "]"
for _, stage := range adapter.ListStartStages {
done := adapter.LogElapsed(m.logger, stage, " ", name)
err = adapter.LegacyStart(service, stage)
done()
if err != nil {
return E.Cause(err, stage, " ", name)
}
}
}
if existsService, loaded := m.serviceByTag[tag]; loaded {
if m.started {
err = existsService.Close()
if err != nil {
return E.Cause(err, "close service/", existsService.Type(), "[", existsService.Tag(), "]")
}
}
existsIndex := common.Index(m.services, func(it adapter.Service) bool {
return it == existsService
})
if existsIndex == -1 {
panic("invalid service index")
}
m.services = append(m.services[:existsIndex], m.services[existsIndex+1:]...)
}
m.services = append(m.services, service)
m.serviceByTag[tag] = service
return nil
}
-72
View File
@@ -1,72 +0,0 @@
package service
import (
"context"
"sync"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
)
type ConstructorFunc[T any] func(ctx context.Context, logger log.ContextLogger, tag string, options T) (adapter.Service, error)
func Register[Options any](registry *Registry, outboundType string, constructor ConstructorFunc[Options]) {
registry.register(outboundType, func() any {
return new(Options)
}, func(ctx context.Context, logger log.ContextLogger, tag string, rawOptions any) (adapter.Service, error) {
var options *Options
if rawOptions != nil {
options = rawOptions.(*Options)
}
return constructor(ctx, logger, tag, common.PtrValueOrDefault(options))
})
}
var _ adapter.ServiceRegistry = (*Registry)(nil)
type (
optionsConstructorFunc func() any
constructorFunc func(ctx context.Context, logger log.ContextLogger, tag string, options any) (adapter.Service, error)
)
type Registry struct {
access sync.Mutex
optionsType map[string]optionsConstructorFunc
constructor map[string]constructorFunc
}
func NewRegistry() *Registry {
return &Registry{
optionsType: make(map[string]optionsConstructorFunc),
constructor: make(map[string]constructorFunc),
}
}
func (m *Registry) CreateOptions(outboundType string) (any, bool) {
m.access.Lock()
defer m.access.Unlock()
optionsConstructor, loaded := m.optionsType[outboundType]
if !loaded {
return nil, false
}
return optionsConstructor(), true
}
func (m *Registry) Create(ctx context.Context, logger log.ContextLogger, tag string, outboundType string, options any) (adapter.Service, error) {
m.access.Lock()
defer m.access.Unlock()
constructor, loaded := m.constructor[outboundType]
if !loaded {
return nil, E.New("outbound type not found: " + outboundType)
}
return constructor(ctx, logger, tag, options)
}
func (m *Registry) register(outboundType string, optionsConstructor optionsConstructorFunc, constructor constructorFunc) {
m.access.Lock()
defer m.access.Unlock()
m.optionsType[outboundType] = optionsConstructor
m.constructor[outboundType] = constructor
}
-18
View File
@@ -1,18 +0,0 @@
package adapter
import (
"net"
N "github.com/sagernet/sing/common/network"
)
type ManagedSSMServer interface {
Inbound
SetTracker(tracker SSMTracker)
UpdateUsers(users []string, uPSKs []string) error
}
type SSMTracker interface {
TrackConnection(conn net.Conn, metadata InboundContext) net.Conn
TrackPacketConnection(conn N.PacketConn, metadata InboundContext) N.PacketConn
}
+1 -1
View File
@@ -3,6 +3,6 @@ package adapter
import "time"
type TimeService interface {
SimpleLifecycle
Service
TimeFunc() func() time.Time
}
+65 -118
View File
@@ -4,165 +4,112 @@ import (
"context"
"net"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
type (
ConnectionHandlerFuncEx = func(ctx context.Context, conn net.Conn, metadata InboundContext, onClose N.CloseHandlerFunc)
PacketConnectionHandlerFuncEx = func(ctx context.Context, conn N.PacketConn, metadata InboundContext, onClose N.CloseHandlerFunc)
ConnectionHandlerFunc = func(ctx context.Context, conn net.Conn, metadata InboundContext) error
PacketConnectionHandlerFunc = func(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
)
func NewUpstreamHandlerEx(
func NewUpstreamHandler(
metadata InboundContext,
connectionHandler ConnectionHandlerFuncEx,
packetHandler PacketConnectionHandlerFuncEx,
) UpstreamHandlerAdapterEx {
return &myUpstreamHandlerWrapperEx{
connectionHandler ConnectionHandlerFunc,
packetHandler PacketConnectionHandlerFunc,
errorHandler E.Handler,
) UpstreamHandlerAdapter {
return &myUpstreamHandlerWrapper{
metadata: metadata,
connectionHandler: connectionHandler,
packetHandler: packetHandler,
errorHandler: errorHandler,
}
}
var _ UpstreamHandlerAdapterEx = (*myUpstreamHandlerWrapperEx)(nil)
var _ UpstreamHandlerAdapter = (*myUpstreamHandlerWrapper)(nil)
type myUpstreamHandlerWrapperEx struct {
type myUpstreamHandlerWrapper struct {
metadata InboundContext
connectionHandler ConnectionHandlerFuncEx
packetHandler PacketConnectionHandlerFuncEx
connectionHandler ConnectionHandlerFunc
packetHandler PacketConnectionHandlerFunc
errorHandler E.Handler
}
func (w *myUpstreamHandlerWrapperEx) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
func (w *myUpstreamHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
myMetadata := w.metadata
if source.IsValid() {
myMetadata.Source = source
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if destination.IsValid() {
myMetadata.Destination = destination
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
w.connectionHandler(ctx, conn, myMetadata, onClose)
return w.connectionHandler(ctx, conn, myMetadata)
}
func (w *myUpstreamHandlerWrapperEx) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
func (w *myUpstreamHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
myMetadata := w.metadata
if source.IsValid() {
myMetadata.Source = source
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if destination.IsValid() {
myMetadata.Destination = destination
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
w.packetHandler(ctx, conn, myMetadata, onClose)
return w.packetHandler(ctx, conn, myMetadata)
}
var _ UpstreamHandlerAdapterEx = (*myUpstreamContextHandlerWrapperEx)(nil)
type myUpstreamContextHandlerWrapperEx struct {
connectionHandler ConnectionHandlerFuncEx
packetHandler PacketConnectionHandlerFuncEx
func (w *myUpstreamHandlerWrapper) NewError(ctx context.Context, err error) {
w.errorHandler.NewError(ctx, err)
}
func NewUpstreamContextHandlerEx(
connectionHandler ConnectionHandlerFuncEx,
packetHandler PacketConnectionHandlerFuncEx,
) UpstreamHandlerAdapterEx {
return &myUpstreamContextHandlerWrapperEx{
func UpstreamMetadata(metadata InboundContext) M.Metadata {
return M.Metadata{
Source: metadata.Source,
Destination: metadata.Destination,
}
}
type myUpstreamContextHandlerWrapper struct {
connectionHandler ConnectionHandlerFunc
packetHandler PacketConnectionHandlerFunc
errorHandler E.Handler
}
func NewUpstreamContextHandler(
connectionHandler ConnectionHandlerFunc,
packetHandler PacketConnectionHandlerFunc,
errorHandler E.Handler,
) UpstreamHandlerAdapter {
return &myUpstreamContextHandlerWrapper{
connectionHandler: connectionHandler,
packetHandler: packetHandler,
errorHandler: errorHandler,
}
}
func (w *myUpstreamContextHandlerWrapperEx) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
_, myMetadata := ExtendContext(ctx)
if source.IsValid() {
myMetadata.Source = source
func (w *myUpstreamContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
myMetadata := ContextFrom(ctx)
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if destination.IsValid() {
myMetadata.Destination = destination
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
w.connectionHandler(ctx, conn, *myMetadata, onClose)
return w.connectionHandler(ctx, conn, *myMetadata)
}
func (w *myUpstreamContextHandlerWrapperEx) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
_, myMetadata := ExtendContext(ctx)
if source.IsValid() {
myMetadata.Source = source
func (w *myUpstreamContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
myMetadata := ContextFrom(ctx)
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if destination.IsValid() {
myMetadata.Destination = destination
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
w.packetHandler(ctx, conn, *myMetadata, onClose)
return w.packetHandler(ctx, conn, *myMetadata)
}
func NewRouteHandlerEx(
metadata InboundContext,
router ConnectionRouterEx,
) UpstreamHandlerAdapterEx {
return &routeHandlerWrapperEx{
metadata: metadata,
router: router,
}
}
var _ UpstreamHandlerAdapterEx = (*routeHandlerWrapperEx)(nil)
type routeHandlerWrapperEx struct {
metadata InboundContext
router ConnectionRouterEx
}
func (r *routeHandlerWrapperEx) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
if source.IsValid() {
r.metadata.Source = source
}
if destination.IsValid() {
r.metadata.Destination = destination
}
r.router.RouteConnectionEx(ctx, conn, r.metadata, onClose)
}
func (r *routeHandlerWrapperEx) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
if source.IsValid() {
r.metadata.Source = source
}
if destination.IsValid() {
r.metadata.Destination = destination
}
r.router.RoutePacketConnectionEx(ctx, conn, r.metadata, onClose)
}
func NewRouteContextHandlerEx(
router ConnectionRouterEx,
) UpstreamHandlerAdapterEx {
return &routeContextHandlerWrapperEx{
router: router,
}
}
var _ UpstreamHandlerAdapterEx = (*routeContextHandlerWrapperEx)(nil)
type routeContextHandlerWrapperEx struct {
router ConnectionRouterEx
}
func (r *routeContextHandlerWrapperEx) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
_, metadata := ExtendContext(ctx)
if source.IsValid() {
metadata.Source = source
}
if destination.IsValid() {
metadata.Destination = destination
}
r.router.RouteConnectionEx(ctx, conn, *metadata, onClose)
}
func (r *routeContextHandlerWrapperEx) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) {
_, metadata := ExtendContext(ctx)
if source.IsValid() {
metadata.Source = source
}
if destination.IsValid() {
metadata.Destination = destination
}
r.router.RoutePacketConnectionEx(ctx, conn, *metadata, onClose)
func (w *myUpstreamContextHandlerWrapper) NewError(ctx context.Context, err error) {
w.errorHandler.NewError(ctx, err)
}
-234
View File
@@ -1,234 +0,0 @@
package adapter
import (
"context"
"net"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/logger"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
type (
// Deprecated
ConnectionHandlerFunc = func(ctx context.Context, conn net.Conn, metadata InboundContext) error
// Deprecated
PacketConnectionHandlerFunc = func(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
)
// Deprecated
//
//nolint:staticcheck
func NewUpstreamHandler(
metadata InboundContext,
connectionHandler ConnectionHandlerFunc,
packetHandler PacketConnectionHandlerFunc,
errorHandler E.Handler,
) UpstreamHandlerAdapter {
return &myUpstreamHandlerWrapper{
metadata: metadata,
connectionHandler: connectionHandler,
packetHandler: packetHandler,
errorHandler: errorHandler,
}
}
var _ UpstreamHandlerAdapter = (*myUpstreamHandlerWrapper)(nil)
// Deprecated: use myUpstreamHandlerWrapperEx instead.
//
//nolint:staticcheck
type myUpstreamHandlerWrapper struct {
metadata InboundContext
connectionHandler ConnectionHandlerFunc
packetHandler PacketConnectionHandlerFunc
errorHandler E.Handler
}
// Deprecated: use myUpstreamHandlerWrapperEx instead.
func (w *myUpstreamHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
myMetadata := w.metadata
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.connectionHandler(ctx, conn, myMetadata)
}
// Deprecated: use myUpstreamHandlerWrapperEx instead.
func (w *myUpstreamHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
myMetadata := w.metadata
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.packetHandler(ctx, conn, myMetadata)
}
// Deprecated: use myUpstreamHandlerWrapperEx instead.
func (w *myUpstreamHandlerWrapper) NewError(ctx context.Context, err error) {
w.errorHandler.NewError(ctx, err)
}
// Deprecated: removed
func UpstreamMetadata(metadata InboundContext) M.Metadata {
return M.Metadata{
Source: metadata.Source.Unwrap(),
Destination: metadata.Destination.Unwrap(),
}
}
// Deprecated: Use NewUpstreamContextHandlerEx instead.
type myUpstreamContextHandlerWrapper struct {
connectionHandler ConnectionHandlerFunc
packetHandler PacketConnectionHandlerFunc
errorHandler E.Handler
}
// Deprecated: Use NewUpstreamContextHandlerEx instead.
func NewUpstreamContextHandler(
connectionHandler ConnectionHandlerFunc,
packetHandler PacketConnectionHandlerFunc,
errorHandler E.Handler,
) UpstreamHandlerAdapter {
return &myUpstreamContextHandlerWrapper{
connectionHandler: connectionHandler,
packetHandler: packetHandler,
errorHandler: errorHandler,
}
}
// Deprecated: Use NewUpstreamContextHandlerEx instead.
func (w *myUpstreamContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
myMetadata := ContextFrom(ctx)
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.connectionHandler(ctx, conn, *myMetadata)
}
// Deprecated: Use NewUpstreamContextHandlerEx instead.
func (w *myUpstreamContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
myMetadata := ContextFrom(ctx)
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.packetHandler(ctx, conn, *myMetadata)
}
// Deprecated: Use NewUpstreamContextHandlerEx instead.
func (w *myUpstreamContextHandlerWrapper) NewError(ctx context.Context, err error) {
w.errorHandler.NewError(ctx, err)
}
// Deprecated: Use ConnectionRouterEx instead.
func NewRouteHandler(
metadata InboundContext,
router ConnectionRouter,
logger logger.ContextLogger,
) UpstreamHandlerAdapter {
return &routeHandlerWrapper{
metadata: metadata,
router: router,
logger: logger,
}
}
// Deprecated: Use ConnectionRouterEx instead.
func NewRouteContextHandler(
router ConnectionRouter,
logger logger.ContextLogger,
) UpstreamHandlerAdapter {
return &routeContextHandlerWrapper{
router: router,
logger: logger,
}
}
var _ UpstreamHandlerAdapter = (*routeHandlerWrapper)(nil)
// Deprecated: Use ConnectionRouterEx instead.
//
//nolint:staticcheck
type routeHandlerWrapper struct {
metadata InboundContext
router ConnectionRouter
logger logger.ContextLogger
}
// Deprecated: Use ConnectionRouterEx instead.
func (w *routeHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
myMetadata := w.metadata
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RouteConnection(ctx, conn, myMetadata)
}
// Deprecated: Use ConnectionRouterEx instead.
func (w *routeHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
myMetadata := w.metadata
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RoutePacketConnection(ctx, conn, myMetadata)
}
// Deprecated: Use ConnectionRouterEx instead.
func (w *routeHandlerWrapper) NewError(ctx context.Context, err error) {
w.logger.ErrorContext(ctx, err)
}
var _ UpstreamHandlerAdapter = (*routeContextHandlerWrapper)(nil)
// Deprecated: Use ConnectionRouterEx instead.
type routeContextHandlerWrapper struct {
router ConnectionRouter
logger logger.ContextLogger
}
// Deprecated: Use ConnectionRouterEx instead.
func (w *routeContextHandlerWrapper) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error {
myMetadata := ContextFrom(ctx)
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RouteConnection(ctx, conn, *myMetadata)
}
// Deprecated: Use ConnectionRouterEx instead.
func (w *routeContextHandlerWrapper) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata M.Metadata) error {
myMetadata := ContextFrom(ctx)
if metadata.Source.IsValid() {
myMetadata.Source = metadata.Source
}
if metadata.Destination.IsValid() {
myMetadata.Destination = metadata.Destination
}
return w.router.RoutePacketConnection(ctx, conn, *myMetadata)
}
// Deprecated: Use ConnectionRouterEx instead.
func (w *routeContextHandlerWrapper) NewError(ctx context.Context, err error) {
w.logger.ErrorContext(ctx, err)
}
+3 -1
View File
@@ -4,6 +4,7 @@ import (
"context"
"net"
E "github.com/sagernet/sing/common/exceptions"
N "github.com/sagernet/sing/common/network"
)
@@ -15,7 +16,8 @@ type V2RayServerTransport interface {
}
type V2RayServerTransportHandler interface {
N.TCPConnectionHandlerEx
N.TCPConnectionHandler
E.Handler
}
type V2RayClientTransport interface {
+201 -401
View File
@@ -9,98 +9,45 @@ import (
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/adapter/endpoint"
"github.com/sagernet/sing-box/adapter/inbound"
"github.com/sagernet/sing-box/adapter/outbound"
"github.com/sagernet/sing-box/adapter/provider"
boxService "github.com/sagernet/sing-box/adapter/service"
"github.com/sagernet/sing-box/common/certificate"
"github.com/sagernet/sing-box/common/dialer"
"github.com/sagernet/sing-box/common/taskmonitor"
"github.com/sagernet/sing-box/common/tls"
"github.com/sagernet/sing-box/common/urltest"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/dns"
"github.com/sagernet/sing-box/experimental"
"github.com/sagernet/sing-box/experimental/cachefile"
"github.com/sagernet/sing-box/experimental/libbox/platform"
"github.com/sagernet/sing-box/inbound"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/protocol/direct"
"github.com/sagernet/sing-box/outbound"
"github.com/sagernet/sing-box/route"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
"github.com/sagernet/sing/common/ntp"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/pause"
)
var _ adapter.SimpleLifecycle = (*Box)(nil)
var _ adapter.Service = (*Box)(nil)
type Box struct {
createdAt time.Time
logFactory log.Factory
logger log.ContextLogger
network *route.NetworkManager
endpoint *endpoint.Manager
inbound *inbound.Manager
outbound *outbound.Manager
provider *provider.Manager
service *boxService.Manager
dnsTransport *dns.TransportManager
dnsRouter *dns.Router
connection *route.ConnectionManager
router *route.Router
internalService []adapter.LifecycleService
done chan struct{}
createdAt time.Time
router adapter.Router
inbounds []adapter.Inbound
outbounds []adapter.Outbound
logFactory log.Factory
logger log.ContextLogger
preServices1 map[string]adapter.Service
preServices2 map[string]adapter.Service
postServices map[string]adapter.Service
done chan struct{}
}
type Options struct {
option.Options
Context context.Context
PlatformInterface platform.Interface
PlatformLogWriter log.PlatformWriter
}
func Context(
ctx context.Context,
inboundRegistry adapter.InboundRegistry,
outboundRegistry adapter.OutboundRegistry,
endpointRegistry adapter.EndpointRegistry,
providerRegistry adapter.ProviderRegistry,
dnsTransportRegistry adapter.DNSTransportRegistry,
serviceRegistry adapter.ServiceRegistry,
) context.Context {
if service.FromContext[option.InboundOptionsRegistry](ctx) == nil ||
service.FromContext[adapter.InboundRegistry](ctx) == nil {
ctx = service.ContextWith[option.InboundOptionsRegistry](ctx, inboundRegistry)
ctx = service.ContextWith[adapter.InboundRegistry](ctx, inboundRegistry)
}
if service.FromContext[option.OutboundOptionsRegistry](ctx) == nil ||
service.FromContext[adapter.OutboundRegistry](ctx) == nil {
ctx = service.ContextWith[option.OutboundOptionsRegistry](ctx, outboundRegistry)
ctx = service.ContextWith[adapter.OutboundRegistry](ctx, outboundRegistry)
}
if service.FromContext[option.EndpointOptionsRegistry](ctx) == nil ||
service.FromContext[adapter.EndpointRegistry](ctx) == nil {
ctx = service.ContextWith[option.EndpointOptionsRegistry](ctx, endpointRegistry)
ctx = service.ContextWith[adapter.EndpointRegistry](ctx, endpointRegistry)
}
if service.FromContext[option.ProviderOptionsRegistry](ctx) == nil ||
service.FromContext[adapter.ProviderRegistry](ctx) == nil {
ctx = service.ContextWith[option.ProviderOptionsRegistry](ctx, providerRegistry)
ctx = service.ContextWith[adapter.ProviderRegistry](ctx, providerRegistry)
}
if service.FromContext[adapter.DNSTransportRegistry](ctx) == nil {
ctx = service.ContextWith[option.DNSTransportOptionsRegistry](ctx, dnsTransportRegistry)
ctx = service.ContextWith[adapter.DNSTransportRegistry](ctx, dnsTransportRegistry)
}
if service.FromContext[adapter.ServiceRegistry](ctx) == nil {
ctx = service.ContextWith[option.ServiceOptionsRegistry](ctx, serviceRegistry)
ctx = service.ContextWith[adapter.ServiceRegistry](ctx, serviceRegistry)
}
return ctx
}
func New(options Options) (*Box, error) {
createdAt := time.Now()
ctx := options.Context
@@ -108,39 +55,9 @@ func New(options Options) (*Box, error) {
ctx = context.Background()
}
ctx = service.ContextWithDefaultRegistry(ctx)
endpointRegistry := service.FromContext[adapter.EndpointRegistry](ctx)
inboundRegistry := service.FromContext[adapter.InboundRegistry](ctx)
outboundRegistry := service.FromContext[adapter.OutboundRegistry](ctx)
providerRegistry := service.FromContext[adapter.ProviderRegistry](ctx)
dnsTransportRegistry := service.FromContext[adapter.DNSTransportRegistry](ctx)
serviceRegistry := service.FromContext[adapter.ServiceRegistry](ctx)
if endpointRegistry == nil {
return nil, E.New("missing endpoint registry in context")
}
if inboundRegistry == nil {
return nil, E.New("missing inbound registry in context")
}
if outboundRegistry == nil {
return nil, E.New("missing outbound registry in context")
}
if providerRegistry == nil {
return nil, E.New("missing provider registry in context")
}
if dnsTransportRegistry == nil {
return nil, E.New("missing DNS transport registry in context")
}
if serviceRegistry == nil {
return nil, E.New("missing service registry in context")
}
ctx = pause.WithDefaultManager(ctx)
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
err := applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug))
if err != nil {
return nil, err
}
applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug))
var needCacheFile bool
var needClashAPI bool
var needV2RayAPI bool
@@ -153,12 +70,8 @@ func New(options Options) (*Box, error) {
if experimentalOptions.V2RayAPI != nil && experimentalOptions.V2RayAPI.Listen != "" {
needV2RayAPI = true
}
if experimentalOptions.UnifiedDelay != nil && experimentalOptions.UnifiedDelay.Enabled {
ctx = urltest.ContextWithIsUnifiedDelay(ctx)
}
platformInterface := service.FromContext[adapter.PlatformInterface](ctx)
var defaultLogWriter io.Writer
if platformInterface != nil {
if options.PlatformInterface != nil {
defaultLogWriter = io.Discard
}
logFactory, err := log.New(log.Options{
@@ -172,274 +85,115 @@ func New(options Options) (*Box, error) {
if err != nil {
return nil, E.Cause(err, "create log factory")
}
service.MustRegister[log.Factory](ctx, logFactory)
var internalServices []adapter.LifecycleService
certificateOptions := common.PtrValueOrDefault(options.Certificate)
if C.IsAndroid || certificateOptions.Store != "" && certificateOptions.Store != C.CertificateStoreSystem ||
len(certificateOptions.Certificate) > 0 ||
len(certificateOptions.CertificatePath) > 0 ||
len(certificateOptions.CertificateDirectoryPath) > 0 {
certificateStore, err := certificate.NewStore(ctx, logFactory.NewLogger("certificate"), certificateOptions)
if err != nil {
return nil, err
}
service.MustRegister[adapter.CertificateStore](ctx, certificateStore)
internalServices = append(internalServices, certificateStore)
}
routeOptions := common.PtrValueOrDefault(options.Route)
dnsOptions := common.PtrValueOrDefault(options.DNS)
endpointManager := endpoint.NewManager(logFactory.NewLogger("endpoint"), endpointRegistry)
inboundManager := inbound.NewManager(logFactory.NewLogger("inbound"), inboundRegistry, endpointManager)
outboundManager := outbound.NewManager(logFactory.NewLogger("outbound"), outboundRegistry, endpointManager, routeOptions.Final)
providerManager := provider.NewManager(logFactory.NewLogger("provider"), providerRegistry)
dnsTransportManager := dns.NewTransportManager(logFactory.NewLogger("dns/transport"), dnsTransportRegistry, outboundManager, dnsOptions.Final)
serviceManager := boxService.NewManager(logFactory.NewLogger("service"), serviceRegistry)
service.MustRegister[adapter.EndpointManager](ctx, endpointManager)
service.MustRegister[adapter.InboundManager](ctx, inboundManager)
service.MustRegister[adapter.OutboundManager](ctx, outboundManager)
service.MustRegister[adapter.ProviderManager](ctx, providerManager)
service.MustRegister[adapter.DNSTransportManager](ctx, dnsTransportManager)
service.MustRegister[adapter.ServiceManager](ctx, serviceManager)
dnsRouter := dns.NewRouter(ctx, logFactory, dnsOptions)
service.MustRegister[adapter.DNSRouter](ctx, dnsRouter)
networkManager, err := route.NewNetworkManager(ctx, logFactory.NewLogger("network"), routeOptions, dnsOptions)
router, err := route.NewRouter(
ctx,
logFactory,
common.PtrValueOrDefault(options.Route),
common.PtrValueOrDefault(options.DNS),
common.PtrValueOrDefault(options.NTP),
options.Inbounds,
options.PlatformInterface,
)
if err != nil {
return nil, E.Cause(err, "initialize network manager")
}
service.MustRegister[adapter.NetworkManager](ctx, networkManager)
connectionManager := route.NewConnectionManager(logFactory.NewLogger("connection"))
service.MustRegister[adapter.ConnectionManager](ctx, connectionManager)
router := route.NewRouter(ctx, logFactory, routeOptions, dnsOptions)
service.MustRegister[adapter.Router](ctx, router)
err = router.Initialize(routeOptions.Rules, routeOptions.RuleSet)
if err != nil {
return nil, E.Cause(err, "initialize router")
}
ntpOptions := common.PtrValueOrDefault(options.NTP)
var timeService *tls.TimeServiceWrapper
if ntpOptions.Enabled {
timeService = new(tls.TimeServiceWrapper)
service.MustRegister[ntp.TimeService](ctx, timeService)
}
for i, transportOptions := range dnsOptions.Servers {
var tag string
if transportOptions.Tag != "" {
tag = transportOptions.Tag
} else {
tag = F.ToString(i)
}
err = dnsTransportManager.Create(
ctx,
logFactory.NewLogger(F.ToString("dns/", transportOptions.Type, "[", tag, "]")),
tag,
transportOptions.Type,
transportOptions.Options,
)
if err != nil {
return nil, E.Cause(err, "initialize DNS server[", i, "]")
}
}
err = dnsRouter.Initialize(dnsOptions.Rules)
if err != nil {
return nil, E.Cause(err, "initialize dns router")
}
for i, endpointOptions := range options.Endpoints {
var tag string
if endpointOptions.Tag != "" {
tag = endpointOptions.Tag
} else {
tag = F.ToString(i)
}
endpointCtx := ctx
if tag != "" {
// TODO: remove this
endpointCtx = adapter.WithContext(endpointCtx, &adapter.InboundContext{
Outbound: tag,
})
}
err = endpointManager.Create(
endpointCtx,
router,
logFactory.NewLogger(F.ToString("endpoint/", endpointOptions.Type, "[", tag, "]")),
tag,
endpointOptions.Type,
endpointOptions.Options,
)
if err != nil {
return nil, E.Cause(err, "initialize endpoint[", i, "]")
}
return nil, E.Cause(err, "parse route options")
}
inbounds := make([]adapter.Inbound, 0, len(options.Inbounds))
outbounds := make([]adapter.Outbound, 0, len(options.Outbounds))
for i, inboundOptions := range options.Inbounds {
var in adapter.Inbound
var tag string
if inboundOptions.Tag != "" {
tag = inboundOptions.Tag
} else {
tag = F.ToString(i)
}
err = inboundManager.Create(
in, err = inbound.New(
ctx,
router,
logFactory.NewLogger(F.ToString("inbound/", inboundOptions.Type, "[", tag, "]")),
tag,
inboundOptions.Type,
inboundOptions.Options,
inboundOptions,
options.PlatformInterface,
)
if err != nil {
return nil, E.Cause(err, "initialize inbound[", i, "]")
return nil, E.Cause(err, "parse inbound[", i, "]")
}
inbounds = append(inbounds, in)
}
options.Outbounds = append(options.Outbounds, option.Outbound{
Tag: "Compatible",
Type: C.TypeDirect,
})
for i, outboundOptions := range options.Outbounds {
var out adapter.Outbound
var tag string
if outboundOptions.Tag != "" {
tag = outboundOptions.Tag
} else {
tag = F.ToString(i)
}
outboundCtx := ctx
if tag != "" {
// TODO: remove this
outboundCtx = adapter.WithContext(outboundCtx, &adapter.InboundContext{
Outbound: tag,
})
}
err = outboundManager.Create(
outboundCtx,
out, err = outbound.New(
ctx,
router,
logFactory.NewLogger(F.ToString("outbound/", outboundOptions.Type, "[", tag, "]")),
tag,
outboundOptions.Type,
outboundOptions.Options,
)
outboundOptions)
if err != nil {
return nil, E.Cause(err, "initialize outbound[", i, "]")
return nil, E.Cause(err, "parse outbound[", i, "]")
}
outbounds = append(outbounds, out)
}
for i, providerOptions := range options.Providers {
var tag string
if providerOptions.Tag != "" {
tag = providerOptions.Tag
} else {
tag = F.ToString(i)
}
err = providerManager.Create(
ctx,
router,
logFactory,
tag,
providerOptions.Type,
providerOptions.Options,
)
if err != nil {
return nil, E.Cause(err, "initialize provider[", i, "]")
}
}
for i, serviceOptions := range options.Services {
var tag string
if serviceOptions.Tag != "" {
tag = serviceOptions.Tag
} else {
tag = F.ToString(i)
}
err = serviceManager.Create(
ctx,
logFactory.NewLogger(F.ToString("service/", serviceOptions.Type, "[", tag, "]")),
tag,
serviceOptions.Type,
serviceOptions.Options,
)
if err != nil {
return nil, E.Cause(err, "initialize service[", i, "]")
}
}
outboundManager.Initialize(func() (adapter.Outbound, error) {
return direct.NewOutbound(
ctx,
router,
logFactory.NewLogger("outbound/direct"),
"direct",
option.DirectOutboundOptions{},
)
err = router.Initialize(inbounds, outbounds, func() adapter.Outbound {
out, oErr := outbound.New(ctx, router, logFactory.NewLogger("outbound/direct"), "direct", option.Outbound{Type: "direct", Tag: "default"})
common.Must(oErr)
outbounds = append(outbounds, out)
return out
})
dnsTransportManager.Initialize(func() (adapter.DNSTransport, error) {
return dnsTransportRegistry.CreateDNSTransport(
ctx,
logFactory.NewLogger("dns/local"),
"local",
C.DNSTypeLocal,
&option.LocalDNSServerOptions{},
)
})
if platformInterface != nil {
err = platformInterface.Initialize(networkManager)
if err != nil {
return nil, err
}
if options.PlatformInterface != nil {
err = options.PlatformInterface.Initialize(ctx, router)
if err != nil {
return nil, E.Cause(err, "initialize platform interface")
}
}
preServices1 := make(map[string]adapter.Service)
preServices2 := make(map[string]adapter.Service)
postServices := make(map[string]adapter.Service)
if needCacheFile {
cacheFile := cachefile.New(ctx, common.PtrValueOrDefault(experimentalOptions.CacheFile))
service.MustRegister[adapter.CacheFile](ctx, cacheFile)
internalServices = append(internalServices, cacheFile)
cacheFile := service.FromContext[adapter.CacheFile](ctx)
if cacheFile == nil {
cacheFile = cachefile.New(ctx, common.PtrValueOrDefault(experimentalOptions.CacheFile))
service.MustRegister[adapter.CacheFile](ctx, cacheFile)
}
preServices1["cache file"] = cacheFile
}
if needClashAPI {
clashAPIOptions := common.PtrValueOrDefault(experimentalOptions.ClashAPI)
clashAPIOptions.ModeList = experimental.CalculateClashModeList(options.Options)
clashServer, err := experimental.NewClashServer(ctx, logFactory.(log.ObservableFactory), clashAPIOptions)
clashServer, err := experimental.NewClashServer(ctx, router, logFactory.(log.ObservableFactory), clashAPIOptions)
if err != nil {
return nil, E.Cause(err, "create clash-server")
return nil, E.Cause(err, "create clash api server")
}
router.AppendTracker(clashServer)
service.MustRegister[adapter.ClashServer](ctx, clashServer)
internalServices = append(internalServices, clashServer)
router.SetClashServer(clashServer)
preServices2["clash api"] = clashServer
}
if needV2RayAPI {
v2rayServer, err := experimental.NewV2RayServer(logFactory.NewLogger("v2ray-api"), common.PtrValueOrDefault(experimentalOptions.V2RayAPI))
if err != nil {
return nil, E.Cause(err, "create v2ray-server")
return nil, E.Cause(err, "create v2ray api server")
}
if v2rayServer.StatsService() != nil {
router.AppendTracker(v2rayServer.StatsService())
internalServices = append(internalServices, v2rayServer)
service.MustRegister[adapter.V2RayServer](ctx, v2rayServer)
}
}
if ntpOptions.Enabled {
ntpDialer, err := dialer.New(ctx, ntpOptions.DialerOptions, ntpOptions.ServerIsDomain())
if err != nil {
return nil, E.Cause(err, "create NTP service")
}
ntpService := ntp.NewService(ntp.Options{
Context: ctx,
Dialer: ntpDialer,
Logger: logFactory.NewLogger("ntp"),
Server: ntpOptions.ServerOptions.Build(),
Interval: time.Duration(ntpOptions.Interval),
WriteToSystem: ntpOptions.WriteToSystem,
})
timeService.TimeService = ntpService
internalServices = append(internalServices, adapter.NewLifecycleService(ntpService, "ntp service"))
router.SetV2RayServer(v2rayServer)
preServices2["v2ray api"] = v2rayServer
}
return &Box{
network: networkManager,
endpoint: endpointManager,
inbound: inboundManager,
outbound: outboundManager,
provider: providerManager,
dnsTransport: dnsTransportManager,
service: serviceManager,
dnsRouter: dnsRouter,
connection: connectionManager,
router: router,
createdAt: createdAt,
logFactory: logFactory,
logger: logFactory.Logger(),
internalService: internalServices,
done: make(chan struct{}),
router: router,
inbounds: inbounds,
outbounds: outbounds,
createdAt: createdAt,
logFactory: logFactory,
logger: logFactory.Logger(),
preServices1: preServices1,
preServices2: preServices2,
postServices: postServices,
done: make(chan struct{}),
}, nil
}
@@ -489,19 +243,35 @@ func (s *Box) preStart() error {
if err != nil {
return E.Cause(err, "start logger")
}
err = adapter.StartNamed(s.logger, adapter.StartStateInitialize, s.internalService) // cache-file clash-api v2ray-api
for serviceName, service := range s.preServices1 {
if preService, isPreService := service.(adapter.PreStarter); isPreService {
monitor.Start("pre-start ", serviceName)
err := preService.PreStart()
monitor.Finish()
if err != nil {
return E.Cause(err, "pre-start ", serviceName)
}
}
}
for serviceName, service := range s.preServices2 {
if preService, isPreService := service.(adapter.PreStarter); isPreService {
monitor.Start("pre-start ", serviceName)
err := preService.PreStart()
monitor.Finish()
if err != nil {
return E.Cause(err, "pre-start ", serviceName)
}
}
}
err = s.router.PreStart()
if err != nil {
return E.Cause(err, "pre-start router")
}
err = s.startOutbounds()
if err != nil {
return err
}
err = adapter.Start(s.logger, adapter.StartStateInitialize, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.outbound, s.inbound, s.endpoint, s.provider, s.service)
if err != nil {
return err
}
err = adapter.Start(s.logger, adapter.StartStateStart, s.outbound, s.provider, s.dnsTransport, s.dnsRouter, s.network, s.connection, s.router)
if err != nil {
return err
}
return nil
return s.router.Start()
}
func (s *Box) start() error {
@@ -509,29 +279,64 @@ func (s *Box) start() error {
if err != nil {
return err
}
err = adapter.StartNamed(s.logger, adapter.StartStateStart, s.internalService)
for serviceName, service := range s.preServices1 {
err = service.Start()
if err != nil {
return E.Cause(err, "start ", serviceName)
}
}
for serviceName, service := range s.preServices2 {
err = service.Start()
if err != nil {
return E.Cause(err, "start ", serviceName)
}
}
for i, in := range s.inbounds {
var tag string
if in.Tag() == "" {
tag = F.ToString(i)
} else {
tag = in.Tag()
}
err = in.Start()
if err != nil {
return E.Cause(err, "initialize inbound/", in.Type(), "[", tag, "]")
}
}
err = s.postStart()
if err != nil {
return err
}
err = adapter.Start(s.logger, adapter.StartStateStart, s.inbound, s.endpoint, s.service)
return s.router.Cleanup()
}
func (s *Box) postStart() error {
for serviceName, service := range s.postServices {
err := service.Start()
if err != nil {
return E.Cause(err, "start ", serviceName)
}
}
// TODO: reorganize ALL start order
for _, out := range s.outbounds {
if lateOutbound, isLateOutbound := out.(adapter.PostStarter); isLateOutbound {
err := lateOutbound.PostStart()
if err != nil {
return E.Cause(err, "post-start outbound/", out.Tag())
}
}
}
err := s.router.PostStart()
if err != nil {
return err
}
err = adapter.Start(s.logger, adapter.StartStatePostStart, s.outbound, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.inbound, s.endpoint, s.provider, s.service)
if err != nil {
return err
}
err = adapter.StartNamed(s.logger, adapter.StartStatePostStart, s.internalService)
if err != nil {
return err
}
err = adapter.Start(s.logger, adapter.StartStateStarted, s.network, s.dnsTransport, s.dnsRouter, s.connection, s.router, s.outbound, s.inbound, s.endpoint, s.provider, s.service)
if err != nil {
return err
}
err = adapter.StartNamed(s.logger, adapter.StartStateStarted, s.internalService)
if err != nil {
return err
for _, in := range s.inbounds {
if lateInbound, isLateInbound := in.(adapter.PostStarter); isLateInbound {
err = lateInbound.PostStart()
if err != nil {
return E.Cause(err, "post-start inbound/", in.Tag())
}
}
}
return nil
}
@@ -543,63 +348,58 @@ func (s *Box) Close() error {
default:
close(s.done)
}
var err error
for _, closeItem := range []struct {
name string
service adapter.Lifecycle
}{
{"service", s.service},
{"endpoint", s.endpoint},
{"inbound", s.inbound},
{"provider", s.provider},
{"outbound", s.outbound},
{"router", s.router},
{"connection", s.connection},
{"dns-router", s.dnsRouter},
{"dns-transport", s.dnsTransport},
{"network", s.network},
} {
done := adapter.LogElapsed(s.logger, "close ", closeItem.name)
err = E.Append(err, closeItem.service.Close(), func(err error) error {
return E.Cause(err, "close ", closeItem.name)
monitor := taskmonitor.New(s.logger, C.StopTimeout)
var errors error
for serviceName, service := range s.postServices {
monitor.Start("close ", serviceName)
errors = E.Append(errors, service.Close(), func(err error) error {
return E.Cause(err, "close ", serviceName)
})
done()
monitor.Finish()
}
for _, lifecycleService := range s.internalService {
done := adapter.LogElapsed(s.logger, "close ", lifecycleService.Name())
err = E.Append(err, lifecycleService.Close(), func(err error) error {
return E.Cause(err, "close ", lifecycleService.Name())
for i, in := range s.inbounds {
monitor.Start("close inbound/", in.Type(), "[", i, "]")
errors = E.Append(errors, in.Close(), func(err error) error {
return E.Cause(err, "close inbound/", in.Type(), "[", i, "]")
})
done()
monitor.Finish()
}
done := adapter.LogElapsed(s.logger, "close logger")
err = E.Append(err, s.logFactory.Close(), func(err error) error {
return E.Cause(err, "close logger")
})
done()
return err
}
func (s *Box) Network() adapter.NetworkManager {
return s.network
for i, out := range s.outbounds {
monitor.Start("close outbound/", out.Type(), "[", i, "]")
errors = E.Append(errors, common.Close(out), func(err error) error {
return E.Cause(err, "close outbound/", out.Type(), "[", i, "]")
})
monitor.Finish()
}
monitor.Start("close router")
if err := common.Close(s.router); err != nil {
errors = E.Append(errors, err, func(err error) error {
return E.Cause(err, "close router")
})
}
monitor.Finish()
for serviceName, service := range s.preServices1 {
monitor.Start("close ", serviceName)
errors = E.Append(errors, service.Close(), func(err error) error {
return E.Cause(err, "close ", serviceName)
})
monitor.Finish()
}
for serviceName, service := range s.preServices2 {
monitor.Start("close ", serviceName)
errors = E.Append(errors, service.Close(), func(err error) error {
return E.Cause(err, "close ", serviceName)
})
monitor.Finish()
}
if err := common.Close(s.logFactory); err != nil {
errors = E.Append(errors, err, func(err error) error {
return E.Cause(err, "close logger")
})
}
return errors
}
func (s *Box) Router() adapter.Router {
return s.router
}
func (s *Box) Inbound() adapter.InboundManager {
return s.inbound
}
func (s *Box) Outbound() adapter.OutboundManager {
return s.outbound
}
func (s *Box) Endpoint() adapter.EndpointManager {
return s.endpoint
}
func (s *Box) LogFactory() log.Factory {
return s.logFactory
}
+85
View File
@@ -0,0 +1,85 @@
package box
import (
"strings"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/taskmonitor"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
)
func (s *Box) startOutbounds() error {
monitor := taskmonitor.New(s.logger, C.StartTimeout)
outboundTags := make(map[adapter.Outbound]string)
outbounds := make(map[string]adapter.Outbound)
for i, outboundToStart := range s.outbounds {
var outboundTag string
if outboundToStart.Tag() == "" {
outboundTag = F.ToString(i)
} else {
outboundTag = outboundToStart.Tag()
}
if _, exists := outbounds[outboundTag]; exists {
return E.New("outbound tag ", outboundTag, " duplicated")
}
outboundTags[outboundToStart] = outboundTag
outbounds[outboundTag] = outboundToStart
}
started := make(map[string]bool)
for {
canContinue := false
startOne:
for _, outboundToStart := range s.outbounds {
outboundTag := outboundTags[outboundToStart]
if started[outboundTag] {
continue
}
dependencies := outboundToStart.Dependencies()
for _, dependency := range dependencies {
if !started[dependency] {
continue startOne
}
}
started[outboundTag] = true
canContinue = true
if starter, isStarter := outboundToStart.(interface {
Start() error
}); isStarter {
monitor.Start("initialize outbound/", outboundToStart.Type(), "[", outboundTag, "]")
err := starter.Start()
monitor.Finish()
if err != nil {
return E.Cause(err, "initialize outbound/", outboundToStart.Type(), "[", outboundTag, "]")
}
}
}
if len(started) == len(s.outbounds) {
break
}
if canContinue {
continue
}
currentOutbound := common.Find(s.outbounds, func(it adapter.Outbound) bool {
return !started[outboundTags[it]]
})
var lintOutbound func(oTree []string, oCurrent adapter.Outbound) error
lintOutbound = func(oTree []string, oCurrent adapter.Outbound) error {
problemOutboundTag := common.Find(oCurrent.Dependencies(), func(it string) bool {
return !started[it]
})
if common.Contains(oTree, problemOutboundTag) {
return E.New("circular outbound dependency: ", strings.Join(oTree, " -> "), " -> ", problemOutboundTag)
}
problemOutbound := outbounds[problemOutboundTag]
if problemOutbound == nil {
return E.New("dependency[", problemOutboundTag, "] not found for outbound[", outboundTags[oCurrent], "]")
}
return lintOutbound(append(oTree, problemOutboundTag), problemOutbound)
}
return lintOutbound([]string{outboundTags[currentOutbound]}, currentOutbound)
}
return nil
}
-194
View File
@@ -1,194 +0,0 @@
// Command admin_panel_pack post-processes a directory of built SPA
// assets so it can be served straight from the Go binary via //go:embed.
// It does *not* generate any Go source any more — that responsibility
// moved to the embed directive in service/admin_panel/service.go.
//
// Three transformations happen here, all in-place inside the supplied
// directory:
//
// 1. Legacy WOFF (1.0) fallback fonts are deleted. Every browser made
// after 2014 reads WOFF2 natively, so shipping both formats roughly
// doubles the embedded font payload for no real-world benefit. The
// matching `,url(*.woff) format("woff")` segments are stripped from
// the bundled CSS in step (2) so the @font-face rules don't reference
// files that aren't shipped.
// 2. Bundled CSS is rewritten to drop those WOFF URL fragments.
// 3. Compressible text assets (.html, .css, .js, .svg, .json, .map) are
// pre-gzipped as companion `*.gz` files. The HTTP handler then either
// passes those bytes through verbatim with Content-Encoding: gzip or
// falls back to the raw file for the rare client that does not
// advertise gzip support — no on-line compression, no surprises.
// Already-compressed formats (.woff2, fonts, images) are skipped: gzip
// can't shrink them and the duplicate would only inflate the binary.
package main
import (
"bytes"
"compress/gzip"
"flag"
"fmt"
"io/fs"
"os"
"path/filepath"
"regexp"
"strings"
"time"
)
func main() {
dir := flag.String("dir", "service/admin_panel/dist", "directory of built SPA assets to post-process in place")
flag.Parse()
woffDropped, err := pruneWoff(*dir)
if err != nil {
fail("prune woff: %v", err)
}
cssRewritten, err := rewriteCSS(*dir)
if err != nil {
fail("rewrite css: %v", err)
}
stats, err := gzipText(*dir)
if err != nil {
fail("gzip text: %v", err)
}
fmt.Fprintf(os.Stderr, "post-processed %s: dropped %d woff, rewrote %d css, gzipped %d files (%d→%d bytes)\n",
*dir, woffDropped, cssRewritten, stats.gzipped, stats.totalRaw, stats.totalGz)
}
// pruneWoff deletes every legacy *.woff (WOFF 1.0) font under dir. The
// bundled CSS still references them on entry; rewriteCSS drops those
// references in a separate pass so the two operations stay independently
// testable.
func pruneWoff(dir string) (int, error) {
var n int
err := filepath.WalkDir(dir, func(p string, d fs.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
if d.IsDir() || !strings.EqualFold(filepath.Ext(p), ".woff") {
return nil
}
if err := os.Remove(p); err != nil {
return err
}
n++
return nil
})
return n, err
}
// woffRefAfterRE / woffRefBeforeRE match a single WOFF 1.0 entry inside a
// Vite-bundled CSS `src:` declaration. Vite minifies the rule to
// `src:url(./X.woff2) format("woff2"),url(./X.woff) format("woff");` so the
// "after" regex (the common case) eats the *leading* comma + woff entry,
// leaving only the woff2 source. We also handle the rare reverse ordering
// in a second pass.
var (
woffRefAfterRE = regexp.MustCompile(`,\s*url\([^)]*\.woff\)\s*format\(["']woff["']\)`)
woffRefBeforeRE = regexp.MustCompile(`url\([^)]*\.woff\)\s*format\(["']woff["']\)\s*,\s*`)
)
// rewriteCSS drops every reference to a *.woff URL from every *.css file
// under dir. Pairs naturally with pruneWoff: after both passes, no font
// URL in the bundle points at a file that isn't shipped.
func rewriteCSS(dir string) (int, error) {
var n int
err := filepath.WalkDir(dir, func(p string, d fs.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
if d.IsDir() || !strings.EqualFold(filepath.Ext(p), ".css") {
return nil
}
data, err := os.ReadFile(p)
if err != nil {
return err
}
out := woffRefAfterRE.ReplaceAll(data, nil)
out = woffRefBeforeRE.ReplaceAll(out, nil)
if bytes.Equal(out, data) {
return nil
}
if err := os.WriteFile(p, out, 0o644); err != nil {
return err
}
n++
return nil
})
return n, err
}
// gzipExts is the set of file extensions for which a `.gz` companion is
// generated. Anything not on this list is left alone — woff2/png/jpeg/etc.
// are already compressed, so gzip can only inflate them slightly while
// doubling the embedded payload.
var gzipExts = map[string]bool{
".html": true,
".css": true,
".js": true,
".mjs": true,
".svg": true,
".json": true,
".map": true,
".txt": true,
".xml": true,
".wasm": true,
}
type gzipStats struct {
gzipped int
totalRaw int64
totalGz int64
}
// gzipText produces a `<file>.gz` companion next to every text-like asset
// in dir, using gzip.BestCompression. The companion is dropped if the
// compressed bytes don't save at least 10 % over the raw file — same
// heuristic we used in the previous (Go-source-emitting) generation, just
// applied to disk files now.
func gzipText(dir string) (gzipStats, error) {
var stats gzipStats
err := filepath.WalkDir(dir, func(p string, d fs.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
if d.IsDir() {
return nil
}
ext := strings.ToLower(filepath.Ext(p))
if ext == ".gz" || !gzipExts[ext] {
return nil
}
raw, err := os.ReadFile(p)
if err != nil {
return err
}
var buf bytes.Buffer
w, err := gzip.NewWriterLevel(&buf, gzip.BestCompression)
if err != nil {
return err
}
// Reproducible: no mtime, no OS marker.
w.ModTime = time.Time{}
w.OS = 0xff
if _, err := w.Write(raw); err != nil {
return err
}
if err := w.Close(); err != nil {
return err
}
if buf.Len() > len(raw)*9/10 {
return nil
}
stats.gzipped++
stats.totalRaw += int64(len(raw))
stats.totalGz += int64(buf.Len())
return os.WriteFile(p+".gz", buf.Bytes(), 0o644)
})
return stats, err
}
func fail(format string, args ...any) {
fmt.Fprintf(os.Stderr, "admin_panel_pack: "+format+"\n", args...)
os.Exit(1)
}
+76 -83
View File
@@ -5,7 +5,6 @@ import (
"net/http"
"os"
"strconv"
"strings"
"time"
"github.com/sagernet/asc-go/asc"
@@ -100,33 +99,12 @@ findVersion:
}
func publishTestflight(ctx context.Context) error {
if len(os.Args) < 3 {
return E.New("platform required: ios, macos, or tvos")
}
var platform asc.Platform
switch os.Args[2] {
case "ios":
platform = asc.PlatformIOS
case "macos":
platform = asc.PlatformMACOS
case "tvos":
platform = asc.PlatformTVOS
default:
return E.New("unknown platform: ", os.Args[2])
}
tagVersion, err := build_shared.ReadTagVersion()
if err != nil {
return err
}
tag := tagVersion.VersionString()
releaseNotes := F.ToString("sing-box ", tagVersion.String())
if len(os.Args) >= 4 {
releaseNotes = strings.Join(os.Args[3:], " ")
}
client := createClient(20 * time.Minute)
client := createClient(10 * time.Minute)
log.Info(tag, " list build IDs")
buildIDsResponse, _, err := client.TestFlight.ListBuildIDsForBetaGroup(ctx, groupID, nil)
@@ -136,76 +114,91 @@ func publishTestflight(ctx context.Context) error {
buildIDs := common.Map(buildIDsResponse.Data, func(it asc.RelationshipData) string {
return it.ID
})
waitingForProcess := false
log.Info(string(platform), " list builds")
for {
builds, _, err := client.Builds.ListBuilds(ctx, &asc.ListBuildsQuery{
FilterApp: []string{appID},
FilterPreReleaseVersionPlatform: []string{string(platform)},
})
if err != nil {
return err
var platforms []asc.Platform
if len(os.Args) == 3 {
switch os.Args[2] {
case "ios":
platforms = []asc.Platform{asc.PlatformIOS}
case "macos":
platforms = []asc.Platform{asc.PlatformMACOS}
case "tvos":
platforms = []asc.Platform{asc.PlatformTVOS}
default:
return E.New("unknown platform: ", os.Args[2])
}
build := builds.Data[0]
log.Info(string(platform), " ", tag, " found build: ", build.ID, " (", *build.Attributes.Version, ")")
if !waitingForProcess && (common.Contains(buildIDs, build.ID) || time.Since(build.Attributes.UploadedDate.Time) > 30*time.Minute) {
log.Info(string(platform), " ", tag, " waiting for process")
time.Sleep(15 * time.Second)
continue
} else {
platforms = []asc.Platform{
asc.PlatformIOS,
asc.PlatformMACOS,
asc.PlatformTVOS,
}
if *build.Attributes.ProcessingState != "VALID" {
waitingForProcess = true
log.Info(string(platform), " ", tag, " waiting for process: ", *build.Attributes.ProcessingState)
time.Sleep(15 * time.Second)
continue
}
log.Info(string(platform), " ", tag, " list localizations")
localizations, _, err := client.TestFlight.ListBetaBuildLocalizationsForBuild(ctx, build.ID, nil)
if err != nil {
return err
}
localization := common.Find(localizations.Data, func(it asc.BetaBuildLocalization) bool {
return *it.Attributes.Locale == "en-US"
})
if localization.ID == "" {
log.Fatal(string(platform), " ", tag, " no en-US localization found")
}
if localization.Attributes == nil || localization.Attributes.WhatsNew == nil || *localization.Attributes.WhatsNew == "" {
log.Info(string(platform), " ", tag, " update localization")
_, _, err = client.TestFlight.UpdateBetaBuildLocalization(ctx, localization.ID, common.Ptr(releaseNotes))
}
for _, platform := range platforms {
log.Info(string(platform), " list builds")
for {
builds, _, err := client.Builds.ListBuilds(ctx, &asc.ListBuildsQuery{
FilterApp: []string{appID},
FilterPreReleaseVersionPlatform: []string{string(platform)},
})
if err != nil {
return err
}
}
log.Info(string(platform), " ", tag, " publish")
response, err := client.TestFlight.AddBuildsToBetaGroup(ctx, groupID, []string{build.ID})
if response != nil && (response.StatusCode == http.StatusUnprocessableEntity || response.StatusCode == http.StatusNotFound) {
log.Info("waiting for process")
time.Sleep(15 * time.Second)
continue
} else if err != nil {
return err
}
log.Info(string(platform), " ", tag, " list submissions")
betaSubmissions, _, err := client.TestFlight.ListBetaAppReviewSubmissions(ctx, &asc.ListBetaAppReviewSubmissionsQuery{
FilterBuild: []string{build.ID},
})
if err != nil {
return err
}
if len(betaSubmissions.Data) == 0 {
log.Info(string(platform), " ", tag, " create submission")
_, _, err = client.TestFlight.CreateBetaAppReviewSubmission(ctx, build.ID)
build := builds.Data[0]
if common.Contains(buildIDs, build.ID) || time.Since(build.Attributes.UploadedDate.Time) > 5*time.Minute {
log.Info(string(platform), " ", tag, " waiting for process")
time.Sleep(15 * time.Second)
continue
}
if *build.Attributes.ProcessingState != "VALID" {
log.Info(string(platform), " ", tag, " waiting for process: ", *build.Attributes.ProcessingState)
time.Sleep(15 * time.Second)
continue
}
log.Info(string(platform), " ", tag, " list localizations")
localizations, _, err := client.TestFlight.ListBetaBuildLocalizationsForBuild(ctx, build.ID, nil)
if err != nil {
if strings.Contains(err.Error(), "ANOTHER_BUILD_IN_REVIEW") {
log.Error(err)
break
return err
}
localization := common.Find(localizations.Data, func(it asc.BetaBuildLocalization) bool {
return *it.Attributes.Locale == "en-US"
})
if localization.ID == "" {
log.Fatal(string(platform), " ", tag, " no en-US localization found")
}
if localization.Attributes == nil || localization.Attributes.WhatsNew == nil || *localization.Attributes.WhatsNew == "" {
log.Info(string(platform), " ", tag, " update localization")
_, _, err = client.TestFlight.UpdateBetaBuildLocalization(ctx, localization.ID, common.Ptr(
F.ToString("sing-box ", tagVersion.String()),
))
if err != nil {
return err
}
}
log.Info(string(platform), " ", tag, " publish")
response, err := client.TestFlight.AddBuildsToBetaGroup(ctx, groupID, []string{build.ID})
if response != nil && response.StatusCode == http.StatusUnprocessableEntity {
log.Info("waiting for process")
time.Sleep(15 * time.Second)
continue
} else if err != nil {
return err
}
log.Info(string(platform), " ", tag, " list submissions")
betaSubmissions, _, err := client.TestFlight.ListBetaAppReviewSubmissions(ctx, &asc.ListBetaAppReviewSubmissionsQuery{
FilterBuild: []string{build.ID},
})
if err != nil {
return err
}
if len(betaSubmissions.Data) == 0 {
log.Info(string(platform), " ", tag, " create submission")
_, _, err = client.TestFlight.CreateBetaAppReviewSubmission(ctx, build.ID)
if err != nil {
return err
}
}
break
}
break
}
return nil
}
+30 -92
View File
@@ -5,7 +5,6 @@ import (
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
_ "github.com/sagernet/gomobile"
@@ -20,14 +19,12 @@ var (
debugEnabled bool
target string
platform string
// withTailscale bool
)
func init() {
flag.BoolVar(&debugEnabled, "debug", false, "enable debug")
flag.StringVar(&target, "target", "android", "target platform")
flag.StringVar(&platform, "platform", "", "specify platform")
// flag.BoolVar(&withTailscale, "with-tailscale", false, "build tailscale for iOS and tvOS")
}
func main() {
@@ -47,9 +44,7 @@ var (
sharedFlags []string
debugFlags []string
sharedTags []string
darwinTags []string
// memcTags []string
notMemcTags []string
iosTags []string
debugTags []string
)
@@ -60,38 +55,17 @@ func init() {
if err != nil {
currentTag = "unknown"
}
sharedFlags = append(sharedFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -X internal/godebug.defaultGODEBUG=multipathtcp=0 -s -w -buildid= -checklinkname=0")
debugFlags = append(debugFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -X internal/godebug.defaultGODEBUG=multipathtcp=0 -checklinkname=0")
sharedFlags = append(sharedFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -s -w -buildid=")
debugFlags = append(debugFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag)
sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_masque", "with_mtproxy", "with_trusttunnel", "with_openvpn", "with_sudoku", "with_utls", "with_naive_outbound", "with_clash_api", "badlinkname", "tfogo_checklinkname0")
darwinTags = append(darwinTags, "with_dhcp", "grpcnotrace")
// memcTags = append(memcTags, "with_tailscale")
sharedTags = append(sharedTags, "with_tailscale", "ts_omit_logtail", "ts_omit_ssh", "ts_omit_drive", "ts_omit_taildrop", "ts_omit_webclient", "ts_omit_doctor", "ts_omit_capture", "ts_omit_kube", "ts_omit_aws", "ts_omit_synology", "ts_omit_bird")
notMemcTags = append(notMemcTags, "with_low_memory")
sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_ech", "with_utls", "with_clash_api")
iosTags = append(iosTags, "with_dhcp", "with_low_memory", "with_conntrack")
debugTags = append(debugTags, "debug")
}
type AndroidBuildConfig struct {
AndroidAPI int
OutputName string
Tags []string
}
func buildAndroid() {
build_shared.FindSDK()
func filterTags(tags []string, exclude ...string) []string {
excludeMap := make(map[string]bool)
for _, tag := range exclude {
excludeMap[tag] = true
}
var result []string
for _, tag := range tags {
if !excludeMap[tag] {
result = append(result, tag)
}
}
return result
}
func checkJavaVersion() {
var javaPath string
javaHome := os.Getenv("JAVA_HOME")
if javaHome == "" {
@@ -107,87 +81,58 @@ func checkJavaVersion() {
if !strings.Contains(javaVersion, "openjdk 17") {
log.Fatal("java version should be openjdk 17")
}
}
func getAndroidBindTarget() string {
var bindTarget string
if platform != "" {
return platform
bindTarget = platform
} else if debugEnabled {
return "android/arm64"
bindTarget = "android/arm64"
} else {
bindTarget = "android"
}
return "android"
}
func buildAndroidVariant(config AndroidBuildConfig, bindTarget string) {
args := []string{
"bind",
"-v",
"-o", config.OutputName,
"-target", bindTarget,
"-androidapi", strconv.Itoa(config.AndroidAPI),
"-androidapi", "21",
"-javapkg=io.nekohasekai",
"-libname=box",
}
if !debugEnabled {
args = append(args, sharedFlags...)
} else {
args = append(args, debugFlags...)
}
args = append(args, "-tags", strings.Join(config.Tags, ","))
args = append(args, "-tags")
if !debugEnabled {
args = append(args, strings.Join(sharedTags, ","))
} else {
args = append(args, strings.Join(append(sharedTags, debugTags...), ","))
}
args = append(args, "./experimental/libbox")
command := exec.Command(build_shared.GoBinPath+"/gomobile", args...)
command.Stdout = os.Stdout
command.Stderr = os.Stderr
err := command.Run()
err = command.Run()
if err != nil {
log.Fatal(err)
}
const name = "libbox.aar"
copyPath := filepath.Join("..", "sing-box-for-android", "app", "libs")
if rw.IsDir(copyPath) {
copyPath, _ = filepath.Abs(copyPath)
err = rw.CopyFile(config.OutputName, filepath.Join(copyPath, config.OutputName))
err = rw.CopyFile(name, filepath.Join(copyPath, name))
if err != nil {
log.Fatal(err)
}
log.Info("copied ", config.OutputName, " to ", copyPath)
log.Info("copied to ", copyPath)
}
}
func buildAndroid() {
build_shared.FindSDK()
checkJavaVersion()
bindTarget := getAndroidBindTarget()
// Build main variant (SDK 23)
mainTags := append([]string{}, sharedTags...)
// mainTags = append(mainTags, memcTags...)
if debugEnabled {
mainTags = append(mainTags, debugTags...)
}
buildAndroidVariant(AndroidBuildConfig{
AndroidAPI: 23,
OutputName: "libbox.aar",
Tags: mainTags,
}, bindTarget)
// Build legacy variant (SDK 21, no naive outbound)
legacyTags := filterTags(sharedTags, "with_naive_outbound")
// legacyTags = append(legacyTags, memcTags...)
if debugEnabled {
legacyTags = append(legacyTags, debugTags...)
}
buildAndroidVariant(AndroidBuildConfig{
AndroidAPI: 21,
OutputName: "libbox-legacy.aar",
Tags: legacyTags,
}, bindTarget)
}
func buildApple() {
var bindTarget string
if platform != "" {
@@ -195,7 +140,7 @@ func buildApple() {
} else if debugEnabled {
bindTarget = "ios"
} else {
bindTarget = "ios,iossimulator,tvos,tvossimulator,macos"
bindTarget = "ios,tvos,macos"
}
args := []string{
@@ -203,27 +148,20 @@ func buildApple() {
"-v",
"-target", bindTarget,
"-libname=box",
"-tags-not-macos=with_low_memory",
}
//if !withTailscale {
// args = append(args, "-tags-macos="+strings.Join(memcTags, ","))
//}
if !debugEnabled {
args = append(args, sharedFlags...)
} else {
args = append(args, debugFlags...)
}
tags := append(sharedTags, darwinTags...)
//if withTailscale {
// tags = append(tags, memcTags...)
//}
if debugEnabled {
tags = append(tags, debugTags...)
tags := append(sharedTags, iosTags...)
args = append(args, "-tags")
if !debugEnabled {
args = append(args, strings.Join(tags, ","))
} else {
args = append(args, strings.Join(append(tags, debugTags...), ","))
}
args = append(args, "-tags", strings.Join(tags, ","))
args = append(args, "./experimental/libbox")
command := exec.Command(build_shared.GoBinPath+"/gomobile", args...)
+1 -1
View File
@@ -48,7 +48,7 @@ func FindSDK() {
}
func findNDK() bool {
const fixedVersion = "28.0.13004108"
const fixedVersion = "28.0.12674087"
const versionFile = "source.properties"
if fixedPath := filepath.Join(androidSDKPath, "ndk", fixedVersion); rw.IsFile(filepath.Join(fixedPath, versionFile)) {
androidNDKPath = fixedPath
-117
View File
@@ -1,117 +0,0 @@
package main
import (
"bytes"
"os"
"path/filepath"
"strings"
"github.com/sagernet/sing-box/log"
)
func main() {
err := filepath.Walk("docs", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
if !strings.HasSuffix(path, ".md") {
return nil
}
return processFile(path)
})
if err != nil {
log.Fatal(err)
}
}
func processFile(path string) error {
content, err := os.ReadFile(path)
if err != nil {
return err
}
lines := strings.Split(string(content), "\n")
modified := false
result := make([]string, 0, len(lines))
inQuoteBlock := false
materialLines := []int{} // indices of :material- lines in the block
for _, line := range lines {
// Check for quote block start
if strings.HasPrefix(line, "!!! quote \"") && strings.Contains(line, "sing-box") {
inQuoteBlock = true
materialLines = nil
result = append(result, line)
continue
}
// Inside a quote block
if inQuoteBlock {
trimmed := strings.TrimPrefix(line, " ")
isMaterialLine := strings.HasPrefix(trimmed, ":material-")
isEmpty := strings.TrimSpace(line) == ""
isIndented := strings.HasPrefix(line, " ")
if isMaterialLine {
materialLines = append(materialLines, len(result))
result = append(result, line)
continue
}
// Block ends when:
// - Empty line AFTER we've seen material lines, OR
// - Non-indented, non-empty line
blockEnds := (isEmpty && len(materialLines) > 0) || (!isEmpty && !isIndented)
if blockEnds {
// Process collected material lines
if len(materialLines) > 0 {
for j, idx := range materialLines {
isLast := j == len(materialLines)-1
resultLine := strings.TrimRight(result[idx], " ")
if !isLast {
// Add trailing two spaces for non-last lines
resultLine += " "
}
if result[idx] != resultLine {
modified = true
result[idx] = resultLine
}
}
}
inQuoteBlock = false
materialLines = nil
}
}
result = append(result, line)
}
// Handle case where file ends while still in a block
if inQuoteBlock && len(materialLines) > 0 {
for j, idx := range materialLines {
isLast := j == len(materialLines)-1
resultLine := strings.TrimRight(result[idx], " ")
if !isLast {
resultLine += " "
}
if result[idx] != resultLine {
modified = true
result[idx] = resultLine
}
}
}
if modified {
newContent := strings.Join(result, "\n")
if !bytes.Equal(content, []byte(newContent)) {
log.Info("formatted: ", path)
return os.WriteFile(path, []byte(newContent), 0o644)
}
}
return nil
}
+2 -2
View File
@@ -48,8 +48,8 @@ func GetRuntimeEnv(key string) (string, error) {
if readErr != nil {
return "", readErr
}
envStrings := strings.SplitSeq(string(data), "\n")
for envItem := range envStrings {
envStrings := strings.Split(string(data), "\n")
for _, envItem := range envStrings {
envItem = strings.TrimSuffix(envItem, "\r")
envKeyValue := strings.Split(envItem, "=")
if strings.EqualFold(strings.TrimSpace(envKeyValue[0]), key) {
+13 -22
View File
@@ -5,49 +5,40 @@ import (
"os"
"github.com/sagernet/sing-box/cmd/internal/build_shared"
"github.com/sagernet/sing-box/common/badversion"
"github.com/sagernet/sing-box/log"
)
var (
flagRunInCI bool
flagRunNightly bool
)
var nightly bool
func init() {
flag.BoolVar(&flagRunInCI, "ci", false, "Run in CI")
flag.BoolVar(&flagRunNightly, "nightly", false, "Run nightly")
flag.BoolVar(&nightly, "nightly", false, "Print nightly tag")
}
func main() {
flag.Parse()
var (
versionStr string
err error
)
if flagRunNightly {
var version badversion.Version
version, err = build_shared.ReadTagVersion()
if err == nil {
versionStr = version.String()
}
} else {
versionStr, err = build_shared.ReadTag()
}
if flagRunInCI {
if nightly {
version, err := build_shared.ReadTagVersionRev()
if err != nil {
log.Fatal(err)
}
var versionStr string
if version.PreReleaseIdentifier != "" {
versionStr = version.VersionString() + "-nightly"
} else {
version.Patch++
versionStr = version.VersionString() + "-nightly"
}
err = setGitHubEnv("version", versionStr)
if err != nil {
log.Fatal(err)
}
} else {
tag, err := build_shared.ReadTag()
if err != nil {
log.Error(err)
os.Stdout.WriteString("unknown\n")
} else {
os.Stdout.WriteString(versionStr + "\n")
os.Stdout.WriteString(tag + "\n")
}
}
}
-284
View File
@@ -1,284 +0,0 @@
package main
import (
"context"
"fmt"
"io"
"net/netip"
"os"
"os/exec"
"strings"
"syscall"
"time"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/include"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json"
"github.com/sagernet/sing/common/shell"
)
var iperf3Path string
func main() {
err := main0()
if err != nil {
log.Fatal(err)
}
}
func main0() error {
err := shell.Exec("sudo", "ls").Run()
if err != nil {
return err
}
results, err := runTests()
if err != nil {
return err
}
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")
return encoder.Encode(results)
}
func runTests() ([]TestResult, error) {
boxPaths := []string{
os.ExpandEnv("$HOME/Downloads/sing-box-1.11.15-darwin-arm64/sing-box"),
//"/Users/sekai/Downloads/sing-box-1.11.15-linux-arm64/sing-box",
"./sing-box",
}
stacks := []string{
"gvisor",
"system",
}
mtus := []int{
1500,
4064,
// 16384,
// 32768,
// 49152,
65535,
}
flagList := [][]string{
{},
}
var results []TestResult
for _, boxPath := range boxPaths {
for _, stack := range stacks {
for _, mtu := range mtus {
if strings.HasPrefix(boxPath, ".") {
for _, flags := range flagList {
result, err := testOnce(boxPath, stack, mtu, false, flags)
if err != nil {
return nil, err
}
results = append(results, *result)
}
} else {
result, err := testOnce(boxPath, stack, mtu, false, nil)
if err != nil {
return nil, err
}
results = append(results, *result)
}
}
}
}
return results, nil
}
type TestResult struct {
BoxPath string `json:"box_path"`
Stack string `json:"stack"`
MTU int `json:"mtu"`
Flags []string `json:"flags"`
MultiThread bool `json:"multi_thread"`
UploadSpeed string `json:"upload_speed"`
DownloadSpeed string `json:"download_speed"`
}
func testOnce(boxPath string, stackName string, mtu int, multiThread bool, flags []string) (result *TestResult, err error) {
testAddress := netip.MustParseAddr("1.1.1.1")
testConfig := option.Options{
Inbounds: []option.Inbound{
{
Type: C.TypeTun,
Options: &option.TunInboundOptions{
Address: []netip.Prefix{netip.MustParsePrefix("172.18.0.1/30")},
AutoRoute: true,
MTU: uint32(mtu),
Stack: stackName,
RouteAddress: []netip.Prefix{netip.PrefixFrom(testAddress, testAddress.BitLen())},
},
},
},
Route: &option.RouteOptions{
Rules: []option.Rule{
{
Type: C.RuleTypeDefault,
DefaultOptions: option.DefaultRule{
RawDefaultRule: option.RawDefaultRule{
IPCIDR: []string{testAddress.String()},
},
RuleAction: option.RuleAction{
Action: C.RuleActionTypeRouteOptions,
RouteOptionsOptions: option.RouteOptionsActionOptions{
OverrideAddress: "127.0.0.1",
},
},
},
},
},
AutoDetectInterface: true,
},
}
ctx := include.Context(context.Background())
tempConfig, err := os.CreateTemp("", "tun-bench-*.json")
if err != nil {
return
}
defer os.Remove(tempConfig.Name())
encoder := json.NewEncoderContext(ctx, tempConfig)
encoder.SetIndent("", " ")
err = encoder.Encode(testConfig)
if err != nil {
return nil, E.Cause(err, "encode test config")
}
tempConfig.Close()
var sudoArgs []string
if len(flags) > 0 {
sudoArgs = append(sudoArgs, "env")
sudoArgs = append(sudoArgs, flags...)
}
sudoArgs = append(sudoArgs, boxPath, "run", "-c", tempConfig.Name())
boxProcess := shell.Exec("sudo", sudoArgs...)
boxProcess.Stdout = &stderrWriter{}
boxProcess.Stderr = io.Discard
err = boxProcess.Start()
if err != nil {
return
}
if C.IsDarwin {
iperf3Path, err = exec.LookPath("iperf3-darwin")
} else {
iperf3Path, err = exec.LookPath("iperf3")
}
if err != nil {
return
}
serverProcess := shell.Exec(iperf3Path, "-s")
serverProcess.Stdout = io.Discard
serverProcess.Stderr = io.Discard
err = serverProcess.Start()
if err != nil {
return nil, E.Cause(err, "start iperf3 server")
}
time.Sleep(time.Second)
args := []string{"-c", testAddress.String()}
if multiThread {
args = append(args, "-P", "10")
}
uploadProcess := shell.Exec(iperf3Path, args...)
output, err := uploadProcess.Read()
if err != nil {
boxProcess.Process.Signal(syscall.SIGKILL)
serverProcess.Process.Signal(syscall.SIGKILL)
println(output)
return
}
uploadResult := common.SubstringBeforeLast(output, "iperf Done.")
uploadResult = common.SubstringBeforeLast(uploadResult, "sender")
uploadResult = common.SubstringBeforeLast(uploadResult, "bits/sec")
uploadResult = common.SubstringAfterLast(uploadResult, "Bytes")
uploadResult = strings.ReplaceAll(uploadResult, " ", "")
result = &TestResult{
BoxPath: boxPath,
Stack: stackName,
MTU: mtu,
Flags: flags,
MultiThread: multiThread,
UploadSpeed: uploadResult,
}
downloadProcess := shell.Exec(iperf3Path, append(args, "-R")...)
output, err = downloadProcess.Read()
if err != nil {
boxProcess.Process.Signal(syscall.SIGKILL)
serverProcess.Process.Signal(syscall.SIGKILL)
println(output)
return
}
downloadResult := common.SubstringBeforeLast(output, "iperf Done.")
downloadResult = common.SubstringBeforeLast(downloadResult, "receiver")
downloadResult = common.SubstringBeforeLast(downloadResult, "bits/sec")
downloadResult = common.SubstringAfterLast(downloadResult, "Bytes")
downloadResult = strings.ReplaceAll(downloadResult, " ", "")
result.DownloadSpeed = downloadResult
printArgs := []any{boxPath, stackName, mtu, "upload", uploadResult, "download", downloadResult}
if len(flags) > 0 {
printArgs = append(printArgs, "flags", strings.Join(flags, " "))
}
if multiThread {
printArgs = append(printArgs, "(-P 10)")
}
fmt.Println(printArgs...)
err = boxProcess.Process.Signal(syscall.SIGTERM)
if err != nil {
return
}
err = serverProcess.Process.Signal(syscall.SIGTERM)
if err != nil {
return
}
boxDone := make(chan struct{})
go func() {
boxProcess.Cmd.Wait()
close(boxDone)
}()
serverDone := make(chan struct{})
go func() {
serverProcess.Process.Wait()
close(serverDone)
}()
select {
case <-boxDone:
case <-time.After(2 * time.Second):
boxProcess.Process.Kill()
case <-time.After(4 * time.Second):
println("box process did not close!")
os.Exit(1)
}
select {
case <-serverDone:
case <-time.After(2 * time.Second):
serverProcess.Process.Kill()
case <-time.After(4 * time.Second):
println("server process did not close!")
os.Exit(1)
}
return
}
type stderrWriter struct{}
func (w *stderrWriter) Write(p []byte) (n int, err error) {
return os.Stderr.Write(p)
}
+4 -10
View File
@@ -13,14 +13,10 @@ import (
"github.com/sagernet/sing/common"
)
var (
flagRunInCI bool
flagRunNightly bool
)
var flagRunInCI bool
func init() {
flag.BoolVar(&flagRunInCI, "ci", false, "Run in CI")
flag.BoolVar(&flagRunNightly, "nightly", false, "Run nightly")
}
func main() {
@@ -39,7 +35,7 @@ func main() {
common.Must(os.Chdir(androidPath))
localProps := common.Must1(os.ReadFile("version.properties"))
var propsList [][]string
for propLine := range strings.SplitSeq(string(localProps), "\n") {
for _, propLine := range strings.Split(string(localProps), "\n") {
propsList = append(propsList, strings.Split(propLine, "="))
}
var (
@@ -50,23 +46,21 @@ func main() {
switch propPair[0] {
case "VERSION_NAME":
if propPair[1] != newVersion {
log.Info("updated version from ", propPair[1], " to ", newVersion)
versionUpdated = true
propPair[1] = newVersion
log.Info("updated version to ", newVersion)
}
case "GO_VERSION":
if propPair[1] != runtime.Version() {
log.Info("updated Go version from ", propPair[1], " to ", runtime.Version())
goVersionUpdated = true
propPair[1] = runtime.Version()
log.Info("updated Go version to ", runtime.Version())
}
}
}
if !(versionUpdated || goVersionUpdated) {
log.Info("version not changed")
return
} else if flagRunInCI && !flagRunNightly {
log.Fatal("version changed, commit changes first.")
}
for _, propPair := range propsList {
switch propPair[0] {
+2 -2
View File
@@ -71,12 +71,12 @@ func findAndReplace(objectsMap map[string]any, projectContent string, bundleIDLi
indexEnd := indexStart + strings.Index(projectContent[indexStart:], "}")
versionStart := indexStart + strings.Index(projectContent[indexStart:indexEnd], "MARKETING_VERSION = ") + 20
versionEnd := versionStart + strings.Index(projectContent[versionStart:indexEnd], ";")
version := strings.Trim(projectContent[versionStart:versionEnd], "\"")
version := projectContent[versionStart:versionEnd]
if version == newVersion {
continue
}
updated = true
projectContent = projectContent[:versionStart] + "\"" + newVersion + "\"" + projectContent[versionEnd:]
projectContent = projectContent[:versionStart] + newVersion + projectContent[versionEnd:]
}
return projectContent, updated
}
-162
View File
@@ -1,162 +0,0 @@
package main
import (
"encoding/csv"
"io"
"net/http"
"os"
"strings"
"github.com/sagernet/sing-box/log"
"golang.org/x/exp/slices"
)
func main() {
err := updateMozillaIncludedRootCAs()
if err != nil {
log.Error(err)
}
err = updateChromeIncludedRootCAs()
if err != nil {
log.Error(err)
}
}
func updateMozillaIncludedRootCAs() error {
response, err := http.Get("https://ccadb.my.salesforce-sites.com/mozilla/IncludedCACertificateReportPEMCSV")
if err != nil {
return err
}
defer response.Body.Close()
reader := csv.NewReader(response.Body)
header, err := reader.Read()
if err != nil {
return err
}
geoIndex := slices.Index(header, "Geographic Focus")
nameIndex := slices.Index(header, "Common Name or Certificate Name")
certIndex := slices.Index(header, "PEM Info")
generated := strings.Builder{}
generated.WriteString(`// Code generated by 'make update_certificates'. DO NOT EDIT.
package certificate
import "crypto/x509"
func newMozillaIncluded() *x509.CertPool {
pool := x509.NewCertPool()
`)
for {
record, err := reader.Read()
if err == io.EOF {
break
} else if err != nil {
return err
}
if record[geoIndex] == "China" {
continue
}
generated.WriteString("\n // ")
generated.WriteString(record[nameIndex])
generated.WriteString("\n")
generated.WriteString(" pool.AppendCertsFromPEM([]byte(`")
cert := record[certIndex]
// Remove single quotes
cert = cert[1 : len(cert)-1]
generated.WriteString(cert)
generated.WriteString("`))\n")
}
generated.WriteString("\treturn pool\n}\n")
return os.WriteFile("common/certificate/mozilla.go", []byte(generated.String()), 0o644)
}
func fetchChinaFingerprints() (map[string]bool, error) {
response, err := http.Get("https://ccadb.my.salesforce-sites.com/ccadb/AllCertificateRecordsCSVFormatv4")
if err != nil {
return nil, err
}
defer response.Body.Close()
reader := csv.NewReader(response.Body)
header, err := reader.Read()
if err != nil {
return nil, err
}
countryIndex := slices.Index(header, "Country")
fingerprintIndex := slices.Index(header, "SHA-256 Fingerprint")
chinaFingerprints := make(map[string]bool)
for {
record, err := reader.Read()
if err == io.EOF {
break
} else if err != nil {
return nil, err
}
if record[countryIndex] == "China" {
chinaFingerprints[record[fingerprintIndex]] = true
}
}
return chinaFingerprints, nil
}
func updateChromeIncludedRootCAs() error {
chinaFingerprints, err := fetchChinaFingerprints()
if err != nil {
return err
}
response, err := http.Get("https://ccadb.my.salesforce-sites.com/ccadb/RootCACertificatesIncludedByRSReportCSV")
if err != nil {
return err
}
defer response.Body.Close()
reader := csv.NewReader(response.Body)
header, err := reader.Read()
if err != nil {
return err
}
subjectIndex := slices.Index(header, "Subject")
statusIndex := slices.Index(header, "Google Chrome Status")
certIndex := slices.Index(header, "X.509 Certificate (PEM)")
fingerprintIndex := slices.Index(header, "SHA-256 Fingerprint")
generated := strings.Builder{}
generated.WriteString(`// Code generated by 'make update_certificates'. DO NOT EDIT.
package certificate
import "crypto/x509"
func newChromeIncluded() *x509.CertPool {
pool := x509.NewCertPool()
`)
for {
record, err := reader.Read()
if err == io.EOF {
break
} else if err != nil {
return err
}
if record[statusIndex] != "Included" {
continue
}
if chinaFingerprints[record[fingerprintIndex]] {
continue
}
generated.WriteString("\n // ")
generated.WriteString(record[subjectIndex])
generated.WriteString("\n")
generated.WriteString(" pool.AppendCertsFromPEM([]byte(`")
cert := record[certIndex]
// Remove single quotes if present
if len(cert) > 0 && cert[0] == '\'' {
cert = cert[1 : len(cert)-1]
}
generated.WriteString(cert)
generated.WriteString("`))\n")
}
generated.WriteString("\treturn pool\n}\n")
return os.WriteFile("common/certificate/chrome.go", []byte(generated.String()), 0o644)
}
+2 -2
View File
@@ -8,7 +8,7 @@ import (
"time"
"github.com/sagernet/sing-box/experimental/deprecated"
"github.com/sagernet/sing-box/include"
_ "github.com/sagernet/sing-box/include"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing/service"
"github.com/sagernet/sing/service/filemanager"
@@ -67,5 +67,5 @@ func preRun(cmd *cobra.Command, args []string) {
if len(configPaths) == 0 && len(configDirectories) == 0 {
configPaths = append(configPaths, "config.json")
}
globalCtx = include.Context(service.ContextWith(globalCtx, deprecated.NewStderrManager(log.StdLogger())))
globalCtx = service.ContextWith(globalCtx, deprecated.NewStderrManager(log.StdLogger()))
}
+1 -1
View File
@@ -38,7 +38,7 @@ func format() error {
return err
}
for _, optionsEntry := range optionsList {
optionsEntry.options, err = badjson.Omitempty(globalCtx, optionsEntry.options)
optionsEntry.options, err = badjson.Omitempty(optionsEntry.options)
if err != nil {
return err
}
+4 -1
View File
@@ -9,6 +9,8 @@ import (
"github.com/spf13/cobra"
)
var pqSignatureSchemesEnabled bool
var commandGenerateECHKeyPair = &cobra.Command{
Use: "ech-keypair <plain_server_name>",
Short: "Generate TLS ECH key pair",
@@ -22,11 +24,12 @@ var commandGenerateECHKeyPair = &cobra.Command{
}
func init() {
commandGenerateECHKeyPair.Flags().BoolVar(&pqSignatureSchemesEnabled, "pq-signature-schemes-enabled", false, "Enable PQ signature schemes")
commandGenerate.AddCommand(commandGenerateECHKeyPair)
}
func generateECHKeyPair(serverName string) error {
configPem, keyPem, err := tls.ECHKeygenDefault(serverName)
configPem, keyPem, err := tls.ECHKeygenDefault(serverName, pqSignatureSchemesEnabled)
if err != nil {
return err
}
+1 -1
View File
@@ -30,7 +30,7 @@ func init() {
}
func generateTLSKeyPair(serverName string) error {
privateKeyPem, publicKeyPem, err := tls.GenerateCertificate(nil, nil, time.Now, serverName, time.Now().AddDate(0, flagGenerateTLSKeyPairMonths, 0))
privateKeyPem, publicKeyPem, err := tls.GenerateKeyPair(time.Now, serverName, time.Now().AddDate(0, flagGenerateTLSKeyPairMonths, 0))
if err != nil {
return err
}
+3 -4
View File
@@ -61,17 +61,16 @@ func geoipExport(countryCode string) error {
outputFile *os.File
outputWriter io.Writer
)
switch flagGeoipExportOutput {
case "stdout":
if flagGeoipExportOutput == "stdout" {
outputWriter = os.Stdout
case flagGeoipExportDefaultOutput:
} else if flagGeoipExportOutput == flagGeoipExportDefaultOutput {
outputFile, err = os.Create("geoip-" + countryCode + ".json")
if err != nil {
return err
}
defer outputFile.Close()
outputWriter = outputFile
default:
} else {
outputFile, err = os.Create(flagGeoipExportOutput)
if err != nil {
return err
+3 -4
View File
@@ -43,17 +43,16 @@ func geositeExport(category string) error {
outputFile *os.File
outputWriter io.Writer
)
switch commandGeositeExportOutput {
case "stdout":
if commandGeositeExportOutput == "stdout" {
outputWriter = os.Stdout
case commandGeositeExportDefaultOutput:
} else if commandGeositeExportOutput == commandGeositeExportDefaultOutput {
outputFile, err = os.Create("geosite-" + category + ".json")
if err != nil {
return err
}
defer outputFile.Close()
outputWriter = outputFile
default:
} else {
outputFile, err = os.Create(commandGeositeExportOutput)
if err != nil {
return err
+18 -7
View File
@@ -18,7 +18,7 @@ import (
)
var commandMerge = &cobra.Command{
Use: "merge <output-path>",
Use: "merge <output>",
Short: "Merge configurations",
Run: func(cmd *cobra.Command, args []string) {
err := merge(args[0])
@@ -68,19 +68,29 @@ func merge(outputPath string) error {
}
func mergePathResources(options *option.Options) error {
for _, inbound := range options.Inbounds {
if tlsOptions, containsTLSOptions := inbound.Options.(option.InboundTLSOptionsWrapper); containsTLSOptions {
for index, inbound := range options.Inbounds {
rawOptions, err := inbound.RawOptions()
if err != nil {
return err
}
if tlsOptions, containsTLSOptions := rawOptions.(option.InboundTLSOptionsWrapper); containsTLSOptions {
tlsOptions.ReplaceInboundTLSOptions(mergeTLSInboundOptions(tlsOptions.TakeInboundTLSOptions()))
}
options.Inbounds[index] = inbound
}
for _, outbound := range options.Outbounds {
for index, outbound := range options.Outbounds {
rawOptions, err := outbound.RawOptions()
if err != nil {
return err
}
switch outbound.Type {
case C.TypeSSH:
mergeSSHOutboundOptions(outbound.Options.(*option.SSHOutboundOptions))
outbound.SSHOptions = mergeSSHOutboundOptions(outbound.SSHOptions)
}
if tlsOptions, containsTLSOptions := outbound.Options.(option.OutboundTLSOptionsWrapper); containsTLSOptions {
if tlsOptions, containsTLSOptions := rawOptions.(option.OutboundTLSOptionsWrapper); containsTLSOptions {
tlsOptions.ReplaceOutboundTLSOptions(mergeTLSOutboundOptions(tlsOptions.TakeOutboundTLSOptions()))
}
options.Outbounds[index] = outbound
}
return nil
}
@@ -128,12 +138,13 @@ func mergeTLSOutboundOptions(options *option.OutboundTLSOptions) *option.Outboun
return options
}
func mergeSSHOutboundOptions(options *option.SSHOutboundOptions) {
func mergeSSHOutboundOptions(options option.SSHOutboundOptions) option.SSHOutboundOptions {
if options.PrivateKeyPath != "" {
if content, err := os.ReadFile(os.ExpandEnv(options.PrivateKeyPath)); err == nil {
options.PrivateKey = trimStringArray(strings.Split(string(content), "\n"))
}
}
return options
}
func trimStringArray(array []string) []string {
+1 -18
View File
@@ -6,10 +6,8 @@ import (
"strings"
"github.com/sagernet/sing-box/common/srs"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/route/rule"
"github.com/sagernet/sing/common/json"
"github.com/spf13/cobra"
@@ -71,7 +69,7 @@ func compileRuleSet(sourcePath string) error {
if err != nil {
return err
}
err = srs.Write(outputFile, plainRuleSet.Options, downgradeRuleSetVersion(plainRuleSet.Version, plainRuleSet.Options))
err = srs.Write(outputFile, plainRuleSet.Options, plainRuleSet.Version)
if err != nil {
outputFile.Close()
os.Remove(outputPath)
@@ -80,18 +78,3 @@ func compileRuleSet(sourcePath string) error {
outputFile.Close()
return nil
}
func downgradeRuleSetVersion(version uint8, options option.PlainRuleSet) uint8 {
if version == C.RuleSetVersion4 && !rule.HasHeadlessRule(options.Rules, func(rule option.DefaultHeadlessRule) bool {
return rule.NetworkInterfaceAddress != nil && rule.NetworkInterfaceAddress.Size() > 0 ||
len(rule.DefaultInterfaceAddress) > 0
}) {
version = C.RuleSetVersion3
}
if version == C.RuleSetVersion3 && !rule.HasHeadlessRule(options.Rules, func(rule option.DefaultHeadlessRule) bool {
return len(rule.NetworkType) > 0 || rule.NetworkIsExpensive || rule.NetworkIsConstrained
}) {
version = C.RuleSetVersion2
}
return version
}
+2 -2
View File
@@ -5,7 +5,7 @@ import (
"os"
"strings"
"github.com/sagernet/sing-box/common/convertor/adguard"
"github.com/sagernet/sing-box/cmd/sing-box/internal/convertor/adguard"
"github.com/sagernet/sing-box/common/srs"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
@@ -54,7 +54,7 @@ func convertRuleSet(sourcePath string) error {
var rules []option.HeadlessRule
switch flagRuleSetConvertType {
case "adguard":
rules, err = adguard.ToOptions(reader, log.StdLogger())
rules, err = adguard.Convert(reader)
case "":
return E.New("source type is required")
default:
-24
View File
@@ -6,10 +6,7 @@ import (
"strings"
"github.com/sagernet/sing-box/common/srs"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json"
"github.com/spf13/cobra"
@@ -53,11 +50,6 @@ func decompileRuleSet(sourcePath string) error {
if err != nil {
return err
}
if hasRule(ruleSet.Options.Rules, func(rule option.DefaultHeadlessRule) bool {
return len(rule.AdGuardDomain) > 0
}) {
return E.New("unable to decompile binary AdGuard rules to rule-set.")
}
var outputPath string
if flagRuleSetDecompileOutput == flagRuleSetDecompileDefaultOutput {
if strings.HasSuffix(sourcePath, ".srs") {
@@ -83,19 +75,3 @@ func decompileRuleSet(sourcePath string) error {
outputFile.Close()
return nil
}
func hasRule(rules []option.HeadlessRule, cond func(rule option.DefaultHeadlessRule) bool) bool {
for _, rule := range rules {
switch rule.Type {
case C.RuleTypeDefault:
if cond(rule.DefaultOptions) {
return true
}
case C.RuleTypeLogical:
if hasRule(rule.LogicalOptions.Rules, cond) {
return true
}
}
}
return false
}
+2 -12
View File
@@ -2,17 +2,15 @@ package main
import (
"bytes"
"context"
"io"
"os"
"path/filepath"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/srs"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/route/rule"
"github.com/sagernet/sing-box/route"
E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
"github.com/sagernet/sing/common/json"
@@ -57,14 +55,6 @@ func ruleSetMatch(sourcePath string, domain string) error {
if err != nil {
return E.Cause(err, "read rule-set")
}
if flagRuleSetMatchFormat == "" {
switch filepath.Ext(sourcePath) {
case ".json":
flagRuleSetMatchFormat = C.RuleSetFormatSource
case ".srs":
flagRuleSetMatchFormat = C.RuleSetFormatBinary
}
}
var ruleSet option.PlainRuleSetCompat
switch flagRuleSetMatchFormat {
case C.RuleSetFormatSource:
@@ -93,7 +83,7 @@ func ruleSetMatch(sourcePath string, domain string) error {
}
for i, ruleOptions := range plainRuleSet.Rules {
var currentRule adapter.HeadlessRule
currentRule, err = rule.NewHeadlessRule(context.Background(), ruleOptions)
currentRule, err = route.NewHeadlessRule(nil, ruleOptions)
if err != nil {
return E.Cause(err, "parse rule_set.rules.[", i, "]")
}
-162
View File
@@ -1,162 +0,0 @@
package main
import (
"bytes"
"io"
"os"
"path/filepath"
"sort"
"strings"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json"
"github.com/sagernet/sing/common/json/badjson"
"github.com/sagernet/sing/common/rw"
"github.com/spf13/cobra"
)
var (
ruleSetPaths []string
ruleSetDirectories []string
)
var commandRuleSetMerge = &cobra.Command{
Use: "merge <output-path>",
Short: "Merge rule-set source files",
Run: func(cmd *cobra.Command, args []string) {
err := mergeRuleSet(args[0])
if err != nil {
log.Fatal(err)
}
},
Args: cobra.ExactArgs(1),
}
func init() {
commandRuleSetMerge.Flags().StringArrayVarP(&ruleSetPaths, "config", "c", nil, "set input rule-set file path")
commandRuleSetMerge.Flags().StringArrayVarP(&ruleSetDirectories, "config-directory", "C", nil, "set input rule-set directory path")
commandRuleSet.AddCommand(commandRuleSetMerge)
}
type RuleSetEntry struct {
content []byte
path string
options option.PlainRuleSetCompat
}
func readRuleSetAt(path string) (*RuleSetEntry, error) {
var (
configContent []byte
err error
)
if path == "stdin" {
configContent, err = io.ReadAll(os.Stdin)
} else {
configContent, err = os.ReadFile(path)
}
if err != nil {
return nil, E.Cause(err, "read config at ", path)
}
options, err := json.UnmarshalExtendedContext[option.PlainRuleSetCompat](globalCtx, configContent)
if err != nil {
return nil, E.Cause(err, "decode config at ", path)
}
return &RuleSetEntry{
content: configContent,
path: path,
options: options,
}, nil
}
func readRuleSet() ([]*RuleSetEntry, error) {
var optionsList []*RuleSetEntry
for _, path := range ruleSetPaths {
optionsEntry, err := readRuleSetAt(path)
if err != nil {
return nil, err
}
optionsList = append(optionsList, optionsEntry)
}
for _, directory := range ruleSetDirectories {
entries, err := os.ReadDir(directory)
if err != nil {
return nil, E.Cause(err, "read rule-set directory at ", directory)
}
for _, entry := range entries {
if !strings.HasSuffix(entry.Name(), ".json") || entry.IsDir() {
continue
}
optionsEntry, err := readRuleSetAt(filepath.Join(directory, entry.Name()))
if err != nil {
return nil, err
}
optionsList = append(optionsList, optionsEntry)
}
}
sort.Slice(optionsList, func(i, j int) bool {
return optionsList[i].path < optionsList[j].path
})
return optionsList, nil
}
func readRuleSetAndMerge() (option.PlainRuleSetCompat, error) {
optionsList, err := readRuleSet()
if err != nil {
return option.PlainRuleSetCompat{}, err
}
if len(optionsList) == 1 {
return optionsList[0].options, nil
}
var optionVersion uint8
for _, options := range optionsList {
if optionVersion < options.options.Version {
optionVersion = options.options.Version
}
}
var mergedMessage json.RawMessage
for _, options := range optionsList {
mergedMessage, err = badjson.MergeJSON(globalCtx, options.options.RawMessage, mergedMessage, false)
if err != nil {
return option.PlainRuleSetCompat{}, E.Cause(err, "merge config at ", options.path)
}
}
mergedOptions, err := json.UnmarshalExtendedContext[option.PlainRuleSetCompat](globalCtx, mergedMessage)
if err != nil {
return option.PlainRuleSetCompat{}, E.Cause(err, "unmarshal merged config")
}
mergedOptions.Version = optionVersion
return mergedOptions, nil
}
func mergeRuleSet(outputPath string) error {
mergedOptions, err := readRuleSetAndMerge()
if err != nil {
return err
}
buffer := new(bytes.Buffer)
encoder := json.NewEncoder(buffer)
encoder.SetIndent("", " ")
err = encoder.Encode(mergedOptions)
if err != nil {
return E.Cause(err, "encode config")
}
if existsContent, err := os.ReadFile(outputPath); err != nil {
if string(existsContent) == buffer.String() {
return nil
}
}
err = rw.MkdirParent(outputPath)
if err != nil {
return err
}
err = os.WriteFile(outputPath, buffer.Bytes(), 0o644)
if err != nil {
return err
}
outputPath, _ = filepath.Abs(outputPath)
os.Stderr.WriteString(outputPath + "\n")
return nil
}
+2 -3
View File
@@ -61,15 +61,14 @@ func upgradeRuleSet(sourcePath string) error {
log.Info("already up-to-date")
return nil
}
plainRuleSetCompat.Options, err = plainRuleSetCompat.Upgrade()
plainRuleSet, err := plainRuleSetCompat.Upgrade()
if err != nil {
return err
}
plainRuleSetCompat.Version = C.RuleSetVersionCurrent
buffer := new(bytes.Buffer)
encoder := json.NewEncoder(buffer)
encoder.SetIndent("", " ")
err = encoder.Encode(plainRuleSetCompat)
err = encoder.Encode(plainRuleSet)
if err != nil {
return E.Cause(err, "encode config")
}
+3 -3
View File
@@ -57,7 +57,7 @@ func readConfigAt(path string) (*OptionsEntry, error) {
if err != nil {
return nil, E.Cause(err, "read config at ", path)
}
options, err := json.UnmarshalExtendedContext[option.Options](globalCtx, configContent)
options, err := json.UnmarshalExtended[option.Options](configContent)
if err != nil {
return nil, E.Cause(err, "decode config at ", path)
}
@@ -109,13 +109,13 @@ func readConfigAndMerge() (option.Options, error) {
}
var mergedMessage json.RawMessage
for _, options := range optionsList {
mergedMessage, err = badjson.MergeJSON(globalCtx, options.options.RawMessage, mergedMessage, false)
mergedMessage, err = badjson.MergeJSON(options.options.RawMessage, mergedMessage, false)
if err != nil {
return option.Options{}, E.Cause(err, "merge config at ", options.path)
}
}
var mergedOptions option.Options
err = mergedOptions.UnmarshalJSONContext(globalCtx, mergedMessage)
err = mergedOptions.UnmarshalJSON(mergedMessage)
if err != nil {
return option.Options{}, E.Cause(err, "unmarshal merged config")
}
+5 -10
View File
@@ -1,9 +1,6 @@
package main
import (
"errors"
"os"
"github.com/sagernet/sing-box"
E "github.com/sagernet/sing/common/exceptions"
N "github.com/sagernet/sing/common/network"
@@ -26,11 +23,9 @@ func init() {
func createPreStartedClient() (*box.Box, error) {
options, err := readConfigAndMerge()
if err != nil {
if !(errors.Is(err, os.ErrNotExist) && len(configDirectories) == 0 && len(configPaths) == 1) || configPaths[0] != "config.json" {
return nil, err
}
return nil, err
}
instance, err := box.New(box.Options{Context: globalCtx, Options: options})
instance, err := box.New(box.Options{Options: options})
if err != nil {
return nil, E.Cause(err, "create service")
}
@@ -41,11 +36,11 @@ func createPreStartedClient() (*box.Box, error) {
return instance, nil
}
func createDialer(instance *box.Box, outboundTag string) (N.Dialer, error) {
func createDialer(instance *box.Box, network string, outboundTag string) (N.Dialer, error) {
if outboundTag == "" {
return instance.Outbound().Default(), nil
return instance.Router().DefaultOutbound(N.NetworkName(network))
} else {
outbound, loaded := instance.Outbound().Outbound(outboundTag)
outbound, loaded := instance.Router().Outbound(outboundTag)
if !loaded {
return nil, E.New("outbound not found: ", outboundTag)
}
+1 -1
View File
@@ -45,7 +45,7 @@ func connect(address string) error {
return err
}
defer instance.Close()
dialer, err := createDialer(instance, commandToolsFlagOutbound)
dialer, err := createDialer(instance, commandConnectFlagNetwork, commandToolsFlagOutbound)
if err != nil {
return err
}
+1 -1
View File
@@ -48,7 +48,7 @@ func fetch(args []string) error {
httpClient = &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
dialer, err := createDialer(instance, commandToolsFlagOutbound)
dialer, err := createDialer(instance, network, commandToolsFlagOutbound)
if err != nil {
return nil, err
}
+2 -2
View File
@@ -16,13 +16,13 @@ import (
)
func initializeHTTP3Client(instance *box.Box) error {
dialer, err := createDialer(instance, commandToolsFlagOutbound)
dialer, err := createDialer(instance, N.NetworkUDP, commandToolsFlagOutbound)
if err != nil {
return err
}
http3Client = &http.Client{
Transport: &http3.Transport{
Dial: func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (*quic.Conn, error) {
Dial: func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
destination := M.ParseSocksaddr(addr)
udpConn, dErr := dialer.DialContext(ctx, N.NetworkUDP, destination)
if dErr != nil {
+4 -2
View File
@@ -4,10 +4,12 @@ import (
"context"
"os"
"github.com/sagernet/sing-box/common/settings"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/common/ntp"
"github.com/spf13/cobra"
@@ -43,7 +45,7 @@ func syncTime() error {
if err != nil {
return err
}
dialer, err := createDialer(instance, commandToolsFlagOutbound)
dialer, err := createDialer(instance, N.NetworkUDP, commandToolsFlagOutbound)
if err != nil {
return err
}
@@ -57,7 +59,7 @@ func syncTime() error {
return err
}
if commandSyncTimeWrite {
err = ntp.SetSystemTime(response.Time)
err = settings.SetSystemTime(response.Time)
if err != nil {
return E.Cause(err, "write time to system")
}

Some files were not shown because too many files have changed in this diff Show More