Compare commits

...
Author SHA1 Message Date
ginuerzh d584b7ac61 bump x to v0.10.7 2026-05-31 22:49:10 +08:00
ginuerzh 56e2a1c496 fix: disable UPX compression to resolve #863 startup regression
UPX --best/--lzma/--brute adds ~3s startup time on low-spec systems
(linux/arm) due to in-memory decompression on every invocation of gost -V.
Disabled by default; opt in via GORELEASER_UPX=true for release builds
that need it.
2026-05-31 22:25:57 +08:00
ginuerzh b0bea19275 bump x to v0.10.6 2026-05-31 22:13:42 +08:00
ginuerzh cd64f2edd3 bump x to v0.10.5 2026-05-31 19:50:49 +08:00
ginuerzh 5f04c84e32 bump core to v0.4.1 2026-05-31 19:40:28 +08:00
ginuerzh 600a64e611 bump x to v0.10.4 2026-05-31 17:47:52 +08:00
ginuerzh 3d6b16686b bump x to v0.10.3 2026-05-29 00:29:26 +08:00
ginuerzh 44684d40c3 add CLAUDE.md with build, CLI, and lifecycle documentation 2026-05-23 00:00:56 +08:00
ginuerzh 2be36abe75 bump x to v0.10.1, go-shadowsocks2 to v0.1.3; add gost binary to .gitignore 2026-05-22 23:21:30 +08:00
ginuerzh 8db62785fa Merge pull request #862: Add e2e test cases for shadowsocks
Add comprehensive e2e tests covering TCP and UDP shadowsocks
connections with various cipher modes (aes-128-gcm, aes-256-gcm,
chacha20, 2022-blake3-aes-128, 2022-blake3-aes-256, including
multi-PSK variants).
2026-05-22 23:09:42 +08:00
RMT 8740e6f258 Add e2e test cases for shadowsocks 2026-05-22 14:28:17 +08:00
ginuerzh d4c9ef5056 add masque connector, dialer, and handler registrations; update x to v0.10.0 2026-05-21 23:03:49 +08:00
RMT c06eb0d331 WIP 2026-04-26 22:18:07 +08:00
RMT c8b48dc248 WIP 2026-04-26 22:18:07 +08:00
azoway 45d94cf391 Update install.sh
在alpine服务器上运行安装脚本报错:
curl: (3) URL rejected: Malformed input to a URL function

排查后发现,当前版本部分会匹配出来2个版本的下载链接:
gost_3.2.6_linux_amd64.tar.gz
gost_3.2.6_linux_amd64v3.tar.gz

