Update On Sat Aug 24 20:31:52 CEST 2024

This commit is contained in:
github-action[bot]
2024-08-24 20:31:53 +02:00
parent 1c8560324f
commit 6a6046ae72
65 changed files with 1764 additions and 1362 deletions

View File

@@ -12,19 +12,19 @@ require (
github.com/hashicorp/go-retryablehttp v0.7.7
github.com/juju/ratelimit v1.0.2
github.com/labstack/echo/v4 v4.12.0
github.com/prometheus/client_golang v1.19.1
github.com/prometheus/client_golang v1.20.0
github.com/prometheus/client_model v0.6.1
github.com/prometheus/common v0.55.0
github.com/prometheus/node_exporter v1.8.1
github.com/sagernet/sing v0.4.1
github.com/sagernet/sing-box v1.9.3
github.com/prometheus/node_exporter v1.8.2
github.com/sagernet/sing v0.4.2
github.com/sagernet/sing-box v1.9.4
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.27.2
github.com/xtls/xray-core v1.8.16
github.com/urfave/cli/v2 v2.27.4
github.com/xtls/xray-core v1.8.23
go.uber.org/atomic v1.11.0
go.uber.org/zap v1.27.0
golang.org/x/sync v0.7.0
golang.org/x/time v0.5.0
golang.org/x/sync v0.8.0
golang.org/x/time v0.6.0
google.golang.org/grpc v1.65.0
gopkg.in/yaml.v3 v3.0.1
)
@@ -66,7 +66,7 @@ require (
github.com/illumos/go-kstat v0.0.0-20210513183136-173c9b0a9973 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/jsimonetti/rtnetlink v1.4.2 // indirect
github.com/klauspost/compress v1.17.8 // indirect
github.com/klauspost/compress v1.17.9 // indirect
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
@@ -89,33 +89,34 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus-community/go-runit v0.1.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/quic-go/quic-go v0.45.0 // indirect
github.com/refraction-networking/utls v1.6.6 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/quic-go v0.45.1 // indirect
github.com/refraction-networking/utls v1.6.7 // indirect
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/safchain/ethtool v0.3.0 // indirect
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f // indirect
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba // indirect
github.com/sagernet/sing-dns v0.2.0 // indirect
github.com/sagernet/sing-shadowsocks v0.2.6 // indirect
github.com/sagernet/sing-dns v0.2.3 // indirect
github.com/sagernet/sing-shadowsocks v0.2.7 // indirect
github.com/sagernet/sing-tun v0.3.2 // indirect
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 // indirect
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/vishvananda/netlink v1.2.1-beta.2.0.20230316163032-ced5aaba43e3 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d // indirect
go.uber.org/mock v0.4.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc // indirect
golang.org/x/mod v0.18.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/tools v0.22.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect

View File

@@ -143,8 +143,8 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
github.com/juju/ratelimit v1.0.2 h1:sRxmtRiajbvrcLQT7S+JbqU0ntsb9W2yhSdNN8tWfaI=
github.com/juju/ratelimit v1.0.2/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -155,6 +155,8 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
@@ -215,16 +217,16 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/prometheus-community/go-runit v0.1.0 h1:uTWEj/Fn2RoLdfg/etSqwzgYNOYPrARx1BHUN052tGA=
github.com/prometheus-community/go-runit v0.1.0/go.mod h1:AvJ9Jo3gAFu2lbM4+qfjdpq30FfiLDJZKbQ015u08IQ=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI=
github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
github.com/prometheus/node_exporter v1.8.1 h1:qYIN+ghn7kEggHe4pcIRp9oXkljU8ARWyEHBr286RPY=
github.com/prometheus/node_exporter v1.8.1/go.mod h1:rJMoAQMglUjAZ7nggHnRuwfJ0hKUVW6+Gv+IaMxh6js=
github.com/prometheus/node_exporter v1.8.2 h1:G8NryhgftPSXTnD+DuaNZTHDqmHF3zLWgPeG5RUtcHg=
github.com/prometheus/node_exporter v1.8.2/go.mod h1:rJMoAQMglUjAZ7nggHnRuwfJ0hKUVW6+Gv+IaMxh6js=
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
@@ -232,10 +234,10 @@ github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
github.com/quic-go/quic-go v0.45.0 h1:OHmkQGM37luZITyTSu6ff03HP/2IrwDX1ZFiNEhSFUE=
github.com/quic-go/quic-go v0.45.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
github.com/refraction-networking/utls v1.6.6 h1:igFsYBUJPYM8Rno9xUuDoM5GQrVEqY4llzEXOkL43Ig=
github.com/refraction-networking/utls v1.6.6/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/quic-go/quic-go v0.45.1 h1:tPfeYCk+uZHjmDRwHHQmvHRYL2t44ROTujLeFVBmjCA=
github.com/quic-go/quic-go v0.45.1/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg=
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
@@ -249,20 +251,20 @@ github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0=
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba h1:EY5AS7CCtfmARNv2zXUOrsEMPFDGYxaw65JzA2p51Vk=
github.com/sagernet/netlink v0.0.0-20240523065131-45e60152f9ba/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/quic-go v0.43.1-beta.2 h1:6YRCE9t1Q3UbNX1/dJGqpwFQbh6DXC6XBrQr2xp6hXY=
github.com/sagernet/quic-go v0.43.1-beta.2/go.mod h1:BkrQYeop7Jx3hN3TW8/76CXcdhYiNPyYEBL/BVJ1ifc=
github.com/sagernet/sing v0.4.1 h1:zVlpE+7k7AFoC2pv6ReqLf0PIHjihL/jsBl5k05PQFk=
github.com/sagernet/sing v0.4.1/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
github.com/sagernet/sing-box v1.9.3 h1:jXiAqQRzBeXCSLTTl0Z92OLs5GkVotsdiNRVATZWpoY=
github.com/sagernet/sing-box v1.9.3/go.mod h1:6Rx5nzbqIfN7HlUaHgO/IdkP7fDPPQ/U/TAC5asEjSM=
github.com/sagernet/sing-dns v0.2.0 h1:dka3weRX6+CrYO3v+hrTy2z68rCOCZXNBiNXpLZ6JNs=
github.com/sagernet/sing-dns v0.2.0/go.mod h1:BJpJv6XLnrUbSyIntOT6DG9FW0f4fETmPAHvNjOprLg=
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
github.com/sagernet/quic-go v0.46.0-beta.4 h1:k9f7VSKaM47AY6MPND0Qf1KRN7HwimPg9zdOFTXTiCk=
github.com/sagernet/quic-go v0.46.0-beta.4/go.mod h1:zJmVdJUNqEDXfubf4KtIOUHHerggjBduiGRLNzJspcM=
github.com/sagernet/sing v0.4.2 h1:jzGNJdZVRI0xlAfFugsIQUPvyB9SuWvbJK7zQCXc4QM=
github.com/sagernet/sing v0.4.2/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
github.com/sagernet/sing-box v1.9.4 h1:Sf2JffjKvcG2a2+YWPOP0NiCOqpu2iPU12RkpZ0PhaM=
github.com/sagernet/sing-box v1.9.4/go.mod h1:DGX0xLYqlQa36DX1PTWJBh6EnChI1hUyzwoJUObhlW4=
github.com/sagernet/sing-dns v0.2.3 h1:YzeBUn2tR38F7HtvGEQ0kLRLmZWMEgi/+7wqa4Twb1k=
github.com/sagernet/sing-dns v0.2.3/go.mod h1:BJpJv6XLnrUbSyIntOT6DG9FW0f4fETmPAHvNjOprLg=
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
github.com/sagernet/sing-tun v0.3.2 h1:z0bLUT/YXH9RrJS9DsIpB0Bb9afl2hVJOmHd0zA3HJY=
github.com/sagernet/sing-tun v0.3.2/go.mod h1:DxLIyhjWU/HwGYoX0vNGg2c5QgTQIakphU1MuERR5tQ=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U=
github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4=
github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
@@ -298,8 +300,8 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8=
github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI=
github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
@@ -315,12 +317,12 @@ github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1Y
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc h1:0Nj8T1n7F7+v4vRVroaJIvY6R0vNABLfPH+lzPHRJvI=
github.com/xtls/reality v0.0.0-20240429224917-ecc4401070cc/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
github.com/xtls/xray-core v1.8.16 h1:PhbpdREAIvDS7xmxR6Sdpkx0h5ugmf6wIoWECWtJ0kE=
github.com/xtls/xray-core v1.8.16/go.mod h1:tjzDQQJpFORuhf7fBsiswiexLVEeJpAfMsD0NE5xV7M=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d h1:+B97uD9uHLgAAulhigmys4BVwZZypzK7gPN3WtpgRJg=
github.com/xtls/reality v0.0.0-20240712055506-48f0b2d5ed6d/go.mod h1:dm4y/1QwzjGaK17ofi0Vs6NpKAHegZky8qk6J2JJZAE=
github.com/xtls/xray-core v1.8.23 h1:A8Wr50ildMYLpaNu3EiK+Stg/tps6i0h7z5Hr4f9H2k=
github.com/xtls/xray-core v1.8.23/go.mod h1:0CwyMPNA5Cs+ukPXHbYQGgne/ug0PuXOSVqBu7zyXOc=
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
@@ -341,8 +343,8 @@ golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc h1:O9NuF4s+E/PvMIy+9IUZB9znFwUIXEWSstNjek6VpVg=
golang.org/x/exp v0.0.0-20240531132922-fd00a4e0eefc/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
@@ -360,8 +362,8 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -372,8 +374,8 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -388,8 +390,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -398,8 +400,8 @@ golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -38,8 +38,8 @@ func loadConfig() (cfg *config.Config, err error) {
},
},
}
if TCPRemoteAddr != "" {
cfg.RelayConfigs[0].TCPRemotes = []string{TCPRemoteAddr}
if RemoteAddr != "" {
cfg.RelayConfigs[0].Remotes = []string{RemoteAddr}
}
if err := cfg.Adjust(); err != nil {
return nil, err

View File

@@ -9,7 +9,7 @@ import (
var (
LocalAddr string
ListenType constant.RelayType
TCPRemoteAddr string
RemoteAddr string
TransportType constant.RelayType
ConfigPath string
WebPort int
@@ -40,7 +40,7 @@ var RootFlags = []cli.Flag{
Name: "r,remote",
Usage: "转发地址,例如 0.0.0.0:5201通过 ws 隧道转发时应为 ws://0.0.0.0:2443",
EnvVars: []string{"EHCO_REMOTE_ADDR"},
Destination: &TCPRemoteAddr,
Destination: &RemoteAddr,
},
&cli.StringFlag{
Name: "tt,transport_type",

View File

@@ -9,14 +9,22 @@ import (
"net"
"time"
"github.com/Ehco1996/ehco/internal/constant"
"github.com/Ehco1996/ehco/internal/lb"
"github.com/Ehco1996/ehco/internal/metrics"
"github.com/Ehco1996/ehco/internal/relay/conf"
"github.com/Ehco1996/ehco/pkg/buffer"
"github.com/Ehco1996/ehco/pkg/bytes"
"go.uber.org/zap"
)
const (
shortHashLength = 7
)
var (
ErrIdleTimeout = errors.New("connection closed due to idle timeout")
)
// RelayConn is the interface that represents a relay connection.
// it contains two connections: clientConn and remoteConn
// clientConn is the connection from the client to the relay server
@@ -63,6 +71,7 @@ type relayConnImpl struct {
HandshakeDuration time.Duration
RelayLabel string `json:"relay_label"`
ConnType string `json:"conn_type"`
Options *conf.Options
}
func WithRelayLabel(relayLabel string) RelayConnOption {
@@ -95,18 +104,31 @@ func WithLogger(l *zap.SugaredLogger) RelayConnOption {
}
}
func WithRelayOptions(opts *conf.Options) RelayConnOption {
return func(rci *relayConnImpl) {
rci.Options = opts
}
}
func (rc *relayConnImpl) Transport() error {
defer rc.Close() // nolint: errcheck
cl := rc.l.Named(shortHashSHA256(rc.GetFlow()))
cl.Debugf("transport start, stats: %s", rc.Stats.String())
defer func() {
err := rc.Close()
if err != nil {
rc.l.Errorf("error closing relay connection: %s", err.Error())
}
}()
rc.l = rc.l.Named(shortHashSHA256(rc.GetFlow()))
rc.l.Debugf("transport start")
c1 := newInnerConn(rc.clientConn, rc)
c1.l = rc.l.Named("client")
c2 := newInnerConn(rc.remoteConn, rc)
c2.l = rc.l.Named("remote")
rc.StartTime = time.Now().Local()
err := copyConn(c1, c2)
if err != nil {
cl.Errorf("transport error: %s", err.Error())
rc.l.Errorf("transport error: %s", err.Error())
}
cl.Debugf("transport end, stats: %s", rc.Stats.String())
rc.l.Debugf("transport end: stats: %s", rc.Stats.String())
rc.EndTime = time.Now().Local()
return err
}
@@ -115,7 +137,7 @@ func (rc *relayConnImpl) Close() error {
err1 := rc.clientConn.Close()
err2 := rc.remoteConn.Close()
rc.Closed = true
return combineErrorsAndMuteEOF(err1, err2)
return combineErrorsAndMuteIDLE(err1, err2)
}
// functions that for web ui
@@ -142,11 +164,11 @@ func (rc *relayConnImpl) GetConnType() string {
return rc.ConnType
}
func combineErrorsAndMuteEOF(err1, err2 error) error {
if err1 == io.EOF {
func combineErrorsAndMuteIDLE(err1, err2 error) error {
if err1 == ErrIdleTimeout {
err1 = nil
}
if err2 == io.EOF {
if err2 == ErrIdleTimeout {
return nil
}
if err1 != nil && err2 != nil {
@@ -180,13 +202,14 @@ func (s *Stats) String() string {
// note that innerConn is a wrapper around net.Conn to allow io.Copy to be used
type innerConn struct {
net.Conn
lastActive time.Time
rc *relayConnImpl
lastActive time.Time
rc *relayConnImpl
l *zap.SugaredLogger
}
func newInnerConn(conn net.Conn, rc *relayConnImpl) *innerConn {
return &innerConn{Conn: conn, rc: rc, lastActive: time.Now()}
return &innerConn{Conn: conn, rc: rc, lastActive: time.Now().Local()}
}
func (c *innerConn) recordStats(n int, isRead bool) {
@@ -208,37 +231,35 @@ func (c *innerConn) recordStats(n int, isRead bool) {
func (c *innerConn) Read(p []byte) (n int, err error) {
for {
deadline := time.Now().Add(constant.ReadTimeOut)
deadline := time.Now().Add(c.rc.Options.ReadTimeout)
if err := c.Conn.SetReadDeadline(deadline); err != nil {
return 0, err
}
n, err = c.Conn.Read(p)
if err == nil {
c.recordStats(n, true)
c.lastActive = time.Now()
return
c.lastActive = time.Now().Local()
return n, err
} else {
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
if time.Since(c.lastActive) > constant.IdleTimeOut {
c.rc.l.Debugf("read idle,close remote: %s", c.rc.remote.Label)
return 0, io.EOF
since := time.Since(c.lastActive)
if since > c.rc.Options.IdleTimeout {
c.l.Debugf("Read idle, close remote: %s", c.rc.remote.Label)
return 0, ErrIdleTimeout
}
continue
}
return n, err
return 0, err
}
}
}
func (c *innerConn) Write(p []byte) (n int, err error) {
if time.Since(c.lastActive) > constant.IdleTimeOut {
c.rc.l.Debugf("write idle,close remote: %s", c.rc.remote.Label)
return 0, io.EOF
}
n, err = c.Conn.Write(p)
c.recordStats(n, false) // false for write operation
if err != nil {
c.lastActive = time.Now()
if err == nil {
c.recordStats(n, false)
now := time.Now().Local()
c.lastActive = now
}
return
}
@@ -265,28 +286,29 @@ func shortHashSHA256(input string) string {
hasher := sha256.New()
hasher.Write([]byte(input))
hash := hasher.Sum(nil)
return hex.EncodeToString(hash)[:7]
return hex.EncodeToString(hash)[:shortHashLength]
}
func copyConn(conn1, conn2 *innerConn) error {
buf := buffer.BufferPool.Get()
defer buffer.BufferPool.Put(buf)
buf1 := buffer.BufferPool.Get()
defer buffer.BufferPool.Put(buf1)
buf2 := buffer.BufferPool.Get()
defer buffer.BufferPool.Put(buf2)
errCH := make(chan error, 1)
// copy conn1 to conn2,read from conn1 and write to conn2
go func() {
_, err := io.CopyBuffer(conn2, conn1, buf)
_, err := io.CopyBuffer(conn2, conn1, buf1)
_ = conn2.CloseWrite() // all data is written to conn2 now, so close the write side of conn2 to send eof
errCH <- err
}()
// reverse copy conn2 to conn1,read from conn2 and write to conn1
buf2 := buffer.BufferPool.Get()
defer buffer.BufferPool.Put(buf2)
_, err := io.CopyBuffer(conn1, conn2, buf2)
_ = conn1.CloseWrite()
err2 := <-errCH
_ = conn1.CloseRead()
_ = conn2.CloseRead()
return combineErrorsAndMuteEOF(err, err2)
return combineErrorsAndMuteIDLE(err, err2)
}

View File

@@ -8,18 +8,23 @@ import (
"time"
"github.com/Ehco1996/ehco/internal/lb"
"github.com/Ehco1996/ehco/internal/relay/conf"
"github.com/stretchr/testify/assert"
)
func TestInnerConn_ReadWrite(t *testing.T) {
testData := []byte("hello")
testOptions := conf.Options{
IdleTimeout: time.Second,
ReadTimeout: time.Second,
}
clientConn, serverConn := net.Pipe()
clientConn.SetDeadline(time.Now().Add(1 * time.Second))
serverConn.SetDeadline(time.Now().Add(1 * time.Second))
defer clientConn.Close()
defer serverConn.Close()
rc := relayConnImpl{Stats: &Stats{}, remote: &lb.Node{Label: "client"}}
rc := relayConnImpl{Stats: &Stats{}, remote: &lb.Node{Label: "client"}, Options: &testOptions}
innerC := newInnerConn(clientConn, &rc)
errChan := make(chan error, 1)
go func() {
@@ -94,8 +99,8 @@ func TestCopyTCPConn(t *testing.T) {
remoteConn, err := net.Dial("tcp", echoServer.Addr().String())
assert.NoError(t, err)
defer remoteConn.Close()
rc := relayConnImpl{Stats: &Stats{}, remote: &lb.Node{Label: "client"}}
testOptions := conf.Options{IdleTimeout: time.Second, ReadTimeout: time.Second}
rc := relayConnImpl{Stats: &Stats{}, remote: &lb.Node{Label: "client"}, Options: &testOptions}
c1 := newInnerConn(clientConn, &rc)
c2 := newInnerConn(remoteConn, &rc)
@@ -155,7 +160,8 @@ func TestCopyUDPConn(t *testing.T) {
assert.NoError(t, err)
defer remoteConn.Close()
rc := relayConnImpl{Stats: &Stats{}, remote: &lb.Node{Label: "client"}}
testOptions := conf.Options{IdleTimeout: time.Second, ReadTimeout: time.Second}
rc := relayConnImpl{Stats: &Stats{}, remote: &lb.Node{Label: "client"}, Options: &testOptions}
c1 := newInnerConn(clientConn, &rc)
c2 := newInnerConn(remoteConn, &rc)

View File

@@ -9,7 +9,7 @@ import (
"sync/atomic"
"time"
"github.com/Ehco1996/ehco/internal/constant"
"github.com/Ehco1996/ehco/internal/relay/conf"
"github.com/Ehco1996/ehco/pkg/buffer"
)
@@ -33,7 +33,7 @@ func (c *uc) Read(b []byte) (int, error) {
c.lastActivity.Store(time.Now())
return n, nil
default:
if time.Since(c.lastActivity.Load().(time.Time)) > constant.IdleTimeOut {
if time.Since(c.lastActivity.Load().(time.Time)) > c.listener.cfg.Options.IdleTimeout {
return 0, io.EOF
}
return 0, nil
@@ -75,6 +75,7 @@ func (c *uc) SetWriteDeadline(t time.Time) error {
}
type UDPListener struct {
cfg *conf.Config
listenAddr *net.UDPAddr
listenConn *net.UDPConn
@@ -90,8 +91,8 @@ type UDPListener struct {
closed atomic.Bool
}
func NewUDPListener(ctx context.Context, addr string) (*UDPListener, error) {
udpAddr, err := net.ResolveUDPAddr("udp", addr)
func NewUDPListener(ctx context.Context, cfg *conf.Config) (*UDPListener, error) {
udpAddr, err := net.ResolveUDPAddr("udp", cfg.Listen)
if err != nil {
return nil, err
}
@@ -104,6 +105,7 @@ func NewUDPListener(ctx context.Context, addr string) (*UDPListener, error) {
ctx, cancel := context.WithCancel(ctx)
l := &UDPListener{
cfg: cfg,
listenConn: conn,
listenAddr: udpAddr,

View File

@@ -5,11 +5,6 @@ import "time"
type RelayType string
var (
// allow change in test
// TODO Set to Relay Config
ReadTimeOut = 5 * time.Second
IdleTimeOut = 30 * time.Second
Version = "1.1.5-dev"
GitBranch string
GitRevision string
@@ -18,9 +13,10 @@ var (
)
const (
DialTimeOut = 3 * time.Second
SniffTimeOut = 300 * time.Millisecond
DefaultDialTimeOut = 3 * time.Second
DefaultReadTimeOut = 5 * time.Second
DefaultIdleTimeOut = 10 * time.Second
DefaultSniffTimeOut = 300 * time.Millisecond
// todo,support config in relay config
BUFFER_POOL_SIZE = 1024 // support 512 connections

View File

@@ -64,7 +64,7 @@ func NewPingGroup(cfg *config.Config) *PingGroup {
// parse addr from rule
for _, relayCfg := range cfg.RelayConfigs {
// NOTE for (https/ws/wss)://xxx.com -> xxx.com
for _, remote := range relayCfg.TCPRemotes {
for _, remote := range relayCfg.Remotes {
addr, err := extractHost(remote)
if err != nil {
pg.logger.Error("try parse host error", zap.Error(err))

View File

@@ -4,6 +4,7 @@ import (
"errors"
"fmt"
"net/url"
"time"
"github.com/Ehco1996/ehco/internal/constant"
"github.com/Ehco1996/ehco/internal/lb"
@@ -31,13 +32,27 @@ func (w *WSConfig) Clone() *WSConfig {
}
type Options struct {
WSConfig *WSConfig `json:"ws_config,omitempty"`
EnableUDP bool `json:"enable_udp,omitempty"`
EnableMultipathTCP bool `json:"enable_multipath_tcp,omitempty"`
EnableUDP bool `json:"enable_udp,omitempty"`
EnableMultipathTCP bool `json:"enable_multipath_tcp,omitempty"`
// connection limit
MaxConnection int `json:"max_connection,omitempty"`
BlockedProtocols []string `json:"blocked_protocols,omitempty"`
MaxReadRateKbps int64 `json:"max_read_rate_kbps,omitempty"`
// ws related
WSConfig *WSConfig `json:"ws_config,omitempty"`
DialTimeoutSec int `json:"dial_timeout_sec,omitempty"`
IdleTimeoutSec int `json:"idle_timeout_sec,omitempty"`
ReadTimeoutSec int `json:"read_timeout_sec,omitempty"`
SniffTimeoutSec int `json:"sniff_timeout_sec,omitempty"`
// timeout in duration
DialTimeout time.Duration
IdleTimeout time.Duration
ReadTimeout time.Duration
SniffTimeout time.Duration
}
func (o *Options) Clone() *Options {
@@ -60,9 +75,12 @@ type Config struct {
Listen string `json:"listen"`
ListenType constant.RelayType `json:"listen_type"`
TransportType constant.RelayType `json:"transport_type"`
TCPRemotes []string `json:"tcp_remotes"` // TODO rename to remotes
Remotes []string `json:"remotes"`
Options *Options `json:"options,omitempty"`
// deprecated
TCPRemotes []string `json:"tcp_remotes"`
}
func (r *Config) GetWSHandShakePath() string {
@@ -83,12 +101,29 @@ func (r *Config) GetWSRemoteAddr(baseAddr string) (string, error) {
return addr, nil
}
func (r *Config) GetTCPRemotes() string {
return fmt.Sprintf("%v", r.TCPRemotes)
func (r *Config) Adjust() error {
if r.Label == "" {
r.Label = r.DefaultLabel()
zap.S().Debugf("label is empty, set default label:%s", r.Label)
}
if len(r.Remotes) == 0 && len(r.TCPRemotes) != 0 {
zap.S().Warnf("tcp remotes is deprecated, use remotes instead")
r.Remotes = r.TCPRemotes
}
if r.Options == nil {
r.Options = newDefaultOptions()
} else {
r.Options.DialTimeout = getDuration(r.Options.DialTimeoutSec, r.Options.DialTimeout)
r.Options.IdleTimeout = getDuration(r.Options.IdleTimeoutSec, r.Options.IdleTimeout)
r.Options.ReadTimeout = getDuration(r.Options.ReadTimeoutSec, r.Options.ReadTimeout)
r.Options.SniffTimeout = getDuration(r.Options.SniffTimeoutSec, r.Options.SniffTimeout)
}
return nil
}
func (r *Config) Validate() error {
if r.Adjust() != nil {
if err := r.Adjust(); err != nil {
return errors.New("adjust config failed")
}
@@ -97,18 +132,18 @@ func (r *Config) Validate() error {
}
if r.Listen == "" {
return fmt.Errorf("invalid listen:%s", r.Listen)
return fmt.Errorf("invalid listen: %s", r.Listen)
}
for _, addr := range r.TCPRemotes {
for _, addr := range r.Remotes {
if addr == "" {
return fmt.Errorf("invalid tcp remote addr:%s", addr)
return fmt.Errorf("invalid remote addr: %s", addr)
}
}
for _, protocol := range r.Options.BlockedProtocols {
if protocol != ProtocolHTTP && protocol != ProtocolTLS {
return fmt.Errorf("invalid blocked protocol:%s", protocol)
return fmt.Errorf("invalid blocked protocol: %s", protocol)
}
}
return nil
@@ -122,8 +157,8 @@ func (r *Config) Clone() *Config {
Label: r.Label,
Options: r.Options.Clone(),
}
new.TCPRemotes = make([]string, len(r.TCPRemotes))
copy(new.TCPRemotes, r.TCPRemotes)
new.Remotes = make([]string, len(r.Remotes))
copy(new.Remotes, r.Remotes)
return new
}
@@ -134,11 +169,11 @@ func (r *Config) Different(new *Config) bool {
r.Label != new.Label {
return true
}
if len(r.TCPRemotes) != len(new.TCPRemotes) {
if len(r.Remotes) != len(new.Remotes) {
return true
}
for i, addr := range r.TCPRemotes {
if addr != new.TCPRemotes[i] {
for i, addr := range r.Remotes {
if addr != new.Remotes[i] {
return true
}
}
@@ -147,28 +182,14 @@ func (r *Config) Different(new *Config) bool {
// todo make this shorter and more readable
func (r *Config) DefaultLabel() string {
defaultLabel := fmt.Sprintf("<At=%s To=%s TP=%s>",
r.Listen, r.TCPRemotes, r.TransportType)
defaultLabel := fmt.Sprintf("<At=%s To=%s By=%s>",
r.Listen, r.Remotes, r.TransportType)
return defaultLabel
}
func (r *Config) Adjust() error {
if r.Label == "" {
r.Label = r.DefaultLabel()
zap.S().Debugf("label is empty, set default label:%s", r.Label)
}
if r.Options == nil {
r.Options = &Options{
WSConfig: &WSConfig{},
EnableMultipathTCP: true, // default enable multipath tcp
}
}
return nil
}
func (r *Config) ToTCPRemotes() lb.RoundRobin {
tcpNodeList := make([]*lb.Node, len(r.TCPRemotes))
for idx, addr := range r.TCPRemotes {
func (r *Config) ToRemotesLB() lb.RoundRobin {
tcpNodeList := make([]*lb.Node, len(r.Remotes))
for idx, addr := range r.Remotes {
tcpNodeList[idx] = &lb.Node{
Address: addr,
Label: fmt.Sprintf("%s-%s", r.Label, addr),
@@ -195,3 +216,21 @@ func (r *Config) validateType() error {
}
return nil
}
func getDuration(seconds int, defaultDuration time.Duration) time.Duration {
if seconds > 0 {
return time.Duration(seconds) * time.Second
}
return defaultDuration
}
func newDefaultOptions() *Options {
return &Options{
EnableMultipathTCP: true,
WSConfig: &WSConfig{},
DialTimeout: constant.DefaultDialTimeOut,
IdleTimeout: constant.DefaultIdleTimeOut,
ReadTimeout: constant.DefaultReadTimeOut,
SniffTimeout: constant.DefaultSniffTimeOut,
}
}

View File

@@ -38,15 +38,12 @@ func NewRelay(cfg *conf.Config, cmgr cmgr.Cmgr) (*Relay, error) {
func (r *Relay) ListenAndServe(ctx context.Context) error {
errCh := make(chan error)
go func() {
r.l.Infof("Start Relay Server(%s):%s", r.cfg.ListenType, r.cfg.DefaultLabel())
r.l.Infof("Start Relay Server: %s", r.cfg.DefaultLabel())
errCh <- r.relayServer.ListenAndServe(ctx)
}()
return <-errCh
}
func (r *Relay) Close() {
r.l.Infof("Close Relay Server:%s", r.cfg.DefaultLabel())
if err := r.relayServer.Close(); err != nil {
r.l.Errorf(err.Error())
}
func (r *Relay) Stop() error {
return r.relayServer.Close()
}

View File

@@ -57,7 +57,7 @@ func (s *Server) startOneRelay(ctx context.Context, r *Relay) {
}
func (s *Server) stopOneRelay(r *Relay) {
r.Close()
_ = r.Stop()
s.relayM.Delete(r.UniqueID())
}
@@ -85,23 +85,20 @@ func (s *Server) Start(ctx context.Context) error {
return err
case <-ctx.Done():
s.l.Info("ctx cancelled start to stop all relay servers")
s.relayM.Range(func(key, value interface{}) bool {
r := value.(*Relay)
r.Close()
return true
})
return nil
return s.Stop()
}
}
func (s *Server) Stop() error {
s.l.Info("relay server stop now")
var err error
s.relayM.Range(func(key, value interface{}) bool {
r := value.(*Relay)
r.Close()
if e := r.Stop(); e != nil {
err = errors.Join(err, e)
}
return true
})
return nil
return err
}
func (s *Server) TriggerReload() {

View File

@@ -38,7 +38,7 @@ func newBaseRelayServer(cfg *conf.Config, cmgr cmgr.Cmgr) (*BaseRelayServer, err
relayer: relayer,
cfg: cfg,
cmgr: cmgr,
remotes: cfg.ToTCPRemotes(),
remotes: cfg.ToRemotesLB(),
l: zap.S().Named(cfg.GetLoggerName()),
}, nil
}
@@ -98,10 +98,10 @@ func (b *BaseRelayServer) sniffAndBlockProtocol(c net.Conn) (net.Conn, error) {
buffer := buf.NewPacket()
ctx, cancel := context.WithTimeout(context.Background(), constant.SniffTimeOut)
ctx, cancel := context.WithTimeout(context.Background(), b.cfg.Options.SniffTimeout)
defer cancel()
sniffMetadata, err := sniff.PeekStream(ctx, c, buffer, constant.SniffTimeOut, sniff.TLSClientHello, sniff.HTTPHost)
sniffMetadata, err := sniff.PeekStream(ctx, c, buffer, b.cfg.Options.SniffTimeout, sniff.TLSClientHello, sniff.HTTPHost)
if err != nil {
b.l.Debugf("sniff error: %s", err)
return c, nil
@@ -137,6 +137,7 @@ func (b *BaseRelayServer) handleRelayConn(c, rc net.Conn, remote *lb.Node, connT
conn.WithRemote(remote),
conn.WithConnType(connType),
conn.WithRelayLabel(b.cfg.Label),
conn.WithRelayOptions(b.cfg.Options),
conn.WithHandshakeDuration(remote.HandShakeDuration),
}
relayConn := conn.NewRelayConn(c, rc, opts...)
@@ -161,7 +162,7 @@ func (b *BaseRelayServer) ListenAndServe(ctx context.Context) error {
}
func NewNetDialer(cfg *conf.Config) *net.Dialer {
dialer := &net.Dialer{Timeout: constant.DialTimeOut}
dialer := &net.Dialer{Timeout: constant.DefaultDialTimeOut}
dialer.SetMultipathTCP(cfg.Options.EnableMultipathTCP)
return dialer
}

View File

@@ -82,7 +82,7 @@ func (s *RawServer) ListenAndServe(ctx context.Context) error {
s.tcpLis = ts
if s.cfg.Options != nil && s.cfg.Options.EnableUDP {
udpLis, err := conn.NewUDPListener(ctx, s.cfg.Listen)
udpLis, err := conn.NewUDPListener(ctx, s.cfg)
if err != nil {
return err
}
@@ -107,10 +107,13 @@ func (s *RawServer) ListenAndServe(ctx context.Context) error {
}
func (s *RawServer) listenUDP(ctx context.Context) error {
s.l.Infof("Start UDP server at %s", s.cfg.Listen)
for {
c, err := s.udpLis.Accept()
if err != nil {
// Check if the error is due to context cancellation
if errors.Is(err, context.Canceled) {
return nil // Return without logging the error
}
s.l.Errorf("UDP accept error: %v", err)
return err
}

View File

@@ -174,10 +174,10 @@ func (c *ClashSub) ToRelayConfigs(listenHost string) ([]*relay_cfg.Config, error
// add other proxies address in group to relay config
for _, proxy := range proxies[1:] {
remote := net.JoinHostPort(proxy.rawServer, proxy.rawPort)
if strInArray(remote, rc.TCPRemotes) {
if strInArray(remote, rc.Remotes) {
continue
}
rc.TCPRemotes = append(rc.TCPRemotes, remote)
rc.Remotes = append(rc.Remotes, remote)
if proxy.UDP {
rc.Options = &relay_cfg.Options{
EnableUDP: true,

View File

@@ -136,7 +136,7 @@ func (p *Proxies) ToRelayConfig(listenHost string, listenPort string, newName st
ListenType: constant.RelayTypeRaw,
TransportType: constant.RelayTypeRaw,
Listen: net.JoinHostPort(listenHost, listenPort),
TCPRemotes: []string{remoteAddr},
Remotes: []string{remoteAddr},
}
if p.UDP {
r.Options = &relay_cfg.Options{

View File

@@ -40,11 +40,6 @@ const (
func TestMain(m *testing.M) {
// Setup
// change the idle timeout to 1 second to make connection close faster in test
constant.IdleTimeOut = time.Second
constant.ReadTimeOut = time.Second
_ = log.InitGlobalLogger("debug")
_ = tls.InitTlsCfg()
@@ -61,66 +56,67 @@ func TestMain(m *testing.M) {
// Cleanup
echoServer.Stop()
for _, server := range relayServers {
server.Close()
server.Stop()
}
os.Exit(code)
}
func startRelayServers() []*relay.Relay {
options := conf.Options{
EnableUDP: true,
IdleTimeoutSec: 1,
ReadTimeoutSec: 1,
}
cfg := config.Config{
RelayConfigs: []*conf.Config{
// raw
{
Label: "raw",
Listen: RAW_LISTEN,
ListenType: constant.RelayTypeRaw,
TCPRemotes: []string{ECHO_SERVER},
Remotes: []string{ECHO_SERVER},
TransportType: constant.RelayTypeRaw,
Options: &conf.Options{
EnableUDP: true,
},
Options: &options,
},
// ws
{
Label: "ws-in",
Listen: WS_LISTEN,
ListenType: constant.RelayTypeRaw,
TCPRemotes: []string{WS_REMOTE},
Remotes: []string{WS_REMOTE},
TransportType: constant.RelayTypeWS,
Options: &conf.Options{
EnableUDP: true,
},
Options: &options,
},
{
Label: "ws-out",
Listen: WS_SERVER,
ListenType: constant.RelayTypeWS,
TCPRemotes: []string{ECHO_SERVER},
Remotes: []string{ECHO_SERVER},
TransportType: constant.RelayTypeRaw,
Options: &conf.Options{
EnableUDP: true,
},
Options: &options,
},
// wss
{
Label: "wss-in",
Listen: WSS_LISTEN,
ListenType: constant.RelayTypeRaw,
TCPRemotes: []string{WSS_REMOTE},
Remotes: []string{WSS_REMOTE},
TransportType: constant.RelayTypeWSS,
Options: &conf.Options{
EnableUDP: true,
},
Options: &options,
},
{
Label: "wss-out",
Listen: WSS_SERVER,
ListenType: constant.RelayTypeWSS,
TCPRemotes: []string{ECHO_SERVER},
Remotes: []string{ECHO_SERVER},
TransportType: constant.RelayTypeRaw,
Options: &conf.Options{
EnableUDP: true,
},
Options: &options,
},
},
}
cfg.Adjust()
var servers []*relay.Relay
for _, c := range cfg.RelayConfigs {
@@ -252,6 +248,6 @@ func testUDPRelay(t *testing.T, address string, concurrent bool, concurrency ...
}
func TestRelayIdleTimeout(t *testing.T) {
err := echo.EchoTcpMsgLong([]byte("hello"), time.Second, RAW_LISTEN)
err := echo.EchoTcpMsgLong([]byte("hello"), time.Second*2, RAW_LISTEN)
require.Error(t, err, "Connection should be rejected")
}