修改后默认取第一个兼容性更好的版本
2026-04-26 22:16:06 +08:00
nivesh bc96fe3918 streamline download/install process
(get binary only, eliminate unnecessary intermediate files)
2026-04-22 00:25:59 +08:00
nivesh 646d3f906c enhance portability (detect user-preferred bash, replace all greps with awk) 2026-04-22 00:25:59 +08:00
nivesh 4c69940f1e Fix #835 2026-04-22 00:25:59 +08:00
David Manouchehri 3d1f6fcbbb add masque connector, dialer, and handler 2026-04-22 00:23:53 +08:00
ginuerzh e388426ec6 go1.26 2026-04-21 23:59:31 +08:00
ginuerzh 340ba32ef0 v3.2.6 2025-11-22 22:47:02 +08:00
ginuerzh 96551d5fa5 metrics: fix server conn wrapper (#797) 2025-10-11 22:07:41 +08:00
ginuerzh 8d05a6ed93 add multiple entrypoints for tunnel 2025-10-09 22:33:31 +08:00
ginuerzh 0348a16aa9 fix panic for channel close (#779) 2025-09-20 10:06:15 +08:00
ginuerzh 50934e0978 fix sniffing for websocket 2025-09-04 21:32:34 +08:00
ginuerzh c2ed9c6f07 add service option for plugin 2025-08-29 23:38:29 +08:00
ginuerzh 3b9da4e260 go1.25 2025-08-21 22:53:28 +08:00
ginuerzh f0a67a1108 fix bugs 2025-08-21 22:24:42 +08:00
ginuerzh 59c9638ce6 add bypass and admission matcher 2025-08-13 21:27:36 +08:00
ginuerzh 49fa28882f fix issue #760 2025-08-10 19:01:10 +08:00
ginuerzh 08c617b54e v3.2.3 2025-08-09 21:01:25 +08:00
ginuerzh d03b0e2360 v3.2.2 2025-08-05 20:46:21 +08:00
ginuerzh 245d610baf without cancel context 2025-08-05 20:25:24 +08:00
ginuerzh f01f0c9215 fix ws listener 2025-08-05 00:19:51 +08:00
ginuerzh 9b6e9d9cae add context for conn 2025-08-04 19:34:54 +08:00
ginuerzh 1a0e2b06ac add proxyProtocol support for dialer 2025-08-03 15:38:57 +08:00
ginuerzh de8bb498db http2: added non-connect request support #749 2025-07-30 21:44:46 +08:00
ginuerzh 1f735d0649 v3.2.0 2025-07-29 09:15:55 +08:00
ginuerzh d173d167da fix tungo for windows and darwin 2025-07-28 21:21:33 +08:00
ginuerzh b593fdb952 add upx for binary compression 2025-07-26 16:43:49 +08:00
ginuerzh d448628fea add tun2socks (tungo) 2025-07-26 16:43:22 +08:00
ginuerzh 0bfc7f10cd add vtun handle and listener 2025-07-23 22:49:59 +08:00
ginuerzh a24b29c8c2 get real client IP from request 2025-07-15 20:21:52 +08:00
ginuerzh 87af3da1b6 add src field for logger and recorder 2025-07-02 21:49:03 +08:00
ginuerzh dc6fe595e0 read config from stdin #701 2025-06-28 18:20:28 +08:00
ginuerzh db4a0a9259 goreleaser: added linux/loong64 2025-06-28 18:13:45 +08:00
Meng Zhuo 62a097c5e4 enable riscv64 in install.sh 2025-06-27 23:36:31 +08:00
ginuerzh b51cecbbfd add new web APIs 2025-06-25 21:31:22 +08:00
ginuerzh 66a260abd1 fix metrics 2025-06-24 21:23:00 +08:00
ginuerzh 1d3603f9ed Merge pull request #713 from ravitheg/FixSSHVulnerability
Fix ssh vulnerability
2025-05-30 15:21:37 +08:00
ravitheg 952c61c1a2 Update go.sum 2025-05-27 14:09:22 -07:00
ravitheg 6d61ab82db Update go.mod 2025-05-27 14:08:56 -07:00
ginuerzh f61bb2fd72 revert to go1.23 2025-02-18 21:43:03 +08:00
ginuerzh 4c2835db04 go1.24 2025-02-18 21:16:47 +08:00
ginuerzh d662b1fd46 router handler: add cache for sd service 2025-02-09 16:19:40 +08:00
ginuerzh 015923fa5d add entrypoint for router handler 2025-02-08 23:11:18 +08:00
ginuerzh f66fce9d49 feat: add router handler & connector 2025-02-07 15:51:51 +08:00
ginuerzh 982a93eee4 add limiter.scope option for service 2025-01-20 23:27:04 +08:00
ginuerzh 758251d3f9 update go.mod 2025-01-10 21:50:18 +08:00
ginuerzh a1e48e164b update config parsing 2025-01-10 21:41:55 +08:00
ginuerzh 581dd74bbb add config hot reload 2025-01-08 23:16:55 +08:00
ginuerzh 3c7a984aa3 v3.0.0 2024-12-31 20:19:49 +08:00
ginuerzh 2a9b7e7d9b fix panic for stats wrapper 2024-12-27 20:43:42 +08:00
ginuerzh ab2b9714ee add traffic reset for stats observer 2024-12-24 20:13:40 +08:00
ginuerzh 6d38c24d88 handle tls for tunnel entrypoint 2024-12-23 21:35:58 +08:00
ginuerzh f376db2000 fix issue #625 2024-12-18 19:06:59 +08:00
ginuerzh 161d96f582 fix observer for http2 2024-12-16 20:49:41 +08:00
ginuerzh 128c0c3117 update go.sum 2024-12-11 22:31:42 +08:00
ginuerzh 66ce980c36 fix webtransport 2024-12-11 22:28:31 +08:00
ginuerzh 829148d3f8 fix ipv6 port for redirect 2024-12-11 22:05:30 +08:00
ginuerzh c45f148a88 add unix domain socket support for api & metrics services 2024-11-22 22:51:16 +08:00
ginuerzh fdc88af4ac fix http keepalive for forwarding 2024-11-17 16:17:31 +08:00
ginuerzh c41c5bf79a add routing rule for node 2024-11-15 20:30:35 +08:00
ginuerzh b3eeb338fb add custom http response header for reverse proxy 2024-11-07 11:08:38 +08:00
ginuerzh 72f185bbf6 add compression flag option for http request 2024-11-02 20:43:44 +08:00
ginuerzh a7599990a8 update deps 2024-11-01 18:19:23 +08:00
ginuerzh 17ca5600d3 update sample rate for websocket recording 2024-10-31 19:16:12 +08:00
ginuerzh 32ccfe483c fix udp port forwarding 2024-10-22 22:57:18 +08:00
ginuerzh 1d0eb06938 sniffing: fix race condition when sniffing websocket frames 2024-10-20 19:24:40 +08:00
ginuerzh 1fa5067d14 sniffing: full websocket frame recording 2024-10-19 20:41:29 +08:00
ginuerzh 7ddfef85a5 sniffing websocket frame 2024-10-19 19:37:21 +08:00
ginuerzh fa98777ab1 fix handler sniffing 2024-10-16 23:03:27 +08:00
ginuerzh e53486efe0 add more fields for log 2024-10-16 22:17:54 +08:00
ginuerzh 881ebfad5b add ClientAddr for websocket conn 2024-10-16 20:48:07 +08:00
ginuerzh d5bb691b38 tunnel: fix http switching protocols 2024-10-15 19:38:43 +08:00
ginuerzh 24c13b861a update tunnel entrypoint 2024-10-15 18:49:21 +08:00
ginuerzh d6daa8bf56 update sniffer for forward & tunnel handler 2024-10-14 23:10:58 +08:00
ginuerzh d18539ef66 recorder: add input/output traffic stats for handler recorder object 2024-10-11 20:39:29 +08:00
ginuerzh 48b0a690c5 update Dockerfile 2024-10-11 13:10:15 +08:00
ginuerzh a7037a27bf update Dockerfile 2024-10-11 11:28:06 +08:00
ginuerzh ac9960de6d update Dockerfile 2024-10-11 00:48:47 +08:00
ginuerzh 404e099907 update github actions 2024-10-11 00:05:00 +08:00
ginuerzh 94cd590142 add keepalive option for http handler 2024-10-10 22:52:04 +08:00
ginuerzh d3809ec634 add sniffer utility for handler traffic sniffing 2024-10-02 22:53:07 +08:00
ginuerzh efb4da6fa6 add traffic sniffing for handler 2024-09-27 20:54:24 +08:00
ginuerzh 2ec8584e96 add route field for reocrder 2024-09-24 20:25:10 +08:00
ginuerzh f05f5cf862 add tls handshake for recorder 2024-09-20 21:28:09 +08:00
ginuerzh bf3018b5b1 add http body for handler recorder 2024-09-16 19:46:24 +08:00
ginuerzh 073af6163e fix recorder clientIP 2024-09-15 18:38:55 +08:00
ginuerzh ef07551e01 add clientIP for handler recorder object 2024-09-15 18:30:02 +08:00
ginuerzh 8077c039f3 update handler recorder object 2024-09-15 12:14:01 +08:00
ginuerzh 33c8f3595a add recorder for handler 2024-09-14 23:24:17 +08:00
ginuerzh 87bff8cac6 add sniffing.fallback option for red handler 2024-09-04 22:46:03 +08:00
ginuerzh d52fcccf06 add scope parameter for traffic limiter 2024-08-31 09:42:03 +08:00
ginuerzh 18610d4608 fix timeout in router 2024-08-06 21:35:19 +08:00
ginuerzh c1de9e4e72 close udp connection when timeout 2024-08-06 18:35:26 +08:00
ginuerzh 1f7c080043 add riscv64 in buildx 2024-08-01 22:05:15 +08:00
ginuerzh b091f72900 fix issue #546 2024-08-01 20:54:21 +08:00
ginuerzh 8e50e9c085 fix ssu handler port exhaustion 2024-07-31 21:03:59 +08:00
ginuerzh 7a35d25c5c add http body rewrite for forward handler 2024-07-19 20:47:01 +08:00
ginuerzh 8e311e7891 add support for icmpv6 2024-07-15 20:42:30 +08:00
ginuerzh 17fc806c2d fix ipv6 for tproxy 2024-07-11 22:39:15 +08:00
ginuerzh b21fd4a22b fix port range parsing 2024-07-10 23:00:06 +08:00
ginuerzh 3e8a025c45 update go.sum 2024-07-08 22:54:09 +08:00
ginuerzh 0d7a6f8091 add port range support for service 2024-07-08 22:52:01 +08:00
ginuerzh 4a2a2a00de update go.sum 2024-07-04 23:12:01 +08:00
ginuerzh c71e128fec bump deps 2024-07-04 23:09:05 +08:00
ginuerzh 1400b5ff5d remove content-length header for http proxy response 2024-06-25 22:26:11 +08:00
ginuerzh cd4fad8c08 add dialTimeout option for service 2024-06-25 21:44:39 +08:00
ginuerzh 56a68ae06f fix netns for socks5 and relay handler 2024-06-24 21:42:37 +08:00
ginuerzh 5d7100f749 add linux network namespace support for listener and dialer 2024-06-21 23:41:27 +08:00
ginuerzh 12871a4ff3 update README.md 2024-06-18 20:59:46 +08:00
ginuerzh 6130bbc075 update go.mod 2024-06-13 23:29:34 +08:00
ginuerzh 85d4fcaf7d add observePeriod option for observer 2024-06-13 22:45:28 +08:00
ginuerzh 7904e571c1 fix #498 2024-06-11 21:58:48 +08:00
ginuerzh 8253c41de6 fix marker for selector 2024-06-07 22:43:48 +08:00
ginuerzh 2148d10def Merge pull request #488 from cgroschupp/update-mod
remove unnecessary replace and update gost modules
2024-05-31 21:25:47 +08:00
Christian Groschupp 8846c69c05 remove unnecessary replace and update gost modules 2024-05-29 18:40:40 +02:00
ginuerzh 2161b97064 add p2p option for tun handler 2024-04-26 20:58:27 +08:00
ginuerzh e245526b33 update README.md 2024-04-25 22:56:57 +08:00
ginuerzh 60389894c0 update go.mod 2024-04-25 21:50:49 +08:00
dependabot[bot] 9ab142ac99 Bump golang.org/x/net from 0.19.0 to 0.23.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.19.0 to 0.23.0.
- [Commits](https://github.com/golang/net/compare/v0.19.0...v0.23.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-24 23:19:10 +08:00
ginuerzh be1b0627d1 Merge pull request #451 from jalalsaberi/master
Add Chinese and English README Button
2024-04-24 23:18:33 +08:00
dependabot[bot] f4115b867d Bump github.com/quic-go/quic-go from 0.40.1 to 0.42.0
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.40.1 to 0.42.0.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.40.1...v0.42.0)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-24 23:11:03 +08:00
kLiHz a513417d7e fixup moving to Docker actions 2024-04-24 23:10:14 +08:00
kLiHz 58bd3d062b bump setup-go in workflow 2024-04-24 23:10:14 +08:00
kLiHz d2b79c13a6 move to Docker actions since it is archived 2024-04-24 23:10:14 +08:00
kLiHz fedd7a7b07 fixup bumping ghaction-docker-buildx 2024-04-24 23:10:14 +08:00
kLiHz 27f4b6abeb bump ghaction-docker-buildx in workflow 2024-04-24 23:10:14 +08:00
kLiHz d4aadbbc14 bump delete-older-releases in workflow 2024-04-24 23:10:14 +08:00
kLiHz 4508747635 fix deprecated set-output command in workflow 2024-04-24 23:10:14 +08:00
dependabot[bot] 50844821f8 Bump google.golang.org/protobuf from 1.31.0 to 1.33.0
Bumps google.golang.org/protobuf from 1.31.0 to 1.33.0.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-24 23:09:36 +08:00
Jalal Saberi 29ec7c94ad Add Chinese and English README Button 2024-04-10 19:09:02 +03:30
Jalal Saberi 53d6706b5d Add Chinese and English README Button 2024-04-10 18:53:53 +03:30
ginuerzh 594418db53 added url path rewriting for forwarder node 2024-01-31 23:20:35 +08:00
ginuerzh 72cd708dfe fix tunnel connector selection 2024-01-28 18:57:34 +08:00
ginuerzh b576bb5645 fix tunnel weight 2024-01-28 18:34:44 +08:00
ginuerzh 8c529e3595 add weight for tunnel connector 2024-01-27 23:32:50 +08:00
ginuerzh b75e133719 fix hop http plugin 2024-01-27 21:33:24 +08:00
dependabot[bot] abfbf23842 Bump github.com/quic-go/quic-go from 0.40.0 to 0.40.1
Bumps [github.com/quic-go/quic-go](https://github.com/quic-go/quic-go) from 0.40.0 to 0.40.1.
- [Release notes](https://github.com/quic-go/quic-go/releases)
- [Changelog](https://github.com/quic-go/quic-go/blob/master/Changelog.md)
- [Commits](https://github.com/quic-go/quic-go/compare/v0.40.0...v0.40.1)

---
updated-dependencies:
- dependency-name: github.com/quic-go/quic-go
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-18 17:33:31 +08:00
ginuerzh 42d62550bf fix deadlock in websocket client conn 2024-01-12 23:50:27 +08:00
ginuerzh 69ba5864ad fix #390 2024-01-08 21:25:41 +08:00
ginuerzh fdd3eb61c3 add auth CLI support for api & metrics 2024-01-07 19:42:14 +08:00
ginuerzh f68bfdb149 add observer 2024-01-03 20:56:24 +08:00
ginuerzh 9e4bca84f1 fix tls handshake sniffing 2023-12-27 20:08:12 +08:00
ginuerzh 925ff89b78 fix issue #376 2023-12-25 22:11:03 +08:00
ginuerzh ca077d418a fix issue #372 2023-12-20 22:00:23 +08:00
ginuerzh 7264fca4f8 parsing config directly from cmd flag -C 2023-12-19 21:45:34 +08:00
ginuerzh bc37fac037 added logger group for service 2023-12-19 21:44:58 +08:00
ginuerzh dc48c4a3b2 fix auth for file handler 2023-12-16 14:33:52 +08:00
ginuerzh 310614663a check date for nightly trigger 2023-12-02 13:03:16 +08:00
ginuerzh 8f094d86b0 fix issue #338 2023-11-30 19:46:29 +08:00
ginuerzh 638c780acd update go.mod 2023-11-29 21:18:54 +08:00
ginuerzh 1f20f199c0 fix tun config 2023-11-20 20:43:27 +08:00
ginuerzh 8dc6146f79 fix go.mod 2023-11-19 20:03:23 +08:00
ginuerzh ed29b34c68 add logger component 2023-11-19 19:57:02 +08:00
ginuerzh b41aea03da add web api for router 2023-11-19 16:17:01 +08:00
ginuerzh 2c17e4417d add logger option for tun router 2023-11-19 14:41:10 +08:00
ginuerzh ea8ff5f77a add router component 2023-11-19 14:24:48 +08:00
ginuerzh 6762957c65 add traffic limiter for proxy handler 2023-11-18 18:30:04 +08:00
ginuerzh 4c934cd737 add more config options for kcp 2023-11-16 22:19:42 +08:00
ginuerzh 0d494f5ef2 fix #335 2023-11-16 20:39:42 +08:00
ginuerzh bf1bab7d84 fix race condition in relay udp conn 2023-11-14 22:37:33 +08:00
ginuerzh b8383b1076 add range port support for forwarder node 2023-11-14 19:43:57 +08:00
ginuerzh 345da28f01 update ingress interface 2023-11-13 20:42:45 +08:00
ginuerzh 907420d18b add webtransport tunnel 2023-11-10 21:30:20 +08:00
ginuerzh c1437794f8 add path option for hop 2023-11-09 20:36:21 +08:00
ginuerzh c2df5650fb add prefer and only options for resolver 2023-11-08 21:09:08 +08:00
ginuerzh 23506579e7 improve udp listener 2023-11-07 23:11:38 +08:00
ginuerzh 969db8691b update README 2023-11-03 17:48:56 +08:00
ginuerzh 3b0a2f1bae update sd 2023-11-02 22:34:11 +08:00
ginuerzh b2ed4ae9fd update sd 2023-11-02 20:54:59 +08:00
ginuerzh b2784011d0 add service discovery for tunnel 2023-10-31 23:00:32 +08:00
ginuerzh d4e00683c3 add tls options 2023-10-29 10:28:46 +08:00
ginuerzh 471513896d update nightly build schedule 2023-10-28 22:48:59 +08:00
ginuerzh 6967278600 add nightly build 2023-10-28 22:41:14 +08:00
ginuerzh 2898732c20 improve tunnel entrypoint 2023-10-27 22:15:53 +08:00
dependabot[bot] bb0c0450e8 Bump google.golang.org/grpc from 1.58.1 to 1.58.3
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.58.1 to 1.58.3.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.58.1...v1.58.3)

---
updated-dependencies:
- dependency-name: google.golang.org/grpc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-27 22:11:52 +08:00
ginuerzh 6bb7dfea8f fix #315 2023-10-25 23:13:39 +08:00
ginuerzh e27d2bc593 set smux version to 1 2023-10-24 20:49:19 +08:00
ginuerzh 3144d61ecd generate random tunnel ID 2023-10-20 23:57:43 +08:00
ginuerzh e4b68d385a fix race condition 2023-10-19 23:50:27 +08:00
ginuerzh a91300d078 get real client ip for http forwarding 2023-10-18 21:23:38 +08:00
ginuerzh b8785eb71e fix race condition when forwarding http 2023-10-18 19:20:43 +08:00
ginuerzh 67fcd929be fix http traffic forwarding 2023-10-18 14:33:38 +08:00
ginuerzh 48c262bf71 fix websocket for forward handler 2023-10-17 23:26:04 +08:00
ginuerzh 05c35005e9 fix websocket for forward handler 2023-10-17 23:06:02 +08:00
ginuerzh f6112773a1 default to smux version 2 for tunnel 2023-10-17 22:16:28 +08:00
ginuerzh 61002b7c9c add mux config 2023-10-17 21:56:29 +08:00
ginuerzh f8a19e0829 fix http handler for tunnel 2023-10-16 23:56:36 +08:00
ginuerzh b1ace73943 update forward handler 2023-10-16 23:17:51 +08:00
ginuerzh 3d0e993498 fix compile error for serial 2023-10-15 23:57:49 +08:00
ginuerzh 9cbc875965 add tunnel handler and connector 2023-10-15 15:40:49 +08:00
dependabot[bot] 139b934fc6 Bump golang.org/x/net from 0.15.0 to 0.17.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.15.0 to 0.17.0.
- [Commits](https://github.com/golang/net/compare/v0.15.0...v0.17.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-10-14 21:07:47 +08:00
ginuerzh c1d9228eee add auther for metrics 2023-10-09 21:30:43 +08:00
ginuerzh 2ea7dc250a fix #239 2023-10-08 22:05:39 +08:00
ginuerzh be33046c16 add proxy protocol support for relay tunnel and rtcp 2023-10-08 19:50:12 +08:00
ginuerzh d85b8d487b fix socks5 connector 2023-10-04 16:37:10 +08:00
ginuerzh ab8d77bb5e fix issue #280 2023-09-30 17:55:22 +08:00
ginuerzh 8640596064 go1.21 2023-09-28 21:31:17 +08:00
ginuerzh 8a699e1906 add reload and plugin support for hop 2023-09-28 21:05:44 +08:00
ginuerzh 0d41f5edc8 update go.sum 2023-09-21 21:55:23 +08:00
ginuerzh 87364d2494 add client addr for auth plugin 2023-09-21 20:01:25 +08:00
ginuerzh 6982b8af63 add HTTP based plugin 2023-09-20 22:58:48 +08:00
ginuerzh 0b1540b23a add client ID for plugin service 2023-09-19 22:39:42 +08:00
ginuerzh 1bbeeb7e66 add unix/serial dialer and connector 2023-09-18 23:18:27 +08:00
ginuerzh 5d4db6e377 add recorder for serial handler 2023-09-18 21:13:52 +08:00
ginuerzh 05d06a2718 add recorder for serial handler 2023-09-18 09:43:44 +08:00
ginuerzh 420b36b2f8 update README.md 2023-09-17 00:23:11 +08:00
ginuerzh 3883a4493a add support for unix domain socket 2023-09-16 23:15:49 +08:00
ginuerzh 355aaa7690 fix typos 2023-09-16 21:52:00 +08:00
ginuerzh c73c98974c add support for serial(COM) port redirector 2023-09-16 21:50:54 +08:00
Sam Sesh 98c9cc2821 update 2023-09-15 23:47:01 +08:00
127.0.0.1:443 b48d2c0dbc Update README.md 2023-09-15 23:47:01 +08:00
127.0.0.1:443 b7266f4660 Update README_en.md 2023-09-15 23:47:01 +08:00
Sam Sesh 6883c32157 set 777 per 2023-09-15 23:47:01 +08:00
Sam Sesh f1c5f7598c check root 2023-09-15 23:47:01 +08:00
Sam Sesh c31242efbb add install script 2023-09-15 23:47:01 +08:00
dependabot[bot] 6ee632cee2 Bump github.com/gin-gonic/gin from 1.9.0 to 1.9.1
Bumps [github.com/gin-gonic/gin](https://github.com/gin-gonic/gin) from 1.9.0 to 1.9.1.
- [Release notes](https://github.com/gin-gonic/gin/releases)
- [Changelog](https://github.com/gin-gonic/gin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gin-gonic/gin/compare/v1.9.0...v1.9.1)

---
updated-dependencies:
- dependency-name: github.com/gin-gonic/gin
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-09-15 23:44:45 +08:00
ginuerzh 8e2060582e add timeout for sniffing 2023-05-21 15:54:57 +08:00
dependabot[bot] 410b4ddf53 Bump github.com/gin-gonic/gin from 1.8.2 to 1.9.0
Bumps [github.com/gin-gonic/gin](https://github.com/gin-gonic/gin) from 1.8.2 to 1.9.0.
- [Release notes](https://github.com/gin-gonic/gin/releases)
- [Changelog](https://github.com/gin-gonic/gin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gin-gonic/gin/compare/v1.8.2...v1.9.0)

---
updated-dependencies:
- dependency-name: github.com/gin-gonic/gin
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-05-10 17:17:53 +08:00
ginuerzh 0b6474d836 increase transport buffer size 2023-05-01 14:06:37 +08:00
ginuerzh 4b6d6e7e7c add token for plugin 2023-04-20 19:07:55 +08:00
ginuerzh b2434dd05b add plugin system 2023-04-18 20:55:04 +08:00
ginuerzh 3d15dedab2 add async option for dns handler 2023-04-14 19:17:10 +08:00
ginuerzh 436864ca92 fix issue #206 2023-04-12 21:32:13 +08:00
ginuerzh 4847f9ee9f add support for windows service 2023-03-31 14:51:08 +08:00
ginuerzh a88b44d01d fix #174: load default CA from ca.pem 2023-03-21 20:25:13 +08:00
ginuerzh 45f1cc2efc fix #188 2023-03-20 18:31:47 +08:00
ginuerzh bfa1530ef6 fix grpc dialer 2023-03-08 00:01:36 +08:00
ginuerzh f02c9810f2 update go.mod 2023-02-26 13:54:17 +08:00
ginuerzh fda6214c12 fix #180: add default server name for tls client config 2023-02-26 13:48:42 +08:00
dependabot[bot] acb8c5bd53 bump golang.org/x/net from 0.5.0 to 0.7.0
Bumps [golang.org/x/net](https://github.com/golang/net) from 0.5.0 to 0.7.0.
- [Release notes](https://github.com/golang/net/releases)
- [Commits](https://github.com/golang/net/compare/v0.5.0...v0.7.0)

---
updated-dependencies:
- dependency-name: golang.org/x/net
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-26 13:43:20 +08:00
ginuerzh 3f53858c83 update version 2023-02-14 18:57:06 +08:00
ginuerzh a379565412 fix relay connect handler 2023-02-14 18:57:06 +08:00
dependabot[bot] 69089b790f Bump github.com/pion/dtls/v2 from 2.1.5 to 2.2.4
Bumps [github.com/pion/dtls/v2](https://github.com/pion/dtls) from 2.1.5 to 2.2.4.
- [Release notes](https://github.com/pion/dtls/releases)
- [Commits](https://github.com/pion/dtls/compare/v2.1.5...v2.2.4)

---
updated-dependencies:
- dependency-name: github.com/pion/dtls/v2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-14 09:48:22 +08:00
ginuerzh 1c2d9b2a5b relay: fix routing for http traffic from entrypoint 2023-02-12 20:44:50 +08:00
ginuerzh 8d852b62cf relay: add direct routing for tunnel 2023-02-06 21:18:35 +08:00
ginuerzh a80dec0dc1 go1.20 2023-02-04 18:48:20 +08:00
ginuerzh 62ca8ff2de add tunnel option for relay 2023-02-02 23:28:04 +08:00
ginuerzh b8504f7f28 update go.mod 2023-02-02 20:00:12 +08:00
ginuerzh 95a2f0d649 add UDP support for reverse proxy tunnel 2023-02-02 19:20:22 +08:00
ginuerzh d810224e7b add .goreleaser.yaml 2023-01-31 21:24:54 +08:00
ginuerzh db36804bfa add goreleaser github action 2023-01-31 21:24:16 +08:00
ginuerzh ad8af1942d update .gitignore 2023-01-31 19:36:10 +08:00
ginuerzh 3d01f74f7c fix nil route panic 2023-01-31 18:08:50 +08:00
ginuerzh 6b05bcb0ab add auth support for forwarder node 2023-01-31 14:07:20 +08:00
ginuerzh 799c95bfb4 forward non-HTTP traffic based on host 2023-01-30 21:10:59 +08:00
ginuerzh de0a584175 fix http traffic forwarding 2023-01-30 14:40:40 +08:00
ginuerzh 381b1c9bf5 fix http traffic forwarding 2023-01-29 23:33:54 +08:00
ginuerzh ed7d72bfd8 update go.mod 2023-01-29 20:53:33 +08:00
ginuerzh 98aef6ba90 forwarder: add http node settings 2023-01-29 20:33:58 +08:00
ginuerzh dfde6efdeb relay: add private tunnel 2023-01-29 11:57:57 +08:00
ginuerzh 8858598cf0 update go.mod 2023-01-20 10:29:39 +08:00
ginuerzh c765789076 fix race condition in config updating 2023-01-20 10:28:32 +08:00
ginuerzh cf49a3ae46 add webapi for ingress 2023-01-15 17:46:24 +08:00
ginuerzh fa47726c3d add tunnel feature for relay 2023-01-14 13:18:45 +08:00
ginuerzh c351b849e6 case-insensitive metadata key 2023-01-11 22:28:43 +08:00
ginuerzh 44fca4e04c grpc: cancel stream when done 2022-12-30 19:38:51 +08:00
ginuerzh a795923980 fix dtls 2022-12-23 18:58:24 +08:00
ginuerzh d3283d6278 tun: support multiple IPs 2022-12-22 17:52:05 +08:00
ginuerzh 4b3e711adb update grpc 2022-12-21 18:21:23 +08:00
ginuerzh 258d9f5b26 fix traffic limiter 2022-12-19 19:38:38 +08:00
Carlos Ibáñez 5d9d33f368 [main] Add -- cmd flag separator to start different Gost processes 2022-12-15 11:12:21 +08:00
Carlos Ibáñez fec33e62ea [cmd] buildConfigFromCmd: Include the process id on config names 2022-12-15 11:12:21 +08:00
ginuerzh 2f0da6993b v3.0.0-rc.1 2022-12-02 17:58:32 +08:00
ginuerzh 39cb9c65d9 grpc.dialer: do not resolve server address 2022-12-01 19:24:52 +08:00
segfault-bilibili 4ef4448249 insert services and nodes to loaded config 2022-11-28 17:20:54 +08:00
segfault-bilibili 1151ecd2a4 fix typo 2022-11-28 17:20:54 +08:00
ginuerzh df3533b4ef don't resolve server addr for tun handler 2022-11-25 18:17:11 +08:00
ginuerzh 2400e29fe0 add dtls tunnel 2022-11-18 18:27:25 +08:00
ginuerzh 41bb4cdbb0 add http3 reverse proxy 2022-11-12 17:16:43 +08:00
ginuerzh 4a192bc1b3 add wildcard supports for vhost 2022-11-12 13:45:27 +08:00
ginuerzh f17b2d2e96 add vhost for port forwarding 2022-11-11 22:25:52 +08:00
ginuerzh e771534920 v3.0.0-rc.0 2022-11-05 16:54:44 +08:00
ginuerzh 68c311a7d1 fix compile error 2022-11-05 16:39:11 +08:00
ginuerzh 1c9974340b fix traffic limiter 2022-11-05 16:29:57 +08:00
ginuerzh 09c12b013c add hooks for service 2022-11-03 21:32:12 +08:00
ginuerzh b86d7ee06d add log rotation 2022-10-20 21:10:25 +08:00
soffchen 8274b62672 add support for linux/amd64v3, windows/amd64v3 2022-10-07 09:27:22 +08:00
ginuerzh 7f924fdeb6 fix proxy protocol 2022-09-28 11:53:25 +08:00
ginuerzh 5d797eac43 add hop 2022-09-22 18:59:56 +08:00
ginuerzh 2c29028a3b update README 2022-09-14 21:13:11 +08:00
ginuerzh e8071d9b65 update limiter 2022-09-14 20:06:14 +08:00
ginuerzh 50cf4edd1f add direct dialer and connector #63 2022-09-08 22:43:29 +08:00
ginuerzh 3d5f0f93fd added proxy protocol for listener 2022-09-08 21:33:19 +08:00
ginuerzh aa754f8515 add rate limiter 2022-09-05 22:51:57 +08:00
ginuerzh a7f4d3e63e parsing limiter config 2022-09-05 14:49:05 +08:00
ginuerzh 180214a124 update selector 2022-09-04 13:25:56 +08:00
ginuerzh baa6f0cea0 fix bug #92 2022-09-03 17:34:12 +08:00
ginuerzh ca0de58757 update selector 2022-09-02 21:55:25 +08:00
ginuerzh 5acccebe7b improve CIDR matcher 2022-08-31 20:22:44 +08:00
ginuerzh 850bb1379f fine-grained node bypass control 2022-08-25 21:38:13 +08:00
ginuerzh 9e404471a6 add list support for reference to auther, admission and bypass 2022-08-23 21:51:46 +08:00
ginuerzh 166317a7d0 add keepalive for tun 2022-08-22 22:15:32 +08:00
ginuerzh 77d9e3798c update tun handler 2022-08-21 13:56:53 +08:00
ginuerzh 5cbba69ae2 update go.mod 2022-08-20 21:43:21 +08:00
ginuerzh 8a8cbdd9e1 change tun from water to wireguard 2022-08-20 21:31:12 +08:00
ginuerzh fb5f57fa80 fix #77 2022-08-19 22:29:07 +08:00
ginuerzh 5603af2fcf add support for linux/riscv64, windows/arm64 2022-08-18 14:54:16 +08:00
ginuerzh 8ae4e43fc3 fix #76 2022-08-18 13:24:43 +08:00
ginuerzh 96b3b7e962 add standard socks5 udp relay 2022-07-29 22:59:42 +08:00
ginuerzh 85de11ae46 update metrics usage 2022-07-29 21:21:39 +08:00
ginuerzh 3a409fea42 update go.mod 2022-07-27 21:11:20 +08:00
ginuerzh 1c65aae3a9 add cmd options compatible with gost v2 2022-07-27 15:56:56 +08:00
ginuerzh 84255850b6 fix resolver for ipv6 2022-05-01 20:56:08 +08:00
ginuerzh 54e0091c38 improve loader 2022-04-21 23:33:27 +08:00
ginuerzh 605c43ca08 add README_en.md 2022-04-13 23:57:21 +08:00
49 changed files with 2397 additions and 1768 deletions
-89
View File
@@ -1,89 +0,0 @@
# ref: https://docs.docker.com/ci-cd/github-actions/
# https://blog.oddbit.com/post/2020-09-25-building-multi-architecture-im/
name: Docker
on:
push:
branches:
- master
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Prepare
id: prepare
run: |
DOCKER_IMAGE=${{ secrets.DOCKER_IMAGE }}
VERSION=latest
# If this is git tag, use the tag name as a docker tag
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
fi
TAGS="${DOCKER_IMAGE}:${VERSION}"
# If the VERSION looks like a version number, assume that
# this is the most recent version of the image and also
# tag it 'latest'.
if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
TAGS="$TAGS,${DOCKER_IMAGE}:latest"
fi
# Set output parameters.
echo ::set-output name=tags::${TAGS}
echo ::set-output name=docker_image::${DOCKER_IMAGE}
echo ::set-output name=docker_platforms::linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/s390x
# https://github.com/crazy-max/ghaction-docker-buildx
- name: Set up Docker Buildx
id: buildx
uses: crazy-max/ghaction-docker-buildx@v1
with:
version: latest
- name: Environment
run: |
echo home=$HOME
echo git_ref=$GITHUB_REF
echo git_sha=$GITHUB_SHA
echo version=${{ steps.prepare.outputs.version }}
echo image=${{ steps.prepare.outputs.docker_image }}
echo platforms=${{ steps.prepare.outputs.docker_platforms }}
echo avail_platforms=${{ steps.buildx.outputs.platforms }}
# https://github.com/actions/checkout
- name: Checkout
uses: actions/checkout@v2
- name: Docker Buildx (no push)
run: |
docker buildx bake \
--set ${{ github.event.repository.name }}.platform=${{ steps.prepare.outputs.docker_platforms }} \
--set ${{ github.event.repository.name }}.output=type=image,push=false \
--set ${{ github.event.repository.name }}.tags="${{ steps.prepare.outputs.tags }}" \
--file docker-compose.yaml
- name: Docker Login
if: success()
env:
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: |
echo "${DOCKER_PASSWORD}" | docker login --username "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Docker Buildx (push)
if: success()
run: |
docker buildx bake \
--set ${{ github.event.repository.name }}.platform=${{ steps.prepare.outputs.docker_platforms }} \
--set ${{ github.event.repository.name }}.output=type=image,push=true \
--set ${{ github.event.repository.name }}.tags="${{ steps.prepare.outputs.tags }}" \
--file docker-compose.yaml
- name: Clear
if: always()
run: |
rm -f ${HOME}/.docker/config.json
+69
View File
@@ -0,0 +1,69 @@
# ref: https://docs.docker.com/ci-cd/github-actions/
# https://blog.oddbit.com/post/2020-09-25-building-multi-architecture-im/
name: docker
on:
push:
branches:
- master
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Prepare
id: prepare
run: |
DOCKER_IMAGE=${{ secrets.DOCKER_IMAGE }}
VERSION=latest
# If this is git tag, use the tag name as a docker tag
if [[ $GITHUB_REF == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
fi
TAGS="${DOCKER_IMAGE}:${VERSION}"
# If the VERSION looks like a version number, assume that
# this is the most recent version of the image and also
# tag it 'latest'.
if [[ $VERSION =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
MAJOR_VERSION=`echo $VERSION | awk '{split($0,a,"."); print a[1]}'`
MINOR_VERSION=`echo $VERSION | awk '{split($0,a,"."); print a[2]}'`
TAGS="$TAGS,${DOCKER_IMAGE}:${MAJOR_VERSION},${DOCKER_IMAGE}:${MAJOR_VERSION}.${MINOR_VERSION},${DOCKER_IMAGE}:latest"
fi
# Set output parameters.
echo "tags=${TAGS}" >> $GITHUB_OUTPUT
echo "docker_image=${DOCKER_IMAGE}" >> $GITHUB_OUTPUT
echo "docker_platforms=linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/s390x,linux/riscv64" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Environment
run: |
echo home=$HOME
echo git_ref=$GITHUB_REF
echo git_sha=$GITHUB_SHA
echo image=${{ steps.prepare.outputs.docker_image }}
echo tags=${{ steps.prepare.outputs.tags }}
echo platforms=${{ steps.prepare.outputs.docker_platforms }}
echo avail_platforms=${{ steps.buildx.outputs.platforms }}
- name: Login to DockerHub
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Buildx and push
uses: docker/build-push-action@v6
with:
platforms: ${{ steps.prepare.outputs.docker_platforms }}
push: true
tags: ${{ steps.prepare.outputs.tags }}
+42
View File
@@ -0,0 +1,42 @@
name: goreleaser
on:
push:
# run only against tags
tags:
- 'v*'
permissions:
contents: write
# packages: write
# issues: write
jobs:
goreleaser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: git fetch --force --tags
- uses: actions/setup-go@v5
with:
go-version: '1.26'
cache: true
- name: Install UPX
uses: crazy-max/ghaction-upx@v3
with:
install-only: true
# More assembly might be required: Docker logins, GPG, etc. It all depends
# on your needs.
- uses: goreleaser/goreleaser-action@v6
with:
# either 'goreleaser' (default) or 'goreleaser-pro':
distribution: goreleaser
version: '~> v2'
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro'
# distribution:
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
+61
View File
@@ -0,0 +1,61 @@
name: Trigger nightly build
on:
schedule:
# * is a special character in YAML, so you have to quote this string
- cron: '00 15 * * *'
workflow_dispatch:
jobs:
check_date:
runs-on: ubuntu-latest
name: Check latest commit
outputs:
should_run: ${{ steps.should_run.outputs.should_run }}
steps:
- uses: actions/checkout@v4
- name: print latest_commit
run: echo ${{ github.sha }}
- id: should_run
continue-on-error: true
name: check latest commit is less than a day
if: ${{ github.event_name == 'schedule' }}
run: test -z $(git rev-list --after="24 hours" ${{ github.sha }}) && echo "should_run=false" >> $GITHUB_OUTPUT
trigger-nightly:
needs: check_date
if: ${{ needs.check_date.outputs.should_run != 'false' }}
name: Push tag for nightly build
runs-on: ubuntu-latest
steps:
-
name: 'Checkout'
uses: actions/checkout@v4
with:
token: ${{ secrets.NIGHTLY_BUILD_GH_TOKEN }}
fetch-depth: 0
-
name: 'Push new tag'
run: |
git config user.name "${GITHUB_ACTOR}"
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com"
# A previous release was created using a lightweight tag
# git describe by default includes only annotated tags
# git describe --tags includes lightweight tags as well
DESCRIBE=`git tag -l --sort=-v:refname | grep -v nightly | head -n 1`
MAJOR_VERSION=`echo $DESCRIBE | awk '{split($0,a,"."); print a[1]}'`
MINOR_VERSION=`echo $DESCRIBE | awk '{split($0,a,"."); print a[2]}'`
PATCH_VERSION=`echo $DESCRIBE | awk '{split($0,a,"."); print a[3]}'`
PATCH_VERSION="$((${PATCH_VERSION} + 1))"
TAG="${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION}-nightly.$(date +'%Y%m%d')"
git tag -a $TAG -m "$TAG: nightly build"
git push origin $TAG
- name: 'Clean up nightly releases'
uses: dev-drprasad/delete-older-releases@v0.3.3
with:
keep_latest: 2
delete_tags: true
delete_tag_pattern: nightly
env:
GITHUB_TOKEN: ${{ secrets.NIGHTLY_BUILD_GH_TOKEN }}
+5 -1
View File
@@ -32,6 +32,10 @@ _testmain.go
*.bak *.bak
cmd/gost/gost cmd/gost/gost
gost
snap snap
*.pem *.pem
/*.yaml
*.txt
dist/
+72
View File
@@ -0,0 +1,72 @@
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com
before:
hooks:
# You may remove this if you don't use go modules.
- go mod tidy
# you may remove this if you don't need go generate
# - go generate ./...
builds:
- env:
- CGO_ENABLED=0
main: ./cmd/gost
targets:
- darwin_amd64
- darwin_arm64
- linux_386
- linux_amd64
- linux_amd64_v3
- linux_arm_5
- linux_arm_6
- linux_arm_7
- linux_arm64
- linux_mips_softfloat
- linux_mips_hardfloat
- linux_mipsle_softfloat
- linux_mipsle_hardfloat
- linux_mips64
- linux_mips64le
- linux_s390x
- linux_riscv64
- linux_loong64
- freebsd_386
- freebsd_amd64
- windows_386
- windows_amd64
- windows_amd64_v3
- windows_arm64
- android_arm64
ldflags:
- "-s -w -X 'main.version={{ .Tag }}'"
upx:
- # UPX compression. Disabled by default (see #863): upx --best/--lzma/--brute
# adds ~3s startup time on low-spec systems (linux/arm). Release builds can
# opt in via GORELEASER_UPX=true environment variable.
enabled: false
archives:
- format: tar.gz
# use zip for windows archives
format_overrides:
- goos: windows
format: zip
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
release:
prerelease: auto
mode: keep-existing
# The lines beneath this are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
+66
View File
@@ -0,0 +1,66 @@
# CLAUDE.md — gost/
CLI binary entry point for GOST (GO Simple Tunnel). This module compiles the `gost` command.
## Build & Run
```bash
cd gost && go build ./cmd/gost/...
# Cross-compile
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" ./cmd/gost/...
# Build all platforms
make all
# Run
./gost -L "http://:8080" -F "socks5://:1080"
./gost -C gost.yml
```
## Structure
| File | Purpose |
|------|---------|
| `cmd/gost/main.go` | CLI entry point: flag parsing, multi-worker mode (`--` separator), program launch via `svc.Run` |
| `cmd/gost/program.go` | Service lifecycle (`Init`/`Start`/`Stop`), config loading, API/metrics/profiling servers, SIGHUP reload |
| `cmd/gost/register.go` | Blank imports for all built-in handlers, listeners, dialers, connectors — triggers `init()` registration |
| `cmd/gost/version.go` | Version string (`3.3.0`) |
## CLI Flags
| Flag | Usage |
|------|-------|
| `-L` | Inline service definition (repeatable) |
| `-F` | Inline chain node definition (repeatable) |
| `-C` | Path to config file (YAML/JSON) |
| `-D` / `-DD` | Debug / trace logging |
| `-api` | API service address (e.g. `:8080`) |
| `-metrics` | Prometheus metrics address |
| `-O` | Output merged config as yaml or json, then exit |
| `-V` | Print version and exit |
## Multi-Worker Mode
Arguments separated by ` -- ` spawn multiple worker processes via `exec.CommandContext`. Each worker runs as a child process with `_GOST_ID` set. Any worker's exit cancels all others. This is triggered in `init()` before flag parsing.
## Service Lifecycle
- `Init` → calls `parser.Init()` with all CLI/config inputs
- `Start` → `parser.Parse()` → `loader.Load()` → `p.run()` (starts services, API, metrics, profiling)
- `Stop` → cancels reload context, closes all services
- SIGHUP → `reloadConfig()` re-parses and re-runs without restarting the process
## Key Dependencies
- `github.com/go-gost/core` — interface definitions
- `github.com/go-gost/x` — all implementations, config, registry
- `github.com/judwhite/go-svc` — OS service framework (handles daemon/SIGHUP/SIGTERM)
## Registration Pattern
All components register via `init()` side-effects in their packages. `cmd/gost/register.go` triggers them with blank imports. When adding a new built-in handler/listener/dialer/connector, add a blank import here.
## Tests
Tests are in `tests/e2e/` — integration tests using the built binary. No unit tests. Run with `go test ./tests/e2e/...`.
+22 -11
View File
@@ -1,25 +1,36 @@
FROM --platform=$BUILDPLATFORM golang:1.18-alpine as builder FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.6.1 AS xx
# Convert TARGETPLATFORM to GOARCH format FROM --platform=$BUILDPLATFORM golang:1.26-alpine3.23 AS builder
# https://github.com/tonistiigi/xx
COPY --from=tonistiigi/xx:golang / / # add upx for binary compression
RUN apk add --no-cache upx || echo "upx not found"
COPY --from=xx / /
ARG TARGETPLATFORM ARG TARGETPLATFORM
RUN apk add --no-cache musl-dev git gcc RUN xx-info env
ADD . /src ENV CGO_ENABLED=0
WORKDIR /src ENV XX_VERIFY_STATIC=1
ENV GO111MODULE=on WORKDIR /app
RUN cd cmd/gost && go env && go build COPY . .
FROM alpine:latest RUN cd cmd/gost && \
xx-go build -ldflags "-s -w" && \
xx-verify gost && \
{ upx --best gost || true; }
FROM alpine:3.23
# add iptables for tun/tap
RUN apk add --no-cache iptables
WORKDIR /bin/ WORKDIR /bin/
COPY --from=builder /src/cmd/gost/gost . COPY --from=builder /app/cmd/gost/gost .
ENTRYPOINT ["/bin/gost"] ENTRYPOINT ["/bin/gost"]
+17 -1
View File
@@ -9,6 +9,7 @@ PLATFORM_LIST = \
darwin-arm64 \ darwin-arm64 \
linux-386 \ linux-386 \
linux-amd64 \ linux-amd64 \
linux-amd64v3 \
linux-armv5 \ linux-armv5 \
linux-armv6 \ linux-armv6 \
linux-armv7 \ linux-armv7 \
@@ -20,12 +21,15 @@ PLATFORM_LIST = \
linux-mips64 \ linux-mips64 \
linux-mips64le \ linux-mips64le \
linux-s390x \ linux-s390x \
linux-riscv64 \
freebsd-386 \ freebsd-386 \
freebsd-amd64 freebsd-amd64
WINDOWS_ARCH_LIST = \ WINDOWS_ARCH_LIST = \
windows-386 \ windows-386 \
windows-amd64 windows-amd64 \
windows-amd64v3 \
windows-arm64
all: linux-amd64 darwin-amd64 darwin-arm64 windows-amd64 # Most used all: linux-amd64 darwin-amd64 darwin-arm64 windows-amd64 # Most used
@@ -41,6 +45,9 @@ linux-386:
linux-amd64: linux-amd64:
GOARCH=amd64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES) GOARCH=amd64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
linux-amd64v3:
GOARCH=amd64 GOOS=linux GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
linux-armv5: linux-armv5:
GOARCH=arm GOOS=linux GOARM=5 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES) GOARCH=arm GOOS=linux GOARM=5 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
@@ -74,6 +81,9 @@ linux-mips64le:
linux-s390x: linux-s390x:
GOARCH=s390x GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES) GOARCH=s390x GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
linux-riscv64:
GOARCH=riscv64 GOOS=linux $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
freebsd-386: freebsd-386:
GOARCH=386 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES) GOARCH=386 GOOS=freebsd $(GOBUILD) -o $(BINDIR)/$(NAME)-$@ $(GOFILES)
@@ -86,6 +96,12 @@ windows-386:
windows-amd64: windows-amd64:
GOARCH=amd64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe $(GOFILES) GOARCH=amd64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe $(GOFILES)
windows-amd64v3:
GOARCH=amd64 GOOS=windows GOAMD64=v3 $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe $(GOFILES)
windows-arm64:
GOARCH=arm64 GOOS=windows $(GOBUILD) -o $(BINDIR)/$(NAME)-$@.exe $(GOFILES)
gz_releases=$(addsuffix .gz, $(PLATFORM_LIST)) gz_releases=$(addsuffix .gz, $(PLATFORM_LIST))
zip_releases=$(addsuffix .zip, $(WINDOWS_ARCH_LIST)) zip_releases=$(addsuffix .zip, $(WINDOWS_ARCH_LIST))
+74 -20
View File
@@ -2,37 +2,69 @@
### GO语言实现的安全隧道 ### GO语言实现的安全隧道
[![zh](https://img.shields.io/badge/Chinese%20README-green)](README.md) [![en](https://img.shields.io/badge/English%20README-gray)](README_en.md)
## 功能特性 ## 功能特性
- [x] 多端口监听 - [x] [多端口监听](https://gost.run/getting-started/quick-start/)
- [x] 多级转发链 - [x] [多级转发链](https://gost.run/concepts/chain/)
- [x] 多协议支持 - [x] [多协议支持](https://gost.run/tutorials/protocols/overview/)
- [x] TCP/UDP端口转发 - [x] [TCP/UDP端口转发](https://gost.run/tutorials/port-forwarding/)
- [x] TCP/UDP透明代理 - [x] [反向代理](https://gost.run/tutorials/reverse-proxy/)和[隧道](https://gost.run/tutorials/reverse-proxy-tunnel/)
- [x] DNS解析和代理 - [x] [TCP/UDP透明代理](https://gost.run/tutorials/redirect/)
- [x] TUN/TAP设备 - [x] DNS[解析](https://gost.run/concepts/resolver/)和[代理](https://gost.run/tutorials/dns/)
- [x] 负载均衡 - [x] [TUN/TAP设备](https://gost.run/tutorials/tuntap/)与[TUN2SOCKS](https://gost.run/tutorials/tungo/)
- [x] 路由控制 - [x] [负载均衡](https://gost.run/concepts/selector/)
- [x] 动态配置 - [x] [路由控制](https://gost.run/concepts/bypass/)
- [x] Prometheus监控指标 - [x] [准入控制](https://gost.run/concepts/admission/)
- [x] Web API - [x] [限速限流](https://gost.run/concepts/limiter/)
- [ ] Web UI - [x] [插件系统](https://gost.run/concepts/plugin/)
- [x] [Prometheus监控指标](https://gost.run/tutorials/metrics/)
- [x] [动态配置](https://gost.run/tutorials/api/config/)
- [x] [Web API](https://gost.run/tutorials/api/overview/)
- [x] [GUI](https://github.com/go-gost/gostctl)/[WebUI](https://github.com/go-gost/gost-ui)
Wiki站点:[https://latest.gost.run](https://latest.gost.run) ## 概览
Telegram讨论群:[https://t.me/gogost](https://t.me/gogost) ![Overview](https://gost.run/images/overview.png)
Google讨论组:[https://groups.google.com/d/forum/go-gost](https://groups.google.com/d/forum/go-gost) GOST作为隧道有三种主要使用方式。
旧版入口:[v2.gost.run](https://v2.gost.run) ### 正向代理
作为代理服务访问网络,可以组合使用多种协议组成转发链进行转发。
![Proxy](https://gost.run/images/proxy.png)
### 端口转发
将一个服务的端口映射到另外一个服务的端口,同样可以组合使用多种协议组成转发链进行转发。
![Forward](https://gost.run/images/forward.png)
### 反向代理
利用隧道和内网穿透将内网服务暴露到公网访问。
![Reverse Proxy](https://gost.run/images/reverse-proxy.png)
## 下载安装 ## 下载安装
### 二进制文件 ### 二进制文件
[https://github.com/go-gost/gost/releases](https://github.com/go-gost/gost/releases) [https://github.com/go-gost/gost/releases](https://github.com/go-gost/gost/releases)
### 安装脚本
```bash
# 安装最新版本 [https://github.com/go-gost/gost/releases](https://github.com/go-gost/gost/releases)
bash <(curl -fsSL https://github.com/go-gost/gost/raw/master/install.sh) --install
```
```bash
# 选择要安装的版本
bash <(curl -fsSL https://github.com/go-gost/gost/raw/master/install.sh)
```
### 源码编译 ### 源码编译
``` ```
@@ -44,9 +76,31 @@ go build
### Docker ### Docker
``` ```
docker pull gogost/gost docker run --rm gogost/gost -V
``` ```
## 工具
### GUI
[go-gost/gostctl](https://github.com/go-gost/gostctl)
### WebUI
[go-gost/gost-ui](https://github.com/go-gost/gost-ui)
### Shadowsocks Android插件 ### Shadowsocks Android插件
[xausky/ShadowsocksGostPlugin](https://github.com/xausky/ShadowsocksGostPlugin) [hamid-nazari/ShadowsocksGostPlugin](https://github.com/hamid-nazari/ShadowsocksGostPlugin)
## 帮助与支持
Wiki站点:[https://gost.run](https://gost.run)
YouTube: [https://www.youtube.com/@gost-tunnel](https://www.youtube.com/@gost-tunnel)
Telegram:[https://t.me/gogost](https://t.me/gogost)
Google讨论组:[https://groups.google.com/d/forum/go-gost](https://groups.google.com/d/forum/go-gost)
旧版入口:[v2.gost.run](https://v2.gost.run)
+106
View File
@@ -0,0 +1,106 @@
# GO Simple Tunnel
### A simple security tunnel written in golang
[![en](https://img.shields.io/badge/English%20README-green)](README_en.md) [![zh](https://img.shields.io/badge/Chinese%20README-gray)](README.md)
## Features
- [x] [Listening on multiple ports](https://gost.run/en/getting-started/quick-start/)
- [x] [Multi-level forwarding chain](https://gost.run/en/concepts/chain/)
- [x] Rich protocol
- [x] [TCP/UDP port forwarding](https://gost.run/en/tutorials/port-forwarding/)
- [x] [Reverse Proxy](https://gost.run/en/tutorials/reverse-proxy/) and [Tunnel](https://gost.run/en/tutorials/reverse-proxy-tunnel/)
- [x] [TCP/UDP transparent proxy](https://gost.run/en/tutorials/redirect/)
- [x] DNS [resolver](https://gost.run/en/concepts/resolver/) and [proxy](https://gost.run/en/tutorials/dns/)
- [x] [TUN/TAP device](https://gost.run/en/tutorials/tuntap/) and [TUN2SOCKS](https://gost.run/en/tutorials/tungo/)
- [x] [Load balancing](https://gost.run/en/concepts/selector/)
- [x] [Routing control](https://gost.run/en/concepts/bypass/)
- [x] [Admission control](https://gost.run/en/concepts/limiter/)
- [x] [Bandwidth/Rate Limiter](https://gost.run/en/concepts/limiter/)
- [x] [Plugin System](https://gost.run/en/concepts/plugin/)
- [x] [Prometheus metrics](https://gost.run/en/tutorials/metrics/)
- [x] [Dynamic configuration](https://gost.run/en/tutorials/api/config/)
- [x] [Web API](https://gost.run/en/tutorials/api/overview/)
- [x] [GUI](https://github.com/go-gost/gostctl)/[WebUI](https://github.com/go-gost/gost-ui)
## Overview
![Overview](https://gost.run/images/overview.png)
There are three main ways to use GOST as a tunnel.
### Proxy
As a proxy service to access the network, multiple protocols can be used in combination to form a forwarding chain for traffic forwarding.
![Proxy](https://gost.run/images/proxy.png)
### Port Forwarding
Mapping the port of one service to the port of another service, you can also use a combination of multiple protocols to form a forwarding chain for traffic forwarding.
![Forward](https://gost.run/images/forward.png)
### Reverse Proxy
Use tunnel and intranet penetration to expose local services behind NAT or firewall to public network for access.
![Reverse Proxy](https://gost.run/images/reverse-proxy.png)
## Installation
### Binary files
[https://github.com/go-gost/gost/releases](https://github.com/go-gost/gost/releases)
### install script
```bash
# install latest from [https://github.com/go-gost/gost/releases](https://github.com/go-gost/gost/releases)
bash <(curl -fsSL https://github.com/go-gost/gost/raw/master/install.sh) --install
```
```bash
# select version for install
bash <(curl -fsSL https://github.com/go-gost/gost/raw/master/install.sh)
```
### From source
```
git clone https://github.com/go-gost/gost.git
cd gost/cmd/gost
go build
```
### Docker
```
docker run --rm gogost/gost -V
```
## Tools
### GUI
[go-gost/gostctl](https://github.com/go-gost/gostctl)
### WebUI
[go-gost/gost-ui](https://github.com/go-gost/gost-ui)
### Shadowsocks Android
[hamid-nazari/ShadowsocksGostPlugin](https://github.com/hamid-nazari/ShadowsocksGostPlugin)
## Support
Wiki: [https://gost.run](https://gost.run/en/)
YouTube: [https://www.youtube.com/@gost-tunnel](https://www.youtube.com/@gost-tunnel)
Telegram: [https://t.me/gogost](https://t.me/gogost)
Google group: [https://groups.google.com/d/forum/go-gost](https://groups.google.com/d/forum/go-gost)
Legacy version: [v2.gost.run](https://v2.gost.run/en/)
-553
View File
@@ -1,553 +0,0 @@
package main
import (
"encoding/base64"
"errors"
"fmt"
"net/url"
"os"
"strings"
"time"
"github.com/go-gost/x/config"
"github.com/go-gost/x/metadata"
"github.com/go-gost/x/registry"
)
var (
ErrInvalidCmd = errors.New("invalid cmd")
ErrInvalidNode = errors.New("invalid node")
)
type stringList []string
func (l *stringList) String() string {
return fmt.Sprintf("%s", *l)
}
func (l *stringList) Set(value string) error {
*l = append(*l, value)
return nil
}
func buildConfigFromCmd(services, nodes stringList) (*config.Config, error) {
cfg := &config.Config{}
if v := os.Getenv("GOST_PROFILING"); v != "" {
cfg.Profiling = &config.ProfilingConfig{
Addr: v,
}
}
if v := os.Getenv("GOST_METRICS"); v != "" {
cfg.Metrics = &config.MetricsConfig{
Addr: v,
}
}
if v := os.Getenv("GOST_LOGGER_LEVEL"); v != "" {
cfg.Log = &config.LogConfig{
Level: v,
}
}
if v := os.Getenv("GOST_API"); v != "" {
cfg.API = &config.APIConfig{
Addr: v,
}
}
var chain *config.ChainConfig
if len(nodes) > 0 {
chain = &config.ChainConfig{
Name: "chain-0",
}
cfg.Chains = append(cfg.Chains, chain)
}
for i, node := range nodes {
url, err := normCmd(node)
if err != nil {
return nil, err
}
nodeConfig, err := buildNodeConfig(url)
if err != nil {
return nil, err
}
nodeConfig.Name = "node-0"
var nodes []*config.NodeConfig
for _, host := range strings.Split(nodeConfig.Addr, ",") {
if host == "" {
continue
}
nodeCfg := &config.NodeConfig{}
*nodeCfg = *nodeConfig
nodeCfg.Name = fmt.Sprintf("node-%d", len(nodes))
nodeCfg.Addr = host
nodes = append(nodes, nodeCfg)
}
mc := nodeConfig.Connector.Metadata
md := metadata.NewMetadata(mc)
hopConfig := &config.HopConfig{
Name: fmt.Sprintf("hop-%d", i),
Selector: parseSelector(mc),
Nodes: nodes,
}
if v := metadata.GetString(md, "bypass"); v != "" {
bypassCfg := &config.BypassConfig{
Name: fmt.Sprintf("bypass-%d", len(cfg.Bypasses)),
}
if v[0] == '~' {
bypassCfg.Reverse = true
v = v[1:]
}
for _, s := range strings.Split(v, ",") {
if s == "" {
continue
}
bypassCfg.Matchers = append(bypassCfg.Matchers, s)
}
hopConfig.Bypass = bypassCfg.Name
cfg.Bypasses = append(cfg.Bypasses, bypassCfg)
delete(mc, "bypass")
}
if v := metadata.GetString(md, "resolver"); v != "" {
resolverCfg := &config.ResolverConfig{
Name: fmt.Sprintf("resolver-%d", len(cfg.Resolvers)),
}
for _, rs := range strings.Split(v, ",") {
if rs == "" {
continue
}
resolverCfg.Nameservers = append(
resolverCfg.Nameservers,
&config.NameserverConfig{
Addr: rs,
},
)
}
hopConfig.Resolver = resolverCfg.Name
cfg.Resolvers = append(cfg.Resolvers, resolverCfg)
delete(mc, "resolver")
}
if v := metadata.GetString(md, "hosts"); v != "" {
hostsCfg := &config.HostsConfig{
Name: fmt.Sprintf("hosts-%d", len(cfg.Hosts)),
}
for _, s := range strings.Split(v, ",") {
ss := strings.SplitN(s, ":", 2)
if len(ss) != 2 {
continue
}
hostsCfg.Mappings = append(
hostsCfg.Mappings,
&config.HostMappingConfig{
Hostname: ss[0],
IP: ss[1],
},
)
}
hopConfig.Hosts = hostsCfg.Name
cfg.Hosts = append(cfg.Hosts, hostsCfg)
delete(mc, "hosts")
}
if v := metadata.GetString(md, "interface"); v != "" {
hopConfig.Interface = v
delete(mc, "interface")
}
if v := metadata.GetInt(md, "so_mark"); v > 0 {
hopConfig.SockOpts = &config.SockOptsConfig{
Mark: v,
}
delete(mc, "so_mark")
}
chain.Hops = append(chain.Hops, hopConfig)
}
for i, svc := range services {
url, err := normCmd(svc)
if err != nil {
return nil, err
}
service, err := buildServiceConfig(url)
if err != nil {
return nil, err
}
service.Name = fmt.Sprintf("service-%d", i)
if chain != nil {
if service.Listener.Type == "rtcp" || service.Listener.Type == "rudp" {
service.Listener.Chain = chain.Name
} else {
service.Handler.Chain = chain.Name
}
}
cfg.Services = append(cfg.Services, service)
mh := service.Handler.Metadata
md := metadata.NewMetadata(mh)
if v := metadata.GetInt(md, "retries"); v > 0 {
service.Handler.Retries = v
delete(mh, "retries")
}
if v := metadata.GetString(md, "admission"); v != "" {
admCfg := &config.AdmissionConfig{
Name: fmt.Sprintf("admission-%d", len(cfg.Admissions)),
}
if v[0] == '~' {
admCfg.Reverse = true
v = v[1:]
}
for _, s := range strings.Split(v, ",") {
if s == "" {
continue
}
admCfg.Matchers = append(admCfg.Matchers, s)
}
service.Admission = admCfg.Name
cfg.Admissions = append(cfg.Admissions, admCfg)
delete(mh, "admission")
}
if v := metadata.GetString(md, "bypass"); v != "" {
bypassCfg := &config.BypassConfig{
Name: fmt.Sprintf("bypass-%d", len(cfg.Bypasses)),
}
if v[0] == '~' {
bypassCfg.Reverse = true
v = v[1:]
}
for _, s := range strings.Split(v, ",") {
if s == "" {
continue
}
bypassCfg.Matchers = append(bypassCfg.Matchers, s)
}
service.Bypass = bypassCfg.Name
cfg.Bypasses = append(cfg.Bypasses, bypassCfg)
delete(mh, "bypass")
}
if v := metadata.GetString(md, "resolver"); v != "" {
resolverCfg := &config.ResolverConfig{
Name: fmt.Sprintf("resolver-%d", len(cfg.Resolvers)),
}
for _, rs := range strings.Split(v, ",") {
if rs == "" {
continue
}
resolverCfg.Nameservers = append(
resolverCfg.Nameservers,
&config.NameserverConfig{
Addr: rs,
},
)
}
service.Resolver = resolverCfg.Name
cfg.Resolvers = append(cfg.Resolvers, resolverCfg)
delete(mh, "resolver")
}
if v := metadata.GetString(md, "hosts"); v != "" {
hostsCfg := &config.HostsConfig{
Name: fmt.Sprintf("hosts-%d", len(cfg.Hosts)),
}
for _, s := range strings.Split(v, ",") {
ss := strings.SplitN(s, ":", 2)
if len(ss) != 2 {
continue
}
hostsCfg.Mappings = append(
hostsCfg.Mappings,
&config.HostMappingConfig{
Hostname: ss[0],
IP: ss[1],
},
)
}
service.Hosts = hostsCfg.Name
cfg.Hosts = append(cfg.Hosts, hostsCfg)
delete(mh, "hosts")
}
}
return cfg, nil
}
func buildServiceConfig(url *url.URL) (*config.ServiceConfig, error) {
var handler, listener string
schemes := strings.Split(url.Scheme, "+")
if len(schemes) == 1 {
handler = schemes[0]
listener = schemes[0]
}
if len(schemes) == 2 {
handler = schemes[0]
listener = schemes[1]
}
svc := &config.ServiceConfig{
Addr: url.Host,
}
if h := registry.HandlerRegistry().Get(handler); h == nil {
handler = "auto"
}
if ln := registry.ListenerRegistry().Get(listener); ln == nil {
listener = "tcp"
if handler == "ssu" {
listener = "udp"
}
}
// forward mode
if remotes := strings.Trim(url.EscapedPath(), "/"); remotes != "" {
svc.Forwarder = &config.ForwarderConfig{
Targets: strings.Split(remotes, ","),
}
if handler != "relay" {
if listener == "tcp" || listener == "udp" ||
listener == "rtcp" || listener == "rudp" ||
listener == "tun" || listener == "tap" {
handler = listener
} else {
handler = "forward"
}
}
}
var auth *config.AuthConfig
if url.User != nil {
auth = &config.AuthConfig{
Username: url.User.Username(),
}
auth.Password, _ = url.User.Password()
}
m := map[string]any{}
for k, v := range url.Query() {
if len(v) > 0 {
m[k] = v[0]
}
}
md := metadata.NewMetadata(m)
if sa := metadata.GetString(md, "auth"); sa != "" {
au, err := parseAuthFromCmd(sa)
if err != nil {
return nil, err
}
auth = au
}
delete(m, "auth")
tlsConfig := &config.TLSConfig{
CertFile: metadata.GetString(md, "certFile"),
KeyFile: metadata.GetString(md, "keyFile"),
CAFile: metadata.GetString(md, "caFile"),
}
delete(m, "certFile")
delete(m, "keyFile")
delete(m, "caFile")
if tlsConfig.CertFile == "" {
tlsConfig = nil
}
if v := metadata.GetString(md, "dns"); v != "" {
md.Set("dns", strings.Split(v, ","))
}
if v := metadata.GetString(md, "interface"); v != "" {
svc.Interface = v
delete(m, "interface")
}
if v := metadata.GetInt(md, "so_mark"); v > 0 {
svc.SockOpts = &config.SockOptsConfig{
Mark: v,
}
delete(m, "so_mark")
}
if svc.Forwarder != nil {
svc.Forwarder.Selector = parseSelector(m)
}
svc.Handler = &config.HandlerConfig{
Type: handler,
Auth: auth,
Metadata: m,
}
svc.Listener = &config.ListenerConfig{
Type: listener,
TLS: tlsConfig,
Metadata: m,
}
if svc.Listener.Type == "ssh" || svc.Listener.Type == "sshd" {
svc.Handler.Auth = nil
svc.Listener.Auth = auth
}
return svc, nil
}
func buildNodeConfig(url *url.URL) (*config.NodeConfig, error) {
var connector, dialer string
schemes := strings.Split(url.Scheme, "+")
if len(schemes) == 1 {
connector = schemes[0]
dialer = schemes[0]
}
if len(schemes) == 2 {
connector = schemes[0]
dialer = schemes[1]
}
node := &config.NodeConfig{
Addr: url.Host,
}
if c := registry.ConnectorRegistry().Get(connector); c == nil {
connector = "http"
}
if d := registry.DialerRegistry().Get(dialer); d == nil {
dialer = "tcp"
if connector == "ssu" {
dialer = "udp"
}
}
var auth *config.AuthConfig
if url.User != nil {
auth = &config.AuthConfig{
Username: url.User.Username(),
}
auth.Password, _ = url.User.Password()
}
m := map[string]any{}
for k, v := range url.Query() {
if len(v) > 0 {
m[k] = v[0]
}
}
md := metadata.NewMetadata(m)
if sauth := metadata.GetString(md, "auth"); sauth != "" && auth == nil {
au, err := parseAuthFromCmd(sauth)
if err != nil {
return nil, err
}
auth = au
}
delete(m, "auth")
tlsConfig := &config.TLSConfig{
CertFile: metadata.GetString(md, "certFile"),
KeyFile: metadata.GetString(md, "keyFile"),
CAFile: metadata.GetString(md, "caFile"),
Secure: metadata.GetBool(md, "secure"),
ServerName: metadata.GetString(md, "serverName"),
}
if tlsConfig.ServerName == "" {
tlsConfig.ServerName = url.Hostname()
}
delete(m, "certFile")
delete(m, "keyFile")
delete(m, "caFile")
delete(m, "secure")
delete(m, "serverName")
if !tlsConfig.Secure && tlsConfig.CertFile == "" && tlsConfig.CAFile == "" {
tlsConfig = nil
}
node.Connector = &config.ConnectorConfig{
Type: connector,
Auth: auth,
Metadata: m,
}
node.Dialer = &config.DialerConfig{
Type: dialer,
TLS: tlsConfig,
Metadata: m,
}
if node.Dialer.Type == "ssh" || node.Dialer.Type == "sshd" {
node.Connector.Auth = nil
node.Dialer.Auth = auth
}
return node, nil
}
func normCmd(s string) (*url.URL, error) {
s = strings.TrimSpace(s)
if s == "" {
return nil, ErrInvalidCmd
}
if s[0] == ':' || !strings.Contains(s, "://") {
s = "auto://" + s
}
url, err := url.Parse(s)
if err != nil {
return nil, err
}
if url.Scheme == "https" {
url.Scheme = "http+tls"
}
return url, nil
}
func parseAuthFromCmd(sa string) (*config.AuthConfig, error) {
v, err := base64.StdEncoding.DecodeString(sa)
if err != nil {
return nil, err
}
cs := string(v)
n := strings.IndexByte(cs, ':')
if n < 0 {
return &config.AuthConfig{
Username: cs,
}, nil
}
return &config.AuthConfig{
Username: cs[:n],
Password: cs[n+1:],
}, nil
}
func parseSelector(m map[string]any) *config.SelectorConfig {
md := metadata.NewMetadata(m)
strategy := metadata.GetString(md, "strategy")
maxFails := metadata.GetInt(md, "maxFails")
failTimeout := metadata.GetDuration(md, "failTimeout")
if strategy == "" && maxFails <= 0 && failTimeout <= 0 {
return nil
}
if strategy == "" {
strategy = "round"
}
if maxFails <= 0 {
maxFails = 1
}
if failTimeout <= 0 {
failTimeout = time.Second
}
delete(m, "strategy")
delete(m, "maxFails")
delete(m, "failTimeout")
return &config.SelectorConfig{
Strategy: strategy,
MaxFails: maxFails,
FailTimeout: failTimeout,
}
}
-149
View File
@@ -1,149 +0,0 @@
package main
import (
"io"
"os"
"github.com/go-gost/core/logger"
"github.com/go-gost/core/service"
"github.com/go-gost/x/api"
"github.com/go-gost/x/config"
"github.com/go-gost/x/config/parsing"
xlogger "github.com/go-gost/x/logger"
metrics "github.com/go-gost/x/metrics/service"
"github.com/go-gost/x/registry"
)
func buildService(cfg *config.Config) (services []service.Service) {
if cfg == nil {
return
}
for _, autherCfg := range cfg.Authers {
if auther := parsing.ParseAuther(autherCfg); auther != nil {
if err := registry.AutherRegistry().Register(autherCfg.Name, auther); err != nil {
log.Fatal(err)
}
}
}
for _, admissionCfg := range cfg.Admissions {
if adm := parsing.ParseAdmission(admissionCfg); adm != nil {
if err := registry.AdmissionRegistry().Register(admissionCfg.Name, adm); err != nil {
log.Fatal(err)
}
}
}
for _, bypassCfg := range cfg.Bypasses {
if bp := parsing.ParseBypass(bypassCfg); bp != nil {
if err := registry.BypassRegistry().Register(bypassCfg.Name, bp); err != nil {
log.Fatal(err)
}
}
}
for _, resolverCfg := range cfg.Resolvers {
r, err := parsing.ParseResolver(resolverCfg)
if err != nil {
log.Fatal(err)
}
if r != nil {
if err := registry.ResolverRegistry().Register(resolverCfg.Name, r); err != nil {
log.Fatal(err)
}
}
}
for _, hostsCfg := range cfg.Hosts {
if h := parsing.ParseHosts(hostsCfg); h != nil {
if err := registry.HostsRegistry().Register(hostsCfg.Name, h); err != nil {
log.Fatal(err)
}
}
}
for _, recorderCfg := range cfg.Recorders {
if h := parsing.ParseRecorder(recorderCfg); h != nil {
if err := registry.RecorderRegistry().Register(recorderCfg.Name, h); err != nil {
log.Fatal(err)
}
}
}
for _, chainCfg := range cfg.Chains {
c, err := parsing.ParseChain(chainCfg)
if err != nil {
log.Fatal(err)
}
if c != nil {
if err := registry.ChainRegistry().Register(chainCfg.Name, c); err != nil {
log.Fatal(err)
}
}
}
for _, svcCfg := range cfg.Services {
svc, err := parsing.ParseService(svcCfg)
if err != nil {
log.Fatal(err)
}
if svc != nil {
if err := registry.ServiceRegistry().Register(svcCfg.Name, svc); err != nil {
log.Fatal(err)
}
}
services = append(services, svc)
}
return
}
func logFromConfig(cfg *config.LogConfig) logger.Logger {
if cfg == nil {
cfg = &config.LogConfig{}
}
opts := []xlogger.LoggerOption{
xlogger.FormatLoggerOption(logger.LogFormat(cfg.Format)),
xlogger.LevelLoggerOption(logger.LogLevel(cfg.Level)),
}
var out io.Writer = os.Stderr
switch cfg.Output {
case "none", "null":
return xlogger.Nop()
case "stdout":
out = os.Stdout
case "stderr", "":
out = os.Stderr
default:
f, err := os.OpenFile(cfg.Output, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Warnf("log", err)
} else {
out = f
}
}
opts = append(opts, xlogger.OutputLoggerOption(out))
return xlogger.NewLogger(opts...)
}
func buildAPIService(cfg *config.APIConfig) (service.Service, error) {
auther := parsing.ParseAutherFromAuth(cfg.Auth)
if cfg.Auther != "" {
auther = registry.AutherRegistry().Get(cfg.Auther)
}
return api.NewService(
cfg.Addr,
api.PathPrefixOption(cfg.PathPrefix),
api.AccessLogOption(cfg.AccessLog),
api.AutherOption(auther),
)
}
func buildMetricsService(cfg *config.MetricsConfig) (service.Service, error) {
return metrics.NewService(
cfg.Addr,
metrics.PathOption(cfg.Path),
)
}
+68 -103
View File
@@ -1,42 +1,97 @@
package main package main
import ( import (
"context"
"flag" "flag"
"fmt" "fmt"
"net/http" "log"
_ "net/http/pprof" _ "net/http/pprof"
"os" "os"
"os/exec"
"runtime" "runtime"
"strings"
"sync"
"github.com/go-gost/core/logger" "github.com/go-gost/core/logger"
"github.com/go-gost/core/metrics"
"github.com/go-gost/x/config"
"github.com/go-gost/x/config/parsing"
xlogger "github.com/go-gost/x/logger" xlogger "github.com/go-gost/x/logger"
xmetrics "github.com/go-gost/x/metrics" "github.com/judwhite/go-svc"
) )
var ( type stringList []string
log logger.Logger
func (l *stringList) String() string {
return fmt.Sprintf("%s", *l)
}
func (l *stringList) Set(value string) error {
*l = append(*l, value)
return nil
}
var (
cfgFile string cfgFile string
outputFormat string outputFormat string
services stringList services stringList
nodes stringList nodes stringList
debug bool debug bool
trace bool
apiAddr string apiAddr string
metricsAddr string metricsAddr string
) )
func init() {
log.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds)
args := strings.Join(os.Args[1:], " ")
if strings.Contains(args, " -- ") {
var (
wg sync.WaitGroup
ret int
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
for wid, wargs := range strings.Split(" "+args+" ", " -- ") {
wg.Add(1)
go func(wid int, wargs string) {
defer wg.Done()
defer cancel()
worker(wid, strings.Split(wargs, " "), &ctx, &ret)
}(wid, strings.TrimSpace(wargs))
}
wg.Wait()
os.Exit(ret)
}
}
func worker(id int, args []string, ctx *context.Context, ret *int) {
cmd := exec.CommandContext(*ctx, os.Args[0], args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Env = append(os.Environ(), fmt.Sprintf("_GOST_ID=%d", id))
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
if cmd.ProcessState.Exited() {
*ret = cmd.ProcessState.ExitCode()
}
}
func init() { func init() {
var printVersion bool var printVersion bool
flag.Var(&services, "L", "service list") flag.Var(&services, "L", "service list")
flag.Var(&nodes, "F", "chain node list") flag.Var(&nodes, "F", "chain node list")
flag.StringVar(&cfgFile, "C", "", "configure file") flag.StringVar(&cfgFile, "C", "", "configuration file")
flag.BoolVar(&printVersion, "V", false, "print version") flag.BoolVar(&printVersion, "V", false, "print version")
flag.StringVar(&outputFormat, "O", "", "output format, one of yaml|json format") flag.StringVar(&outputFormat, "O", "", "output format, one of yaml|json format")
flag.BoolVar(&debug, "D", false, "debug mode") flag.BoolVar(&debug, "D", false, "debug mode")
flag.BoolVar(&trace, "DD", false, "trace mode")
flag.StringVar(&apiAddr, "api", "", "api service address") flag.StringVar(&apiAddr, "api", "", "api service address")
flag.StringVar(&metricsAddr, "metrics", "", "metrics service address") flag.StringVar(&metricsAddr, "metrics", "", "metrics service address")
flag.Parse() flag.Parse()
@@ -46,105 +101,15 @@ func init() {
version, runtime.Version(), runtime.GOOS, runtime.GOARCH) version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
os.Exit(0) os.Exit(0)
} }
log = xlogger.NewLogger()
logger.SetDefault(log)
} }
func main() { func main() {
cfg := &config.Config{} log := xlogger.NewLogger()
var err error
if len(services) > 0 || apiAddr != "" {
cfg, err = buildConfigFromCmd(services, nodes)
if debug && cfg != nil {
if cfg.Log == nil {
cfg.Log = &config.LogConfig{}
}
cfg.Log.Level = string(logger.DebugLevel)
}
if apiAddr != "" {
cfg.API = &config.APIConfig{
Addr: apiAddr,
}
}
if metricsAddr != "" {
cfg.Metrics = &config.MetricsConfig{
Addr: metricsAddr,
}
}
} else {
if cfgFile != "" {
err = cfg.ReadFile(cfgFile)
} else {
err = cfg.Load()
}
}
if err != nil {
log.Fatal(err)
}
log = logFromConfig(cfg.Log)
logger.SetDefault(log) logger.SetDefault(log)
if outputFormat != "" { p := &program{}
if err := cfg.Write(os.Stdout, outputFormat); err != nil {
log.Fatal(err) if err := svc.Run(p); err != nil {
} logger.Default().Fatal(err)
os.Exit(0)
} }
if cfg.Profiling != nil {
go func() {
addr := cfg.Profiling.Addr
if addr == "" {
addr = ":6060"
}
log.Info("profiling server on ", addr)
log.Fatal(http.ListenAndServe(addr, nil))
}()
}
if cfg.API != nil {
s, err := buildAPIService(cfg.API)
if err != nil {
log.Fatal(err)
}
defer s.Close()
go func() {
log.Info("api service on ", s.Addr())
log.Fatal(s.Serve())
}()
}
if cfg.Metrics != nil {
metrics.SetGlobal(xmetrics.NewMetrics())
if cfg.Metrics.Addr != "" {
s, err := buildMetricsService(cfg.Metrics)
if err != nil {
log.Fatal(err)
}
go func() {
defer s.Close()
log.Info("metrics service on ", s.Addr())
log.Fatal(s.Serve())
}()
}
}
parsing.BuildDefaultTLSConfig(cfg.TLS)
services := buildService(cfg)
for _, svc := range services {
svc := svc
go func() {
svc.Serve()
svc.Close()
}()
}
config.SetGlobal(cfg)
select {}
} }
+274
View File
@@ -0,0 +1,274 @@
package main
import (
"context"
"errors"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"github.com/go-gost/core/auth"
"github.com/go-gost/core/logger"
"github.com/go-gost/core/service"
api_service "github.com/go-gost/x/api/service"
xauth "github.com/go-gost/x/auth"
"github.com/go-gost/x/config"
"github.com/go-gost/x/config/loader"
auth_parser "github.com/go-gost/x/config/parsing/auth"
"github.com/go-gost/x/config/parsing/parser"
xmetrics "github.com/go-gost/x/metrics"
metrics "github.com/go-gost/x/metrics/service"
"github.com/go-gost/x/registry"
"github.com/judwhite/go-svc"
)
type program struct {
srvApi service.Service
srvMetrics service.Service
srvProfiling *http.Server
cancel context.CancelFunc
}
func (p *program) Init(env svc.Environment) error {
parser.Init(parser.Args{
CfgFile: cfgFile,
Services: services,
Nodes: nodes,
Debug: debug,
Trace: trace,
ApiAddr: apiAddr,
MetricsAddr: metricsAddr,
})
return nil
}
func (p *program) Start() error {
cfg, err := parser.Parse()
if err != nil {
return err
}
if outputFormat != "" {
if err := cfg.Write(os.Stdout, outputFormat); err != nil {
return err
}
os.Exit(0)
}
config.Set(cfg)
if err := loader.Load(cfg); err != nil {
return err
}
if err := p.run(cfg); err != nil {
return err
}
ctx, cancel := context.WithCancel(context.Background())
p.cancel = cancel
go p.reload(ctx)
return nil
}
func (p *program) run(cfg *config.Config) error {
for _, svc := range registry.ServiceRegistry().GetAll() {
svc := svc
go func() {
svc.Serve()
}()
}
if p.srvApi != nil {
p.srvApi.Close()
p.srvApi = nil
}
if cfg.API != nil {
s, err := buildApiService(cfg.API)
if err != nil {
return err
}
p.srvApi = s
go func() {
defer s.Close()
log := logger.Default().WithFields(map[string]any{"kind": "service", "service": "@api"})
log.Info("listening on ", s.Addr())
if err := s.Serve(); !errors.Is(err, http.ErrServerClosed) {
log.Error(err)
}
}()
}
if p.srvMetrics != nil {
p.srvMetrics.Close()
p.srvMetrics = nil
}
if cfg.Metrics != nil && cfg.Metrics.Addr != "" {
s, err := buildMetricsService(cfg.Metrics)
if err != nil {
return err
}
p.srvMetrics = s
xmetrics.Enable(true)
go func() {
defer s.Close()
log := logger.Default().WithFields(map[string]any{"kind": "service", "service": "@metrics"})
log.Info("listening on ", s.Addr())
if err := s.Serve(); !errors.Is(err, http.ErrServerClosed) {
log.Error(err)
}
}()
}
if p.srvProfiling != nil {
p.srvProfiling.Close()
p.srvProfiling = nil
}
if cfg.Profiling != nil {
addr := cfg.Profiling.Addr
if addr == "" {
addr = ":6060"
}
s := &http.Server{
Addr: addr,
}
p.srvProfiling = s
go func() {
defer s.Close()
log := logger.Default().WithFields(map[string]any{"kind": "service", "service": "@profiling"})
log.Info("listening on ", addr)
if err := s.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
log.Error(err)
}
}()
}
return nil
}
func (p *program) Stop() error {
if p.cancel != nil {
p.cancel()
}
for name, srv := range registry.ServiceRegistry().GetAll() {
srv.Close()
logger.Default().Debugf("service %s shutdown", name)
}
if p.srvApi != nil {
p.srvApi.Close()
logger.Default().Debug("service @api shutdown")
}
if p.srvMetrics != nil {
p.srvMetrics.Close()
logger.Default().Debug("service @metrics shutdown")
}
if p.srvProfiling != nil {
p.srvProfiling.Close()
logger.Default().Debug("service @profiling shutdown")
}
return nil
}
func (p *program) reload(ctx context.Context) {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP)
for {
select {
case <-c:
if err := p.reloadConfig(); err != nil {
logger.Default().Error(err)
} else {
logger.Default().Info("config reloaded")
}
case <-ctx.Done():
return
}
}
}
func (p *program) reloadConfig() error {
cfg, err := parser.Parse()
if err != nil {
return err
}
config.Set(cfg)
if err := loader.Load(cfg); err != nil {
return err
}
if err := p.run(cfg); err != nil {
return err
}
return nil
}
func buildApiService(cfg *config.APIConfig) (service.Service, error) {
var authers []auth.Authenticator
if auther := auth_parser.ParseAutherFromAuth(cfg.Auth); auther != nil {
authers = append(authers, auther)
}
if cfg.Auther != "" {
authers = append(authers, registry.AutherRegistry().Get(cfg.Auther))
}
var auther auth.Authenticator
if len(authers) > 0 {
auther = xauth.AuthenticatorGroup(authers...)
}
network := "tcp"
addr := cfg.Addr
if strings.HasPrefix(addr, "unix://") {
network = "unix"
addr = strings.TrimPrefix(addr, "unix://")
}
return api_service.NewService(
network, addr,
api_service.PathPrefixOption(cfg.PathPrefix),
api_service.AccessLogOption(cfg.AccessLog),
api_service.AutherOption(auther),
)
}
func buildMetricsService(cfg *config.MetricsConfig) (service.Service, error) {
auther := auth_parser.ParseAutherFromAuth(cfg.Auth)
if cfg.Auther != "" {
auther = registry.AutherRegistry().Get(cfg.Auther)
}
network := "tcp"
addr := cfg.Addr
if strings.HasPrefix(addr, "unix://") {
network = "unix"
addr = strings.TrimPrefix(addr, "unix://")
}
return metrics.NewService(
network, addr,
metrics.PathOption(cfg.Path),
metrics.AutherOption(auther),
)
}
+32
View File
@@ -2,48 +2,70 @@ package main
import ( import (
// Register connectors // Register connectors
_ "github.com/go-gost/x/connector/direct"
_ "github.com/go-gost/x/connector/forward" _ "github.com/go-gost/x/connector/forward"
_ "github.com/go-gost/x/connector/http" _ "github.com/go-gost/x/connector/http"
_ "github.com/go-gost/x/connector/http2" _ "github.com/go-gost/x/connector/http2"
_ "github.com/go-gost/x/connector/masque"
_ "github.com/go-gost/x/connector/relay" _ "github.com/go-gost/x/connector/relay"
_ "github.com/go-gost/x/connector/router"
_ "github.com/go-gost/x/connector/serial"
_ "github.com/go-gost/x/connector/sni" _ "github.com/go-gost/x/connector/sni"
_ "github.com/go-gost/x/connector/socks/v4" _ "github.com/go-gost/x/connector/socks/v4"
_ "github.com/go-gost/x/connector/socks/v5" _ "github.com/go-gost/x/connector/socks/v5"
_ "github.com/go-gost/x/connector/ss" _ "github.com/go-gost/x/connector/ss"
_ "github.com/go-gost/x/connector/ss/udp" _ "github.com/go-gost/x/connector/ss/udp"
_ "github.com/go-gost/x/connector/sshd" _ "github.com/go-gost/x/connector/sshd"
_ "github.com/go-gost/x/connector/tcp"
_ "github.com/go-gost/x/connector/tunnel"
_ "github.com/go-gost/x/connector/unix"
_ "github.com/go-gost/x/connector/masque"
// Register dialers // Register dialers
_ "github.com/go-gost/x/dialer/direct"
_ "github.com/go-gost/x/dialer/dtls"
_ "github.com/go-gost/x/dialer/ftcp" _ "github.com/go-gost/x/dialer/ftcp"
_ "github.com/go-gost/x/dialer/grpc" _ "github.com/go-gost/x/dialer/grpc"
_ "github.com/go-gost/x/dialer/http2" _ "github.com/go-gost/x/dialer/http2"
_ "github.com/go-gost/x/dialer/http2/h2" _ "github.com/go-gost/x/dialer/http2/h2"
_ "github.com/go-gost/x/dialer/http3" _ "github.com/go-gost/x/dialer/http3"
_ "github.com/go-gost/x/dialer/http3/masque"
_ "github.com/go-gost/x/dialer/http3/wt"
_ "github.com/go-gost/x/dialer/icmp" _ "github.com/go-gost/x/dialer/icmp"
_ "github.com/go-gost/x/dialer/kcp" _ "github.com/go-gost/x/dialer/kcp"
_ "github.com/go-gost/x/dialer/mtcp"
_ "github.com/go-gost/x/dialer/mtls" _ "github.com/go-gost/x/dialer/mtls"
_ "github.com/go-gost/x/dialer/mws" _ "github.com/go-gost/x/dialer/mws"
_ "github.com/go-gost/x/dialer/obfs/http" _ "github.com/go-gost/x/dialer/obfs/http"
_ "github.com/go-gost/x/dialer/obfs/tls" _ "github.com/go-gost/x/dialer/obfs/tls"
_ "github.com/go-gost/x/dialer/pht" _ "github.com/go-gost/x/dialer/pht"
_ "github.com/go-gost/x/dialer/quic" _ "github.com/go-gost/x/dialer/quic"
_ "github.com/go-gost/x/dialer/serial"
_ "github.com/go-gost/x/dialer/ssh" _ "github.com/go-gost/x/dialer/ssh"
_ "github.com/go-gost/x/dialer/sshd" _ "github.com/go-gost/x/dialer/sshd"
_ "github.com/go-gost/x/dialer/tcp" _ "github.com/go-gost/x/dialer/tcp"
_ "github.com/go-gost/x/dialer/tls" _ "github.com/go-gost/x/dialer/tls"
_ "github.com/go-gost/x/dialer/udp" _ "github.com/go-gost/x/dialer/udp"
_ "github.com/go-gost/x/dialer/unix"
_ "github.com/go-gost/x/dialer/ws" _ "github.com/go-gost/x/dialer/ws"
// Register handlers // Register handlers
_ "github.com/go-gost/x/handler/api"
_ "github.com/go-gost/x/handler/auto" _ "github.com/go-gost/x/handler/auto"
_ "github.com/go-gost/x/handler/dns" _ "github.com/go-gost/x/handler/dns"
_ "github.com/go-gost/x/handler/file"
_ "github.com/go-gost/x/handler/forward/local" _ "github.com/go-gost/x/handler/forward/local"
_ "github.com/go-gost/x/handler/forward/remote" _ "github.com/go-gost/x/handler/forward/remote"
_ "github.com/go-gost/x/handler/http" _ "github.com/go-gost/x/handler/http"
_ "github.com/go-gost/x/handler/http2" _ "github.com/go-gost/x/handler/http2"
_ "github.com/go-gost/x/handler/http3"
_ "github.com/go-gost/x/handler/masque"
_ "github.com/go-gost/x/handler/metrics"
_ "github.com/go-gost/x/handler/redirect/tcp" _ "github.com/go-gost/x/handler/redirect/tcp"
_ "github.com/go-gost/x/handler/redirect/udp" _ "github.com/go-gost/x/handler/redirect/udp"
_ "github.com/go-gost/x/handler/relay" _ "github.com/go-gost/x/handler/relay"
_ "github.com/go-gost/x/handler/router"
_ "github.com/go-gost/x/handler/serial"
_ "github.com/go-gost/x/handler/sni" _ "github.com/go-gost/x/handler/sni"
_ "github.com/go-gost/x/handler/socks/v4" _ "github.com/go-gost/x/handler/socks/v4"
_ "github.com/go-gost/x/handler/socks/v5" _ "github.com/go-gost/x/handler/socks/v5"
@@ -52,16 +74,23 @@ import (
_ "github.com/go-gost/x/handler/sshd" _ "github.com/go-gost/x/handler/sshd"
_ "github.com/go-gost/x/handler/tap" _ "github.com/go-gost/x/handler/tap"
_ "github.com/go-gost/x/handler/tun" _ "github.com/go-gost/x/handler/tun"
_ "github.com/go-gost/x/handler/tungo"
_ "github.com/go-gost/x/handler/tunnel"
_ "github.com/go-gost/x/handler/unix"
// Register listeners // Register listeners
_ "github.com/go-gost/x/listener/dns" _ "github.com/go-gost/x/listener/dns"
_ "github.com/go-gost/x/listener/dtls"
_ "github.com/go-gost/x/listener/ftcp" _ "github.com/go-gost/x/listener/ftcp"
_ "github.com/go-gost/x/listener/grpc" _ "github.com/go-gost/x/listener/grpc"
_ "github.com/go-gost/x/listener/http2" _ "github.com/go-gost/x/listener/http2"
_ "github.com/go-gost/x/listener/http2/h2" _ "github.com/go-gost/x/listener/http2/h2"
_ "github.com/go-gost/x/listener/http3" _ "github.com/go-gost/x/listener/http3"
_ "github.com/go-gost/x/listener/http3/h3"
_ "github.com/go-gost/x/listener/http3/wt"
_ "github.com/go-gost/x/listener/icmp" _ "github.com/go-gost/x/listener/icmp"
_ "github.com/go-gost/x/listener/kcp" _ "github.com/go-gost/x/listener/kcp"
_ "github.com/go-gost/x/listener/mtcp"
_ "github.com/go-gost/x/listener/mtls" _ "github.com/go-gost/x/listener/mtls"
_ "github.com/go-gost/x/listener/mws" _ "github.com/go-gost/x/listener/mws"
_ "github.com/go-gost/x/listener/obfs/http" _ "github.com/go-gost/x/listener/obfs/http"
@@ -72,12 +101,15 @@ import (
_ "github.com/go-gost/x/listener/redirect/udp" _ "github.com/go-gost/x/listener/redirect/udp"
_ "github.com/go-gost/x/listener/rtcp" _ "github.com/go-gost/x/listener/rtcp"
_ "github.com/go-gost/x/listener/rudp" _ "github.com/go-gost/x/listener/rudp"
_ "github.com/go-gost/x/listener/serial"
_ "github.com/go-gost/x/listener/ssh" _ "github.com/go-gost/x/listener/ssh"
_ "github.com/go-gost/x/listener/sshd" _ "github.com/go-gost/x/listener/sshd"
_ "github.com/go-gost/x/listener/tap" _ "github.com/go-gost/x/listener/tap"
_ "github.com/go-gost/x/listener/tcp" _ "github.com/go-gost/x/listener/tcp"
_ "github.com/go-gost/x/listener/tls" _ "github.com/go-gost/x/listener/tls"
_ "github.com/go-gost/x/listener/tun" _ "github.com/go-gost/x/listener/tun"
_ "github.com/go-gost/x/listener/tungo"
_ "github.com/go-gost/x/listener/udp" _ "github.com/go-gost/x/listener/udp"
_ "github.com/go-gost/x/listener/unix"
_ "github.com/go-gost/x/listener/ws" _ "github.com/go-gost/x/listener/ws"
) )
+2 -2
View File
@@ -1,5 +1,5 @@
package main package main
const ( var (
version = "3.0.0-beta.2" version = "3.3.0"
) )
-4
View File
@@ -1,4 +0,0 @@
version: "3.4"
services:
gost:
build: .
+143 -71
View File
@@ -1,98 +1,170 @@
module github.com/go-gost/gost module github.com/go-gost/gost
go 1.18 go 1.26.3
replace github.com/templexxx/cpu v0.0.7 => github.com/templexxx/cpu v0.0.10-0.20211111114238-98168dcec14a
require ( require (
github.com/go-gost/core v0.0.0-20220413143512-acee88323487 github.com/go-gost/core v0.4.1
github.com/go-gost/x v0.0.0-20220413143619-7a334c173cb8 github.com/go-gost/x v0.10.7
github.com/judwhite/go-svc v1.2.1
github.com/stretchr/testify v1.11.1
github.com/testcontainers/testcontainers-go v0.42.0
) )
require ( require (
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect dario.cat/mergo v1.0.2 // indirect
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/alessio/shellescape v1.4.1 // indirect
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/bytedance/sonic v1.11.6 // indirect
github.com/cheekybits/genny v1.0.0 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/containerd/errdefs v1.0.0 // indirect
github.com/containerd/errdefs/pkg v0.3.0 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/containerd/platforms v0.2.1 // indirect
github.com/coreos/go-iptables v0.5.0 // indirect github.com/coreos/go-iptables v0.5.0 // indirect
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/danieljoos/wincred v1.2.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/docker/libcontainer v2.2.1+incompatible // indirect github.com/distribution/reference v0.6.0 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/docker/go-connections v0.7.0 // indirect
github.com/gin-contrib/cors v1.3.1 // indirect github.com/docker/go-units v0.5.0 // indirect
github.com/dunglas/httpsfv v1.1.0 // indirect
github.com/ebitengine/purego v0.10.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/gin-contrib/cors v1.7.2 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.7.7 // indirect github.com/gin-gonic/gin v1.10.1 // indirect
github.com/go-gost/gosocks4 v0.0.1 // indirect github.com/go-gost/go-shadowsocks2 v0.1.3 // indirect
github.com/go-gost/gosocks5 v0.3.1-0.20211109033403-d894d75b7f09 // indirect github.com/go-gost/gosocks4 v0.1.0 // indirect
github.com/go-gost/relay v0.1.1-0.20211123134818-8ef7fd81ffd7 // indirect github.com/go-gost/gosocks5 v0.5.0 // indirect
github.com/go-gost/tls-dissector v0.0.2-0.20220408131628-aac992c27451 // indirect github.com/go-gost/plugin v0.3.0 // indirect
github.com/go-playground/locales v0.14.0 // indirect github.com/go-gost/relay v0.6.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-gost/tls-dissector v0.2.0 // indirect
github.com/go-playground/validator/v10 v10.10.1 // indirect github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.20.0 // indirect
github.com/go-redis/redis/v8 v8.11.5 // indirect github.com/go-redis/redis/v8 v8.11.5 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/gobwas/glob v0.2.3 // indirect github.com/gobwas/glob v0.2.3 // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/goccy/go-json v0.10.2 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/gopacket v1.1.19 // indirect github.com/google/gopacket v1.1.19 // indirect
github.com/gorilla/websocket v1.5.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/jonboulle/clockwork v0.2.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid v1.3.1 // indirect github.com/klauspost/compress v1.18.5 // indirect
github.com/klauspost/reedsolomon v1.9.9 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/leodido/go-urn v1.2.1 // indirect github.com/klauspost/reedsolomon v1.11.8 // indirect
github.com/lucas-clemente/quic-go v0.25.0 // indirect github.com/leodido/go-urn v1.4.0 // indirect
github.com/magiconair/properties v1.8.6 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/marten-seemann/qpack v0.2.1 // indirect github.com/magiconair/properties v1.8.10 // indirect
github.com/marten-seemann/qtls-go1-16 v0.1.4 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/marten-seemann/qtls-go1-17 v0.1.0 // indirect github.com/miekg/dns v1.1.61 // indirect
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/miekg/dns v1.1.47 // indirect github.com/moby/go-archive v0.2.0 // indirect
github.com/milosgajdos/tenus v0.0.3 // indirect github.com/moby/moby/api v1.54.1 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/moby/moby/client v0.4.0 // indirect
github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 // indirect github.com/moby/patternmatcher v0.6.1 // indirect
github.com/moby/sys/sequential v0.6.0 // indirect
github.com/moby/sys/user v0.4.0 // indirect
github.com/moby/sys/userns v0.1.0 // indirect
github.com/moby/term v0.5.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nxadm/tail v1.4.8 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pion/dtls/v3 v3.1.1 // indirect
github.com/pion/logging v0.2.4 // indirect
github.com/pion/transport/v4 v4.0.1 // indirect
github.com/pires/go-proxyproto v0.8.1 // indirect
github.com/pkg/errors v0.9.1 // indirect github.com/pkg/errors v0.9.1 // indirect
github.com/prometheus/client_golang v1.12.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.2.0 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/procfs v0.7.3 // indirect github.com/prometheus/client_model v0.6.0 // indirect
github.com/prometheus/common v0.48.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/quic-go/qpack v0.6.0 // indirect
github.com/quic-go/quic-go v0.59.0 // indirect
github.com/quic-go/webtransport-go v0.10.0 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/rs/xid v1.3.0 // indirect github.com/rs/xid v1.3.0 // indirect
github.com/shadowsocks/go-shadowsocks2 v0.1.5 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/shadowsocks/shadowsocks-go v0.0.0-20200409064450-3e585ff90601 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sirupsen/logrus v1.8.1 // indirect github.com/shadowsocks/go-shadowsocks2 v0.1.6-0.20241020092332-e1fe9ea73740 // indirect
github.com/shirou/gopsutil/v4 v4.26.3 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 // indirect github.com/songgao/water v0.0.0-20200317203138-2b4b6d7c09d8 // indirect
github.com/spf13/afero v1.8.2 // indirect github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/cast v1.4.1 // indirect github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.10.1 // indirect github.com/spf13/viper v1.19.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect
github.com/templexxx/cpu v0.0.7 // indirect github.com/templexxx/cpu v0.1.1 // indirect
github.com/templexxx/xorsimd v0.4.1 // indirect github.com/templexxx/xorsimd v0.4.3 // indirect
github.com/tjfoc/gmsm v1.3.2 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect github.com/tklauser/go-sysconf v0.3.16 // indirect
github.com/xtaci/kcp-go/v5 v5.6.1 // indirect github.com/tklauser/numcpus v0.11.0 // indirect
github.com/xtaci/smux v1.5.16 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/vishvananda/netlink v1.1.1-0.20211118161826-650dca95af54 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
github.com/vulcand/predicate v1.2.0 // indirect
github.com/xjasonlyu/tun2socks/v2 v2.6.0 // indirect
github.com/xtaci/kcp-go/v5 v5.6.5 // indirect
github.com/xtaci/smux v1.5.31 // indirect
github.com/xtaci/tcpraw v1.2.25 // indirect github.com/xtaci/tcpraw v1.2.25 // indirect
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect github.com/yl2chen/cidranger v1.0.2 // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect
golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect github.com/zalando/go-keyring v0.2.4 // indirect
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 // indirect github.com/zeebo/blake3 v0.2.4 // indirect
golang.org/x/text v0.3.7 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect
golang.org/x/tools v0.1.10 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect go.opentelemetry.io/otel v1.41.0 // indirect
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350 // indirect go.opentelemetry.io/otel/metric v1.41.0 // indirect
google.golang.org/grpc v1.45.0 // indirect go.opentelemetry.io/otel/trace v1.41.0 // indirect
google.golang.org/protobuf v1.27.1 // indirect go.uber.org/multierr v1.11.0 // indirect
gopkg.in/ini.v1 v1.66.4 // indirect golang.org/x/arch v0.8.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect golang.org/x/crypto v0.50.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect
golang.org/x/mod v0.34.0 // indirect
golang.org/x/net v0.53.0 // indirect
golang.org/x/sync v0.20.0 // indirect
golang.org/x/sys v0.43.0 // indirect
golang.org/x/term v0.42.0 // indirect
golang.org/x/text v0.36.0 // indirect
golang.org/x/time v0.12.0 // indirect
golang.org/x/tools v0.43.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20251202230838-ff82c1b0f217 // indirect
google.golang.org/grpc v1.79.3 // indirect
google.golang.org/protobuf v1.36.10 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gvisor.dev/gvisor v0.0.0-20250523182742-eede7a881b20 // indirect
) )
+346 -759
View File
File diff suppressed because it is too large Load Diff
+40 -5
View File
@@ -32,9 +32,11 @@ services:
abc: xyz abc: xyz
def: 456 def: 456
forwarder: forwarder:
targets: nodes:
- 192.168.1.1:1234 - name: target-0
- 192.168.1.2:2345 addr: 192.168.1.1:1234
- name: target-1
addr: 192.168.1.2:2345
selector: selector:
strategy: rand strategy: rand
maxFails: 1 maxFails: 1
@@ -48,6 +50,7 @@ chains:
failTimeout: 30s failTimeout: 30s
hops: hops:
- name: hop-0 - name: hop-0
- name: hop-1
interface: 192.168.1.2 interface: 192.168.1.2
selector: selector:
strategy: rand strategy: rand
@@ -78,6 +81,38 @@ chains:
metadata: metadata:
bar: baz bar: baz
hops:
- name: hop-0
interface: 192.168.1.2
selector:
strategy: rand
maxFails: 3
failTimeout: 60s
bypass: bypass-0
nodes:
- name: node-0
addr: ":1080"
interface: eth1
bypass: bypass-0
connector:
type: socks5
auth:
username: user
password: pass
metadata:
foo: bar
dialer:
type: tcp
auth:
username: user
password: pass
tls:
caFile: "ca.pem"
secure: true
serverName: "example.com"
metadata:
bar: baz
tls: tls:
certFile: "cert.pem" certFile: "cert.pem"
keyFile: "key.pem" keyFile: "key.pem"
@@ -93,14 +128,14 @@ authers:
admissions: admissions:
- name: admission-0 - name: admission-0
reverse: false whitelist: false
matchers: matchers:
- 127.0.0.1 - 127.0.0.1
- 192.168.0.0/16 - 192.168.0.0/16
bypasses: bypasses:
- name: bypass-0 - name: bypass-0
reverse: false whitelist: false
matchers: matchers:
- "*.example.com" - "*.example.com"
- .example.org - .example.org
Executable
+102
View File
@@ -0,0 +1,102 @@
#!/usr/bin/env bash
# Check Root User
# If you want to run as another user, please modify $EUID to be owned by this user
if [[ "$EUID" -ne '0' ]]; then
echo "$(tput setaf 1)Error: You must run this script as root!$(tput sgr0)"
exit 1
fi
# Set the desired GitHub repository
repo="go-gost/gost"
base_url="https://api.github.com/repos/$repo/releases"
# Function to download and install gost
install_gost() {
version=$1
# Detect the operating system
if [[ "$(uname)" == "Linux" ]]; then
os="linux"
elif [[ "$(uname)" == "Darwin" ]]; then
os="darwin"
elif [[ "$(uname)" == "MINGW"* ]]; then
os="windows"
else
echo "Unsupported operating system."
exit 1
fi
# Detect the CPU architecture
arch=$(uname -m)
case $arch in
x86_64)
cpu_arch="amd64"
;;
armv5*)
cpu_arch="armv5"
;;
armv6*)
cpu_arch="armv6"
;;
armv7*)
cpu_arch="armv7"
;;
aarch64|arm64)
cpu_arch="arm64"
;;
i686)
cpu_arch="386"
;;
mips64*)
cpu_arch="mips64"
;;
mips*)
cpu_arch="mips"
;;
mipsel*)
cpu_arch="mipsle"
;;
riscv64)
cpu_arch="riscv64"
;;
*)
echo "Unsupported CPU architecture."
exit 1
;;
esac
get_download_url="$base_url/tags/$version"
download_url=$(curl -s "$get_download_url" | awk -F'"' -v re=".*${os}.*${cpu_arch}.*" '/"browser_download_url":/ && $4 ~ re { print $4 }' | head -n 1)
# Download and install the binary
install_path="/usr/local/bin"
echo "Downloading and installing gost version $version..."
curl -fsSL "$download_url" | tar -xzC "$install_path" gost
chmod +x "$install_path/gost"
# Remove binary from macOS quarantine when installing for first time
[[ "$os" == "darwin" ]] && { xattr -d com.apple.quarantine "$install_path/gost" 2>&-; }
echo "gost installation completed!"
}
# Retrieve available versions from GitHub API
versions=$(curl -s "$base_url" | awk -F'"' '/"tag_name":/ {print $4}')
# Check if --install option provided
if [[ "$1" == "--install" ]]; then
# Install the latest version automatically
latest_version=$(echo "$versions" | head -n 1)
install_gost $latest_version
else
# Display available versions to the user
echo "Available gost versions:"
select version in $versions; do
if [[ -n $version ]]; then
install_gost $version
break
else
echo "Invalid choice! Please select a valid option."
fi
done
fi
+4
View File
@@ -0,0 +1,4 @@
FROM alpine:3.22
# add tools needed by e2e containers and health checks
RUN apk add --no-cache iptables curl netcat-openbsd python3
+53
View File
@@ -0,0 +1,53 @@
# End-to-End Tests
Integration tests that spin up real gost instances inside Docker containers and verify protocol behavior over the network.
## Prerequisites
- [Docker](https://docs.docker.com/get-docker/) (running daemon)
- Go toolchain (for compiling the gost binary under test)
## Running
From the repository root:
```bash
# Run all e2e tests
go test ./tests/e2e/ -v -timeout 10m
# Run a specific test suite
go test ./tests/e2e/ -v -run TestShadowsocksSuite -timeout 5m
go test ./tests/e2e/ -v -run TestParallelSelectorSuite -timeout 5m
# Use a pre-built gost binary (skips compilation)
go test ./tests/e2e/ -v -gost-bin /path/to/gost
```
## Architecture
```
tests/e2e/
├── Dockerfile # Shared base image (Alpine + curl, python3, etc.)
├── main_test.go # TestMain: compiles gost, creates Docker network
├── utils.go # Helpers: container lifecycle, config rendering
├── scripts/
│ ├── tcp_echo.py # HTTP echo server (responds with "hello-gost")
│ └── udp_echo.py # UDP echo server (reflects payloads)
├── testdata/ # config files or data files for running cases
├── shadowsocks_test.go # Shadowsocks protocol tests
└── parallel_selector_test.go # Parallel node selector tests
```
### How it works
1. **TestMain** (`main_test.go`) compiles the gost binary from `../../cmd/gost` (unless `-gost-bin` is provided) and creates a shared Docker network for all containers.
2. Each test suite starts echo server containers (TCP/UDP), then launches separate gost containers for server and client roles.
3. Client configs use Go template syntax (`{{.ServerAddr}}`) so the server address is injected at runtime.
4. Tests verify end-to-end connectivity by sending traffic through the gost proxy chain and checking that the echo server responds correctly.
## Tips
- Increase `-timeout` for CI or slow networks. Container image builds on first run take extra time.
- Use `-gost-bin` to avoid recompiling when iterating on tests locally.
- Add `-v` to see container log output on failure.
- RunGostContainer will wait for exposedPorts automatically, but it's not reliable for udp ports. So, you should check the readiness of udp ports inside cases.
+56
View File
@@ -0,0 +1,56 @@
package e2e
import (
"context"
"flag"
"fmt"
"os"
"os/exec"
"testing"
"github.com/testcontainers/testcontainers-go/network"
)
var SharedNetworkName string
var GostBinPath string
func init() {
flag.StringVar(&GostBinPath, "gost-bin", "", "Path to a pre-built gost binary (skips compilation)")
}
func TestMain(m *testing.M) {
flag.Parse()
ctx := context.Background()
shouldCleanup := false
if GostBinPath == "" {
GostBinPath = "/tmp/gost-test-bin"
cmd := exec.Command("go", "build", "-o", GostBinPath, "../../cmd/gost")
cmd.Env = append(os.Environ(), "CGO_ENABLED=0")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Printf("Failed to compile gost: %v\n", err)
os.Exit(1)
}
shouldCleanup = true
}
net, err := network.New(ctx)
if err != nil {
fmt.Printf("Failed to create network: %v\n", err)
os.Exit(1)
}
SharedNetworkName = net.Name
code := m.Run()
net.Remove(ctx)
if shouldCleanup {
os.Remove(GostBinPath)
}
os.Exit(code)
}
+57
View File
@@ -0,0 +1,57 @@
package e2e
import (
"context"
"fmt"
"io"
"testing"
"github.com/stretchr/testify/suite"
"github.com/testcontainers/testcontainers-go"
)
type ParallelSelectorSuite struct {
suite.Suite
ctx context.Context
echoC testcontainers.Container
echoIP string
}
func (s *ParallelSelectorSuite) SetupSuite() {
s.ctx = context.Background()
echoC, err := RunEchoContainer(s.ctx, SharedNetworkName)
s.Require().NoError(err)
s.echoC = echoC
echoIP, err := echoC.ContainerIP(s.ctx)
s.Require().NoError(err)
s.echoIP = echoIP
}
func (s *ParallelSelectorSuite) TearDownSuite() {
if s.echoC != nil {
s.echoC.Terminate(s.ctx)
}
}
func (s *ParallelSelectorSuite) TestParallelSelector() {
gostC, err := RunGostContainerWithPorts(s.ctx, SharedNetworkName, "testdata/parallel_selector/server.yaml", "8080/tcp")
s.Require().NoError(err)
defer gostC.Terminate(s.ctx)
// Test the proxy by running curl inside the gost container
cmd := []string{"curl", "-v", "-s", "-x", "http://127.0.0.1:8080", fmt.Sprintf("http://%s:5678", s.echoIP)}
code, out, err := gostC.Exec(s.ctx, cmd)
s.Require().NoError(err)
body, err := io.ReadAll(out)
s.Require().NoError(err)
s.Require().Equal(0, code)
s.Require().Contains(string(body), "hello-gost")
}
func TestParallelSelectorSuite(t *testing.T) {
suite.Run(t, new(ParallelSelectorSuite))
}
+16
View File
@@ -0,0 +1,16 @@
from http.server import BaseHTTPRequestHandler, HTTPServer
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
body = b"hello-gost"
self.send_response(200)
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
def log_message(self, format, *args):
return
HTTPServer(("0.0.0.0", 5678), Handler).serve_forever()
+9
View File
@@ -0,0 +1,9 @@
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(("0.0.0.0", 5679))
while True:
data, addr = sock.recvfrom(2048)
sock.sendto(data, addr)
+160
View File
@@ -0,0 +1,160 @@
package e2e
import (
"context"
"fmt"
"io"
"net"
"os"
"strings"
"testing"
"time"
"github.com/stretchr/testify/suite"
"github.com/testcontainers/testcontainers-go"
)
type ShadowsocksSuite struct {
suite.Suite
ctx context.Context
echoC testcontainers.Container
echoIP string
udpC testcontainers.Container
}
func (s *ShadowsocksSuite) SetupSuite() {
s.ctx = context.Background()
s.T().Logf("start tcp echo container...")
echoC, err := RunEchoContainer(s.ctx, SharedNetworkName)
s.Require().NoError(err)
s.echoC = echoC
echoIP, err := echoC.ContainerIP(s.ctx)
s.Require().NoError(err)
s.echoIP = echoIP
s.T().Logf("start udp echo container...")
udpC, err := RunUDPEchoContainer(s.ctx, SharedNetworkName)
s.Require().NoError(err)
s.udpC = udpC
}
func (s *ShadowsocksSuite) TearDownSuite() {
if s.echoC != nil {
s.echoC.Terminate(s.ctx)
}
if s.udpC != nil {
s.udpC.Terminate(s.ctx)
}
}
func (s *ShadowsocksSuite) TestShadowsocksTCP() {
s.runTCPCase("aes256gcm", "testdata/shadowsocks/tcp_server_aes256gcm.yaml", "testdata/shadowsocks/tcp_client_aes256gcm.yaml")
s.runTCPCase("chacha20", "testdata/shadowsocks/tcp_server_chacha20.yaml", "testdata/shadowsocks/tcp_client_chacha20.yaml")
}
func (s *ShadowsocksSuite) TestShadowsocks2022TCP() {
s.runTCPCase("2022-aes128", "testdata/shadowsocks/tcp_server_2022_aes128.yaml", "testdata/shadowsocks/tcp_client_2022_aes128.yaml")
s.runTCPCase("2022-aes256", "testdata/shadowsocks/tcp_server_2022_aes256.yaml", "testdata/shadowsocks/tcp_client_2022_aes256.yaml")
}
func (s *ShadowsocksSuite) TestShadowsocks2022TCPMultiPSK() {
s.runTCPCase("2022-aes128-multipsk", "testdata/shadowsocks/tcp_server_2022_aes128_multipsk.yaml", "testdata/shadowsocks/tcp_client_2022_aes128_multipsk.yaml")
s.runTCPCase("2022-aes256-multipsk", "testdata/shadowsocks/tcp_server_2022_aes256_multipsk.yaml", "testdata/shadowsocks/tcp_client_2022_aes256_multipsk.yaml")
}
func (s *ShadowsocksSuite) TestShadowsocksUDP() {
s.runUDPCase("aes256gcm", "testdata/shadowsocks/udp_server_aes256gcm.yaml", "testdata/shadowsocks/udp_client_aes256gcm.yaml")
}
func (s *ShadowsocksSuite) TestShadowsocks2022UDP() {
s.runUDPCase("2022-aes128", "testdata/shadowsocks/udp_server_2022_aes128.yaml", "testdata/shadowsocks/udp_client_2022_aes128.yaml")
s.runUDPCase("2022-aes256", "testdata/shadowsocks/udp_server_2022_aes256.yaml", "testdata/shadowsocks/udp_client_2022_aes256.yaml")
}
func (s *ShadowsocksSuite) runUDPCase(name, serverConfig, clientConfig string) {
s.T().Run(name, func(t *testing.T) {
serverAlias := name + "-ssu-server"
serverC, err := RunGostContainerWithOptions(s.ctx, SharedNetworkName, serverConfig, []string{serverAlias}, []string{"8389/udp"})
s.Require().NoError(err)
defer serverC.Terminate(s.ctx)
rendered, err := RenderConfig(clientConfig, ConfigData{ServerAddr: serverAlias + ":8389"})
s.Require().NoError(err)
defer os.Remove(rendered)
clientC, err := RunGostContainerWithPorts(
s.ctx,
SharedNetworkName,
rendered,
"9000/udp",
)
s.Require().NoError(err)
defer clientC.Terminate(s.ctx)
host, err := clientC.Host(s.ctx)
s.Require().NoError(err)
port, err := clientC.MappedPort(s.ctx, "9000/udp")
s.Require().NoError(err)
conn, err := net.DialTimeout("udp", net.JoinHostPort(host, port.Port()), 5*time.Second)
s.Require().NoError(err)
defer conn.Close()
payload := []byte("hello-gost-udp")
buf := make([]byte, 2048)
var n int
for i := range 5 {
_, err = conn.Write(payload)
s.Require().NoError(err)
_ = conn.SetReadDeadline(time.Now().Add(2 * time.Second))
n, err = conn.Read(buf)
if err == nil {
break
}
s.T().Logf("udp read attempt %d failed: %v, retrying...", i+1, err)
time.Sleep(2 * time.Second)
}
if err != nil {
DumpLogs(s.T(), s.ctx, name+" udp client logs", clientC)
DumpLogs(s.T(), s.ctx, name+" udp server logs", serverC)
}
s.Require().NoError(err)
s.Require().Contains(string(buf[:n]), "hello-gost")
})
}
func TestShadowsocksSuite(t *testing.T) {
suite.Run(t, new(ShadowsocksSuite))
}
func (s *ShadowsocksSuite) runTCPCase(name, serverConfig, clientConfig string) {
s.T().Run(name, func(t *testing.T) {
serverAlias := name + "-ss-server"
serverC, err := RunGostContainerWithOptions(s.ctx, SharedNetworkName, serverConfig, []string{serverAlias}, []string{"8388/tcp"})
s.Require().NoError(err)
defer serverC.Terminate(s.ctx)
rendered, err := RenderConfig(clientConfig, ConfigData{ServerAddr: serverAlias + ":8388"})
s.Require().NoError(err)
defer os.Remove(rendered)
clientC, err := RunGostContainerWithPorts(s.ctx, SharedNetworkName, rendered, "8080/tcp")
s.Require().NoError(err)
defer clientC.Terminate(s.ctx)
cmd := []string{"curl", "-v", "-s", "-x", "http://127.0.0.1:8080", fmt.Sprintf("http://%s:5678", s.echoIP)}
code, out, err := clientC.Exec(s.ctx, cmd)
s.Require().NoError(err)
body, err := io.ReadAll(out)
s.Require().NoError(err)
if code != 0 || !strings.Contains(string(body), "hello-gost") {
DumpLogs(s.T(), s.ctx, name+" client logs", clientC)
DumpLogs(s.T(), s.ctx, name+" server logs", serverC)
}
s.Require().Equal(0, code)
s.Require().Contains(string(body), "hello-gost")
})
}
+30
View File
@@ -0,0 +1,30 @@
services:
- name: proxy
addr: :8080
handler:
type: http
chain: my-chain
listener:
type: tcp
- name: dummy-1
addr: :18081
handler:
type: http
chains:
- name: my-chain
hops:
- name: hop-1
selector:
strategy: parallel
nodes:
- name: node-1
addr: 127.0.0.1:18081
connector:
type: http
# non existed node
- name: node-2
addr: 127.0.0.1:18082
connector:
type: http
@@ -0,0 +1,23 @@
services:
- name: http-proxy
addr: :8080
handler:
type: http
chain: ss-tcp-chain
listener:
type: tcp
chains:
- name: ss-tcp-chain
hops:
- name: ss-hop
nodes:
- name: ss-node
addr: {{.ServerAddr}}
connector:
type: ss
auth:
username: 2022-blake3-aes-128-gcm
password: MTIzNDU2Nzg5MDEyMzQ1Ng==
dialer:
type: tcp
@@ -0,0 +1,23 @@
services:
- name: http-proxy
addr: :8080
handler:
type: http
chain: ss-tcp-chain
listener:
type: tcp
chains:
- name: ss-tcp-chain
hops:
- name: ss-hop
nodes:
- name: ss-node
addr: {{.ServerAddr}}
connector:
type: ss
auth:
username: 2022-blake3-aes-128-gcm
password: MTIzNDU2Nzg5MDEyMzQ1Ng==:Vbwi6yqCwvPMPR1bCi32Dg==
dialer:
type: tcp
@@ -0,0 +1,23 @@
services:
- name: http-proxy
addr: :8080
handler:
type: http
chain: ss-tcp-chain
listener:
type: tcp
chains:
- name: ss-tcp-chain
hops:
- name: ss-hop
nodes:
- name: ss-node
addr: {{.ServerAddr}}
connector:
type: ss
auth:
username: 2022-blake3-aes-256-gcm
password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY=
dialer:
type: tcp
@@ -0,0 +1,23 @@
services:
- name: http-proxy
addr: :8080
handler:
type: http
chain: ss-tcp-chain
listener:
type: tcp
chains:
- name: ss-tcp-chain
hops:
- name: ss-hop
nodes:
- name: ss-node
addr: {{.ServerAddr}}
connector:
type: ss
auth:
username: 2022-blake3-aes-256-gcm
password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY=:YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
dialer:
type: tcp
@@ -0,0 +1,23 @@
services:
- name: http-proxy
addr: :8080
handler:
type: http
chain: ss-tcp-chain
listener:
type: tcp
chains:
- name: ss-tcp-chain
hops:
- name: ss-hop
nodes:
- name: ss-node
addr: {{.ServerAddr}}
connector:
type: ss
auth:
username: aes-256-gcm
password: secret
dialer:
type: tcp
+23
View File
@@ -0,0 +1,23 @@
services:
- name: http-proxy
addr: :8080
handler:
type: http
chain: ss-tcp-chain
listener:
type: tcp
chains:
- name: ss-tcp-chain
hops:
- name: ss-hop
nodes:
- name: ss-node
addr: {{.ServerAddr}}
connector:
type: ss
auth:
username: chacha20-ietf-poly1305
password: secret
dialer:
type: tcp
@@ -0,0 +1,10 @@
services:
- name: ss-server
addr: :8388
handler:
type: ss
auth:
username: 2022-blake3-aes-128-gcm
password: MTIzNDU2Nzg5MDEyMzQ1Ng==
listener:
type: tcp
@@ -0,0 +1,13 @@
services:
- name: ss-server
addr: :8388
handler:
type: ss
auth:
username: 2022-blake3-aes-128-gcm
password: MTIzNDU2Nzg5MDEyMzQ1Ng==
metadata:
users:
test: Vbwi6yqCwvPMPR1bCi32Dg==
listener:
type: tcp
@@ -0,0 +1,10 @@
services:
- name: ss-server
addr: :8388
handler:
type: ss
auth:
username: 2022-blake3-aes-256-gcm
password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY=
listener:
type: tcp
@@ -0,0 +1,13 @@
services:
- name: ss-server
addr: :8388
handler:
type: ss
auth:
username: 2022-blake3-aes-256-gcm
password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY=
metadata:
users:
test: YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY=
listener:
type: tcp
@@ -0,0 +1,10 @@
services:
- name: ss-server
addr: :8388
handler:
type: ss
auth:
username: aes-256-gcm
password: secret
listener:
type: tcp
+10
View File
@@ -0,0 +1,10 @@
services:
- name: ss-server
addr: :8388
handler:
type: ss
auth:
username: chacha20-ietf-poly1305
password: secret
listener:
type: tcp
@@ -0,0 +1,27 @@
services:
- name: udp-proxy
addr: :9000
handler:
type: udp
chain: ssu-chain
forwarder:
nodes:
- name: udp-echo
addr: udp-echo:5679
listener:
type: udp
chains:
- name: ssu-chain
hops:
- name: ssu-hop
nodes:
- name: ssu-node
addr: {{.ServerAddr}}
connector:
type: ssu
auth:
username: 2022-blake3-aes-128-gcm
password: MTIzNDU2Nzg5MDEyMzQ1Ng==
dialer:
type: udp
@@ -0,0 +1,27 @@
services:
- name: udp-proxy
addr: :9000
handler:
type: udp
chain: ssu-chain
forwarder:
nodes:
- name: udp-echo
addr: udp-echo:5679
listener:
type: udp
chains:
- name: ssu-chain
hops:
- name: ssu-hop
nodes:
- name: ssu-node
addr: {{.ServerAddr}}
connector:
type: ssu
auth:
username: 2022-blake3-aes-256-gcm
password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY=
dialer:
type: udp
@@ -0,0 +1,27 @@
services:
- name: udp-proxy
addr: :9000
handler:
type: udp
chain: ssu-chain
forwarder:
nodes:
- name: udp-echo
addr: udp-echo:5679
listener:
type: udp
chains:
- name: ssu-chain
hops:
- name: ssu-hop
nodes:
- name: ssu-node
addr: {{.ServerAddr}}
connector:
type: ssu
auth:
username: aes-256-gcm
password: secret
dialer:
type: udp
@@ -0,0 +1,10 @@
services:
- name: ssu-server
addr: :8389
handler:
type: ssu
auth:
username: 2022-blake3-aes-128-gcm
password: MTIzNDU2Nzg5MDEyMzQ1Ng==
listener:
type: udp
@@ -0,0 +1,10 @@
services:
- name: ssu-server
addr: :8389
handler:
type: ssu
auth:
username: 2022-blake3-aes-256-gcm
password: MTIzNDU2Nzg5MDEyMzQ1NjEyMzQ1Njc4OTAxMjM0NTY=
listener:
type: udp
@@ -0,0 +1,10 @@
services:
- name: ssu-server
addr: :8389
handler:
type: ssu
auth:
username: aes-256-gcm
password: secret
listener:
type: udp
+156
View File
@@ -0,0 +1,156 @@
package e2e
import (
"context"
"io"
"os"
"testing"
"text/template"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
type ConfigData struct {
ServerAddr string
}
func DumpLogs(t *testing.T, ctx context.Context, label string, c testcontainers.Container) {
logs, err := c.Logs(ctx)
if err != nil {
return
}
defer logs.Close()
body, err := io.ReadAll(logs)
if err != nil {
return
}
t.Logf("%s:\n%s", label, string(body))
}
func RenderConfig(tmplPath string, data ConfigData) (string, error) {
tmpl, err := template.ParseFiles(tmplPath)
if err != nil {
return "", err
}
f, err := os.CreateTemp("", "gost-e2e-config-*.yaml")
if err != nil {
return "", err
}
if err := tmpl.Execute(f, data); err != nil {
f.Close()
os.Remove(f.Name())
return "", err
}
if err := f.Close(); err != nil {
os.Remove(f.Name())
return "", err
}
return f.Name(), nil
}
func RunEchoContainer(ctx context.Context, networkName string) (testcontainers.Container, error) {
req := echoContainerRequest(ctx, networkName)
return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
}
func echoContainerRequest(_ context.Context, networkName string) testcontainers.ContainerRequest {
return testcontainers.ContainerRequest{
FromDockerfile: testcontainers.FromDockerfile{
Context: ".",
Dockerfile: "Dockerfile",
Repo: "gost-e2e",
Tag: "latest",
KeepImage: true,
},
Networks: []string{networkName},
NetworkAliases: map[string][]string{
networkName: {"tcp-echo"},
},
Files: []testcontainers.ContainerFile{
{HostFilePath: "scripts/tcp_echo.py", ContainerFilePath: "/scripts/tcp_echo.py", FileMode: 0644},
},
ExposedPorts: []string{"5678/tcp"},
Cmd: []string{"python3", "/scripts/tcp_echo.py"},
WaitingFor: wait.ForExposedPort(),
}
}
func RunUDPEchoContainer(ctx context.Context, networkName string) (testcontainers.Container, error) {
req := udpEchoContainerRequest(ctx, networkName)
return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
}
func udpEchoContainerRequest(_ context.Context, networkName string) testcontainers.ContainerRequest {
return testcontainers.ContainerRequest{
FromDockerfile: testcontainers.FromDockerfile{
Context: ".",
Dockerfile: "Dockerfile",
Repo: "gost-e2e",
Tag: "latest",
KeepImage: true,
},
Networks: []string{networkName},
NetworkAliases: map[string][]string{
networkName: {"udp-echo"},
},
Files: []testcontainers.ContainerFile{
{HostFilePath: "scripts/udp_echo.py", ContainerFilePath: "/scripts/udp_echo.py", FileMode: 0644},
},
ExposedPorts: []string{"5679/udp"},
Cmd: []string{"python3", "/scripts/udp_echo.py"},
WaitingFor: wait.ForExposedPort().SkipInternalCheck(),
}
}
func RunGostContainer(ctx context.Context, networkName, yamlPath string) (testcontainers.Container, error) {
return runGostContainer(ctx, networkName, yamlPath, nil, nil)
}
func RunGostContainerWithPorts(ctx context.Context, networkName, yamlPath string, exposedPorts ...string) (testcontainers.Container, error) {
return runGostContainer(ctx, networkName, yamlPath, nil, exposedPorts)
}
func RunGostContainerWithOptions(ctx context.Context, networkName, yamlPath string, aliases, exposedPorts []string) (testcontainers.Container, error) {
return runGostContainer(ctx, networkName, yamlPath, aliases, exposedPorts)
}
func runGostContainer(ctx context.Context, networkName, yamlPath string, aliases, exposedPorts []string) (testcontainers.Container, error) {
req := testcontainers.ContainerRequest{
FromDockerfile: testcontainers.FromDockerfile{
Context: ".",
Dockerfile: "Dockerfile",
Repo: "gost-e2e",
Tag: "latest",
KeepImage: true,
},
ExposedPorts: exposedPorts,
// interal check for udp ports will be failed
WaitingFor: wait.ForExposedPort().SkipInternalCheck(),
Networks: []string{networkName},
NetworkAliases: map[string][]string{
networkName: aliases,
},
Files: []testcontainers.ContainerFile{
{HostFilePath: GostBinPath, ContainerFilePath: "/bin/gost", FileMode: 0755},
{HostFilePath: yamlPath, ContainerFilePath: "/config.yaml", FileMode: 0644},
},
Cmd: []string{"/bin/gost", "-C", "/config.yaml"},
}
return testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
}