mirror of
https://github.com/v2fly/v2ray-core.git
synced 2025-01-17 23:06:30 -05:00
Remove hysteria2
The hysteria2 fork used "github.com/JimmyHuang454/hysteria" removed the original license of hysteria2 (which is not allowed) and replaced it with GPL which conflicts with v2ray's license. Given that the quality of the related code is very poor and it is not synchronized with the upstream, I deleted it.
This commit is contained in:
parent
d59c2b4c85
commit
1d21d7a077
9
go.mod
9
go.mod
@ -6,8 +6,6 @@ toolchain go1.22.7
|
||||
|
||||
require (
|
||||
github.com/adrg/xdg v0.5.3
|
||||
github.com/apernet/hysteria/core/v2 v2.4.5
|
||||
github.com/apernet/quic-go v0.45.2-0.20240702221538-ed74cfbe8b6e
|
||||
github.com/go-chi/chi/v5 v5.1.0
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/go-playground/validator/v10 v10.22.1
|
||||
@ -67,8 +65,10 @@ require (
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/klauspost/reedsolomon v1.11.7 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mustafaturan/monoton v1.0.0 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.17.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pion/logging v0.2.2 // indirect
|
||||
@ -76,10 +76,8 @@ require (
|
||||
github.com/pion/sctp v1.8.7 // indirect
|
||||
github.com/pion/transport/v3 v3.0.7 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/quic-go/qpack v0.5.1 // indirect
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect
|
||||
github.com/secure-io/siv-go v0.0.0-20180922214919-5ff40651e2c4 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/xtaci/smux v1.5.24 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
|
||||
@ -88,8 +86,7 @@ require (
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.22.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
)
|
||||
|
||||
replace github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 => github.com/xiaokangwang/struc v0.0.0-20231031203518-0e381172f248
|
||||
|
||||
replace github.com/apernet/hysteria/core/v2 v2.4.5 => github.com/JimmyHuang454/hysteria/core/v2 v2.0.0-20240724161647-b3347cf6334d
|
||||
|
24
go.sum
24
go.sum
@ -14,8 +14,6 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/FlowerWrong/water v0.0.0-20180301012659-01a4eaa1f6f2/go.mod h1:xrG5L7lq7T2DLnPr2frMnL906CNEoKRwLB+VYFhPq2w=
|
||||
github.com/JimmyHuang454/hysteria/core/v2 v2.0.0-20240724161647-b3347cf6334d h1:DN3vqWeuVa1anRkwCueIqPEUPnSyFCk4PR2LcyJKrZk=
|
||||
github.com/JimmyHuang454/hysteria/core/v2 v2.0.0-20240724161647-b3347cf6334d/go.mod h1:3OIt9vhWrxoHUMPm6WcpAg7jUEqfy6Q4IyFZA67Azcg=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78=
|
||||
github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ=
|
||||
@ -27,8 +25,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/apernet/quic-go v0.45.2-0.20240702221538-ed74cfbe8b6e h1:KBs8aBfKl5AKPKGpfn3bl0joDJXDq5fnH+AjFODiU+A=
|
||||
github.com/apernet/quic-go v0.45.2-0.20240702221538-ed74cfbe8b6e/go.mod h1:MjGWpXA31DZZWESdX3/PjIpSWIT1fOm8FNCqyXXFZFU=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
@ -54,6 +50,7 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -192,11 +189,10 @@ github.com/klauspost/reedsolomon v1.11.7/go.mod h1:4bXRN+cVzMdml6ti7qLouuYi32KHJ
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
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/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/lunixbochs/struc v0.0.0-20190916212049-a5c72983bc42/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg=
|
||||
@ -225,6 +221,8 @@ github.com/mustafaturan/monoton v1.0.0/go.mod h1:FOnE7NV3s3EWPXb8/7+/OSdiMBbdlkV
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo/v2 v2.17.0 h1:kdnunFXpBjbzN56hcJHrXZ8M+LOkenKA7NnBzTNigTI=
|
||||
github.com/onsi/ginkgo/v2 v2.17.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
@ -273,8 +271,6 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
|
||||
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
|
||||
github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM=
|
||||
@ -283,8 +279,6 @@ github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr
|
||||
github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
@ -313,8 +307,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@ -358,8 +350,6 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.starlark.net v0.0.0-20230612165344-9532f5667272 h1:2/wtqS591wZyD2OsClsVBKRPEvBsQt/Js+fsCiYhwu8=
|
||||
go.starlark.net v0.0.0-20230612165344-9532f5667272/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
|
||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
@ -580,8 +570,8 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
|
@ -1,78 +0,0 @@
|
||||
package v4
|
||||
|
||||
import (
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common/net/packetaddr"
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
"github.com/v2fly/v2ray-core/v5/common/serial"
|
||||
"github.com/v2fly/v2ray-core/v5/infra/conf/cfgcommon"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/hysteria2"
|
||||
)
|
||||
|
||||
// Hysteria2ServerTarget is configuration of a single hysteria2 server
|
||||
type Hysteria2ServerTarget struct {
|
||||
Address *cfgcommon.Address `json:"address"`
|
||||
Port uint16 `json:"port"`
|
||||
Email string `json:"email"`
|
||||
Level byte `json:"level"`
|
||||
}
|
||||
|
||||
// Hysteria2ClientConfig is configuration of hysteria2 servers
|
||||
type Hysteria2ClientConfig struct {
|
||||
Servers []*Hysteria2ServerTarget `json:"servers"`
|
||||
}
|
||||
|
||||
// Build implements Buildable
|
||||
func (c *Hysteria2ClientConfig) Build() (proto.Message, error) {
|
||||
config := new(hysteria2.ClientConfig)
|
||||
|
||||
if len(c.Servers) == 0 {
|
||||
return nil, newError("0 Hysteria2 server configured.")
|
||||
}
|
||||
|
||||
serverSpecs := make([]*protocol.ServerEndpoint, len(c.Servers))
|
||||
for idx, rec := range c.Servers {
|
||||
if rec.Address == nil {
|
||||
return nil, newError("Hysteria2 server address is not set.")
|
||||
}
|
||||
if rec.Port == 0 {
|
||||
return nil, newError("Invalid Hysteria2 port.")
|
||||
}
|
||||
account := &hysteria2.Account{}
|
||||
hysteria2 := &protocol.ServerEndpoint{
|
||||
Address: rec.Address.Build(),
|
||||
Port: uint32(rec.Port),
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Level: uint32(rec.Level),
|
||||
Email: rec.Email,
|
||||
Account: serial.ToTypedMessage(account),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
serverSpecs[idx] = hysteria2
|
||||
}
|
||||
|
||||
config.Server = serverSpecs
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// Hysteria2ServerConfig is Inbound configuration
|
||||
type Hysteria2ServerConfig struct {
|
||||
PacketEncoding string `json:"packetEncoding"`
|
||||
}
|
||||
|
||||
// Build implements Buildable
|
||||
func (c *Hysteria2ServerConfig) Build() (proto.Message, error) {
|
||||
config := new(hysteria2.ServerConfig)
|
||||
switch c.PacketEncoding {
|
||||
case "Packet":
|
||||
config.PacketEncoding = packetaddr.PacketAddrType_Packet
|
||||
case "", "None":
|
||||
config.PacketEncoding = packetaddr.PacketAddrType_None
|
||||
}
|
||||
return config, nil
|
||||
}
|
@ -16,7 +16,6 @@ import (
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/domainsocket"
|
||||
httpheader "github.com/v2fly/v2ray-core/v5/transport/internet/headers/http"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/http"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/kcp"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/quic"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tcp"
|
||||
@ -144,26 +143,6 @@ type Hy2ConfigCongestion struct {
|
||||
DownMbps uint64 `json:"down_mbps"`
|
||||
}
|
||||
|
||||
type Hy2Config struct {
|
||||
Password string `json:"password"`
|
||||
Congestion Hy2ConfigCongestion `json:"congestion"`
|
||||
UseUdpExtension bool `json:"use_udp_extension"`
|
||||
IgnoreClientBandwidth bool `json:"ignore_client_bandwidth"`
|
||||
}
|
||||
|
||||
// Build implements Buildable.
|
||||
func (c *Hy2Config) Build() (proto.Message, error) {
|
||||
return &hysteria2.Config{Password: c.Password,
|
||||
Congestion: &hysteria2.Congestion{
|
||||
Type: c.Congestion.Type,
|
||||
DownMbps: c.Congestion.DownMbps,
|
||||
UpMbps: c.Congestion.UpMbps,
|
||||
},
|
||||
UseUdpExtension: c.UseUdpExtension,
|
||||
IgnoreClientBandwidth: c.IgnoreClientBandwidth,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type WebSocketConfig struct {
|
||||
Path string `json:"path"`
|
||||
Headers map[string]string `json:"headers"`
|
||||
@ -306,8 +285,6 @@ func (p TransportProtocol) Build() (string, error) {
|
||||
return "quic", nil
|
||||
case "gun", "grpc":
|
||||
return "gun", nil
|
||||
case "hy2", "hysteria2":
|
||||
return "hysteria2", nil
|
||||
default:
|
||||
return "", newError("Config: unknown transport protocol: ", p)
|
||||
}
|
||||
@ -325,7 +302,6 @@ type StreamConfig struct {
|
||||
QUICSettings *QUICConfig `json:"quicSettings"`
|
||||
GunSettings *GunConfig `json:"gunSettings"`
|
||||
GRPCSettings *GunConfig `json:"grpcSettings"`
|
||||
Hy2Settings *Hy2Config `json:"hy2Settings"`
|
||||
SocketSettings *socketcfg.SocketConfig `json:"sockopt"`
|
||||
}
|
||||
|
||||
@ -427,16 +403,6 @@ func (c *StreamConfig) Build() (*internet.StreamConfig, error) {
|
||||
Settings: serial.ToTypedMessage(gs),
|
||||
})
|
||||
}
|
||||
if c.Hy2Settings != nil {
|
||||
hy2, err := c.Hy2Settings.Build()
|
||||
if err != nil {
|
||||
return nil, newError("Failed to build hy2 config.").Base(err)
|
||||
}
|
||||
config.TransportSettings = append(config.TransportSettings, &internet.TransportConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
Settings: serial.ToTypedMessage(hy2),
|
||||
})
|
||||
}
|
||||
if c.SocketSettings != nil {
|
||||
ss, err := c.SocketSettings.Build()
|
||||
if err != nil {
|
||||
|
@ -35,7 +35,6 @@ var (
|
||||
"vless": func() interface{} { return new(VLessInboundConfig) },
|
||||
"vmess": func() interface{} { return new(VMessInboundConfig) },
|
||||
"trojan": func() interface{} { return new(TrojanServerConfig) },
|
||||
"hysteria2": func() interface{} { return new(Hysteria2ServerConfig) },
|
||||
}, "protocol", "settings")
|
||||
|
||||
outboundConfigLoader = loader.NewJSONConfigLoader(loader.ConfigCreatorCache{
|
||||
@ -47,7 +46,6 @@ var (
|
||||
"vless": func() interface{} { return new(VLessOutboundConfig) },
|
||||
"vmess": func() interface{} { return new(VMessOutboundConfig) },
|
||||
"trojan": func() interface{} { return new(TrojanClientConfig) },
|
||||
"hysteria2": func() interface{} { return new(Hysteria2ClientConfig) },
|
||||
"dns": func() interface{} { return new(DNSOutboundConfig) },
|
||||
"loopback": func() interface{} { return new(LoopbackConfig) },
|
||||
}, "protocol", "settings")
|
||||
|
@ -53,7 +53,6 @@ import (
|
||||
_ "github.com/v2fly/v2ray-core/v5/proxy/vlite/inbound"
|
||||
_ "github.com/v2fly/v2ray-core/v5/proxy/vlite/outbound"
|
||||
|
||||
_ "github.com/v2fly/v2ray-core/v5/proxy/hysteria2"
|
||||
_ "github.com/v2fly/v2ray-core/v5/proxy/shadowsocks2022"
|
||||
|
||||
// Transports
|
||||
@ -83,8 +82,6 @@ import (
|
||||
|
||||
_ "github.com/v2fly/v2ray-core/v5/transport/internet/httpupgrade"
|
||||
|
||||
_ "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
|
||||
// Transport headers
|
||||
_ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/http"
|
||||
_ "github.com/v2fly/v2ray-core/v5/transport/internet/headers/noop"
|
||||
|
@ -1,216 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
hyProtocol "github.com/apernet/hysteria/core/v2/international/protocol"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net/packetaddr"
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
"github.com/v2fly/v2ray-core/v5/common/retry"
|
||||
"github.com/v2fly/v2ray-core/v5/common/session"
|
||||
"github.com/v2fly/v2ray-core/v5/common/signal"
|
||||
"github.com/v2fly/v2ray-core/v5/common/task"
|
||||
"github.com/v2fly/v2ray-core/v5/features/policy"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy"
|
||||
"github.com/v2fly/v2ray-core/v5/transport"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
hyTransport "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/udp"
|
||||
)
|
||||
|
||||
// Client is an inbound handler
|
||||
type Client struct {
|
||||
serverPicker protocol.ServerPicker
|
||||
policyManager policy.Manager
|
||||
}
|
||||
|
||||
// NewClient create a new client.
|
||||
func NewClient(ctx context.Context, config *ClientConfig) (*Client, error) {
|
||||
serverList := protocol.NewServerList()
|
||||
for _, rec := range config.Server {
|
||||
s, err := protocol.NewServerSpecFromPB(rec)
|
||||
if err != nil {
|
||||
return nil, newError("failed to parse server spec").Base(err)
|
||||
}
|
||||
serverList.AddServer(s)
|
||||
}
|
||||
if serverList.Size() == 0 {
|
||||
return nil, newError("0 server")
|
||||
}
|
||||
|
||||
v := core.MustFromContext(ctx)
|
||||
client := &Client{
|
||||
serverPicker: protocol.NewRoundRobinServerPicker(serverList),
|
||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
// Process implements OutboundHandler.Process().
|
||||
func (c *Client) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
if outbound == nil || !outbound.Target.IsValid() {
|
||||
return newError("target not specified")
|
||||
}
|
||||
destination := outbound.Target
|
||||
network := destination.Network
|
||||
|
||||
var server *protocol.ServerSpec
|
||||
var conn internet.Connection
|
||||
|
||||
err := retry.ExponentialBackoff(5, 100).On(func() error {
|
||||
server = c.serverPicker.PickServer()
|
||||
rawConn, err := dialer.Dial(ctx, server.Destination())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conn = rawConn
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return newError("failed to find an available destination").AtWarning().Base(err)
|
||||
}
|
||||
newError("tunneling request to ", destination, " via ", server.Destination().NetAddr()).WriteToLog(session.ExportIDToError(ctx))
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
iConn := conn
|
||||
if statConn, ok := conn.(*internet.StatCouterConnection); ok {
|
||||
iConn = statConn.Connection // will not count the UDP traffic.
|
||||
}
|
||||
hyConn, IsHy2Transport := iConn.(*hyTransport.HyConn)
|
||||
|
||||
if !IsHy2Transport && network == net.Network_UDP {
|
||||
// hysteria2 need to use udp extension to proxy UDP.
|
||||
return newError(hyTransport.CanNotUseUdpExtension)
|
||||
}
|
||||
|
||||
user := server.PickUser()
|
||||
userLevel := uint32(0)
|
||||
if user != nil {
|
||||
userLevel = user.Level
|
||||
}
|
||||
sessionPolicy := c.policyManager.ForLevel(userLevel)
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||
|
||||
if packetConn, err := packetaddr.ToPacketAddrConn(link, destination); err == nil {
|
||||
postRequest := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||
|
||||
var buffer [2048]byte
|
||||
n, addr, err := packetConn.ReadFrom(buffer[:])
|
||||
if err != nil {
|
||||
return newError("failed to read a packet").Base(err)
|
||||
}
|
||||
dest := net.DestinationFromAddr(addr)
|
||||
|
||||
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
|
||||
connWriter := &ConnWriter{Writer: bufferWriter, Target: dest}
|
||||
packetWriter := &PacketWriter{Writer: connWriter, Target: dest, HyConn: hyConn}
|
||||
|
||||
// write some request payload to buffer
|
||||
if _, err := packetWriter.WriteTo(buffer[:n], addr); err != nil {
|
||||
return newError("failed to write a request payload").Base(err)
|
||||
}
|
||||
|
||||
// Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer
|
||||
if err = bufferWriter.SetBuffered(false); err != nil {
|
||||
return newError("failed to flush payload").Base(err).AtWarning()
|
||||
}
|
||||
|
||||
return udp.CopyPacketConn(packetWriter, packetConn, udp.UpdateActivity(timer))
|
||||
}
|
||||
|
||||
getResponse := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
|
||||
|
||||
packetReader := &PacketReader{Reader: conn, HyConn: hyConn}
|
||||
packetConnectionReader := &PacketConnectionReader{reader: packetReader}
|
||||
|
||||
return udp.CopyPacketConn(packetConn, packetConnectionReader, udp.UpdateActivity(timer))
|
||||
}
|
||||
|
||||
responseDoneAndCloseWriter := task.OnSuccess(getResponse, task.Close(link.Writer))
|
||||
if err := task.Run(ctx, postRequest, responseDoneAndCloseWriter); err != nil {
|
||||
return newError("connection ends").Base(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
postRequest := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||
|
||||
var bodyWriter buf.Writer
|
||||
bufferWriter := buf.NewBufferedWriter(buf.NewWriter(conn))
|
||||
connWriter := &ConnWriter{Writer: bufferWriter, Target: destination}
|
||||
bodyWriter = connWriter
|
||||
|
||||
if network == net.Network_UDP {
|
||||
bodyWriter = &PacketWriter{Writer: connWriter, Target: destination, HyConn: hyConn}
|
||||
} else {
|
||||
// write some request payload to buffer
|
||||
err = buf.CopyOnceTimeout(link.Reader, bodyWriter, proxy.FirstPayloadTimeout)
|
||||
switch err {
|
||||
case buf.ErrNotTimeoutReader, buf.ErrReadTimeout:
|
||||
if err := connWriter.WriteTCPHeader(); err != nil {
|
||||
return newError("failed to write request header").Base(err).AtWarning()
|
||||
}
|
||||
case nil:
|
||||
default:
|
||||
return newError("failed to write a request payload").Base(err).AtWarning()
|
||||
}
|
||||
// Flush; bufferWriter.WriteMultiBuffer now is bufferWriter.writer.WriteMultiBuffer
|
||||
if err = bufferWriter.SetBuffered(false); err != nil {
|
||||
return newError("failed to flush payload").Base(err).AtWarning()
|
||||
}
|
||||
}
|
||||
|
||||
if err = buf.Copy(link.Reader, bodyWriter, buf.UpdateActivity(timer)); err != nil {
|
||||
return newError("failed to transfer request payload").Base(err).AtInfo()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
getResponse := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
|
||||
|
||||
var reader buf.Reader
|
||||
if network == net.Network_UDP {
|
||||
reader = &PacketReader{
|
||||
Reader: conn, HyConn: hyConn,
|
||||
}
|
||||
} else {
|
||||
ok, msg, err := hyProtocol.ReadTCPResponse(conn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return newError(msg)
|
||||
}
|
||||
reader = buf.NewReader(conn)
|
||||
}
|
||||
return buf.Copy(reader, link.Writer, buf.UpdateActivity(timer))
|
||||
}
|
||||
|
||||
responseDoneAndCloseWriter := task.OnSuccess(getResponse, task.Close(link.Writer))
|
||||
if err := task.Run(ctx, postRequest, responseDoneAndCloseWriter); err != nil {
|
||||
return newError("connection ends").Base(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
return NewClient(ctx, config.(*ClientConfig))
|
||||
}))
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
)
|
||||
|
||||
// MemoryAccount is an account type converted from Account.
|
||||
type MemoryAccount struct{}
|
||||
|
||||
// AsAccount implements protocol.AsAccount.
|
||||
func (a *Account) AsAccount() (protocol.Account, error) {
|
||||
return &MemoryAccount{}, nil
|
||||
}
|
||||
|
||||
// Equals implements protocol.Account.Equals().
|
||||
func (a *MemoryAccount) Equals(another protocol.Account) bool {
|
||||
return false
|
||||
}
|
@ -1,282 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
packetaddr "github.com/v2fly/v2ray-core/v5/common/net/packetaddr"
|
||||
protocol "github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
_ "github.com/v2fly/v2ray-core/v5/common/protoext"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Account struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
}
|
||||
|
||||
func (x *Account) Reset() {
|
||||
*x = Account{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Account) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Account) ProtoMessage() {}
|
||||
|
||||
func (x *Account) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Account.ProtoReflect.Descriptor instead.
|
||||
func (*Account) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_hysteria2_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type ClientConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Server []*protocol.ServerEndpoint `protobuf:"bytes,1,rep,name=server,proto3" json:"server,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ClientConfig) Reset() {
|
||||
*x = ClientConfig{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ClientConfig) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ClientConfig) ProtoMessage() {}
|
||||
|
||||
func (x *ClientConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ClientConfig.ProtoReflect.Descriptor instead.
|
||||
func (*ClientConfig) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_hysteria2_config_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *ClientConfig) GetServer() []*protocol.ServerEndpoint {
|
||||
if x != nil {
|
||||
return x.Server
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
PacketEncoding packetaddr.PacketAddrType `protobuf:"varint,1,opt,name=packet_encoding,json=packetEncoding,proto3,enum=v2ray.core.net.packetaddr.PacketAddrType" json:"packet_encoding,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ServerConfig) Reset() {
|
||||
*x = ServerConfig{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ServerConfig) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ServerConfig) ProtoMessage() {}
|
||||
|
||||
func (x *ServerConfig) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proxy_hysteria2_config_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ServerConfig.ProtoReflect.Descriptor instead.
|
||||
func (*ServerConfig) Descriptor() ([]byte, []int) {
|
||||
return file_proxy_hysteria2_config_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ServerConfig) GetPacketEncoding() packetaddr.PacketAddrType {
|
||||
if x != nil {
|
||||
return x.PacketEncoding
|
||||
}
|
||||
return packetaddr.PacketAddrType(0)
|
||||
}
|
||||
|
||||
var File_proxy_hysteria2_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proxy_hysteria2_config_proto_rawDesc = []byte{
|
||||
0x0a, 0x1c, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61,
|
||||
0x32, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a,
|
||||
0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x78, 0x79,
|
||||
0x2e, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x1a, 0x22, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x6f, 0x6e, 0x2f, 0x6e, 0x65, 0x74, 0x2f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x61, 0x64, 0x64,
|
||||
0x72, 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21,
|
||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2f,
|
||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x65,
|
||||
0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x22, 0x09, 0x0a, 0x07, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x6d,
|
||||
0x0a, 0x0c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x42,
|
||||
0x0a, 0x06, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a,
|
||||
0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x6d,
|
||||
0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2e, 0x53, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x06, 0x73, 0x65, 0x72, 0x76,
|
||||
0x65, 0x72, 0x3a, 0x19, 0x82, 0xb5, 0x18, 0x15, 0x0a, 0x08, 0x6f, 0x75, 0x74, 0x62, 0x6f, 0x75,
|
||||
0x6e, 0x64, 0x12, 0x09, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x22, 0x7c, 0x0a,
|
||||
0x0c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x52, 0x0a,
|
||||
0x0f, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63,
|
||||
0x6f, 0x72, 0x65, 0x2e, 0x6e, 0x65, 0x74, 0x2e, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x61, 0x64,
|
||||
0x64, 0x72, 0x2e, 0x50, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x54, 0x79, 0x70,
|
||||
0x65, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e,
|
||||
0x67, 0x3a, 0x18, 0x82, 0xb5, 0x18, 0x14, 0x0a, 0x07, 0x69, 0x6e, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x12, 0x09, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x42, 0x6f, 0x0a, 0x1e, 0x63,
|
||||
0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72,
|
||||
0x6f, 0x78, 0x79, 0x2e, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x50, 0x01, 0x5a,
|
||||
0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c,
|
||||
0x79, 0x2f, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f,
|
||||
0x70, 0x72, 0x6f, 0x78, 0x79, 0x2f, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0xaa,
|
||||
0x02, 0x1a, 0x56, 0x32, 0x52, 0x61, 0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x50, 0x72, 0x6f,
|
||||
0x78, 0x79, 0x2e, 0x48, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x62, 0x06, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_proxy_hysteria2_config_proto_rawDescOnce sync.Once
|
||||
file_proxy_hysteria2_config_proto_rawDescData = file_proxy_hysteria2_config_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_proxy_hysteria2_config_proto_rawDescGZIP() []byte {
|
||||
file_proxy_hysteria2_config_proto_rawDescOnce.Do(func() {
|
||||
file_proxy_hysteria2_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_proxy_hysteria2_config_proto_rawDescData)
|
||||
})
|
||||
return file_proxy_hysteria2_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_proxy_hysteria2_config_proto_msgTypes = make([]protoimpl.MessageInfo, 3)
|
||||
var file_proxy_hysteria2_config_proto_goTypes = []any{
|
||||
(*Account)(nil), // 0: v2ray.core.proxy.hysteria2.Account
|
||||
(*ClientConfig)(nil), // 1: v2ray.core.proxy.hysteria2.ClientConfig
|
||||
(*ServerConfig)(nil), // 2: v2ray.core.proxy.hysteria2.ServerConfig
|
||||
(*protocol.ServerEndpoint)(nil), // 3: v2ray.core.common.protocol.ServerEndpoint
|
||||
(packetaddr.PacketAddrType)(0), // 4: v2ray.core.net.packetaddr.PacketAddrType
|
||||
}
|
||||
var file_proxy_hysteria2_config_proto_depIdxs = []int32{
|
||||
3, // 0: v2ray.core.proxy.hysteria2.ClientConfig.server:type_name -> v2ray.core.common.protocol.ServerEndpoint
|
||||
4, // 1: v2ray.core.proxy.hysteria2.ServerConfig.packet_encoding:type_name -> v2ray.core.net.packetaddr.PacketAddrType
|
||||
2, // [2:2] is the sub-list for method output_type
|
||||
2, // [2:2] is the sub-list for method input_type
|
||||
2, // [2:2] is the sub-list for extension type_name
|
||||
2, // [2:2] is the sub-list for extension extendee
|
||||
0, // [0:2] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proxy_hysteria2_config_proto_init() }
|
||||
func file_proxy_hysteria2_config_proto_init() {
|
||||
if File_proxy_hysteria2_config_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_proxy_hysteria2_config_proto_msgTypes[0].Exporter = func(v any, i int) any {
|
||||
switch v := v.(*Account); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proxy_hysteria2_config_proto_msgTypes[1].Exporter = func(v any, i int) any {
|
||||
switch v := v.(*ClientConfig); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proxy_hysteria2_config_proto_msgTypes[2].Exporter = func(v any, i int) any {
|
||||
switch v := v.(*ServerConfig); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_proxy_hysteria2_config_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 3,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_proxy_hysteria2_config_proto_goTypes,
|
||||
DependencyIndexes: file_proxy_hysteria2_config_proto_depIdxs,
|
||||
MessageInfos: file_proxy_hysteria2_config_proto_msgTypes,
|
||||
}.Build()
|
||||
File_proxy_hysteria2_config_proto = out.File
|
||||
file_proxy_hysteria2_config_proto_rawDesc = nil
|
||||
file_proxy_hysteria2_config_proto_goTypes = nil
|
||||
file_proxy_hysteria2_config_proto_depIdxs = nil
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.proxy.hysteria2;
|
||||
option csharp_namespace = "V2Ray.Core.Proxy.Hysteria2";
|
||||
option go_package = "github.com/v2fly/v2ray-core/v5/proxy/hysteria2";
|
||||
option java_package = "com.v2ray.core.proxy.hysteria2";
|
||||
option java_multiple_files = true;
|
||||
|
||||
import "common/net/packetaddr/config.proto";
|
||||
import "common/protocol/server_spec.proto";
|
||||
import "common/protoext/extensions.proto";
|
||||
|
||||
message Account {
|
||||
}
|
||||
|
||||
message ClientConfig {
|
||||
option (v2ray.core.common.protoext.message_opt).type = "outbound";
|
||||
option (v2ray.core.common.protoext.message_opt).short_name = "hysteria2";
|
||||
|
||||
repeated v2ray.core.common.protocol.ServerEndpoint server = 1;
|
||||
}
|
||||
|
||||
message ServerConfig {
|
||||
option (v2ray.core.common.protoext.message_opt).type = "inbound";
|
||||
option (v2ray.core.common.protoext.message_opt).short_name = "hysteria2";
|
||||
|
||||
v2ray.core.net.packetaddr.PacketAddrType packet_encoding = 1;
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import "github.com/v2fly/v2ray-core/v5/common/errors"
|
||||
|
||||
type errPathObjHolder struct{}
|
||||
|
||||
func newError(values ...interface{}) *errors.Error {
|
||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
||||
}
|
@ -1 +0,0 @@
|
||||
package hysteria2
|
@ -1,210 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"io"
|
||||
"math/rand"
|
||||
|
||||
hyProtocol "github.com/apernet/hysteria/core/v2/international/protocol"
|
||||
"github.com/apernet/quic-go/quicvarint"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
hyTransport "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
)
|
||||
|
||||
const (
|
||||
paddingChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
)
|
||||
|
||||
// ConnWriter is TCP Connection Writer Wrapper
|
||||
type ConnWriter struct {
|
||||
io.Writer
|
||||
Target net.Destination
|
||||
TCPHeaderSent bool
|
||||
}
|
||||
|
||||
// Write implements io.Writer
|
||||
func (c *ConnWriter) Write(p []byte) (n int, err error) {
|
||||
if !c.TCPHeaderSent {
|
||||
if err := c.writeTCPHeader(); err != nil {
|
||||
return 0, newError("failed to write request header").Base(err)
|
||||
}
|
||||
}
|
||||
|
||||
return c.Writer.Write(p)
|
||||
}
|
||||
|
||||
// WriteMultiBuffer implements buf.Writer
|
||||
func (c *ConnWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
defer buf.ReleaseMulti(mb)
|
||||
|
||||
for _, b := range mb {
|
||||
if !b.IsEmpty() {
|
||||
if _, err := c.Write(b.Bytes()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *ConnWriter) WriteTCPHeader() error {
|
||||
if !c.TCPHeaderSent {
|
||||
if err := c.writeTCPHeader(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func QuicLen(s int) int {
|
||||
return int(quicvarint.Len(uint64(s)))
|
||||
}
|
||||
|
||||
func (c *ConnWriter) writeTCPHeader() error {
|
||||
c.TCPHeaderSent = true
|
||||
|
||||
paddingLen := 64 + rand.Intn(512-64)
|
||||
padding := make([]byte, paddingLen)
|
||||
for i := range padding {
|
||||
padding[i] = paddingChars[rand.Intn(len(paddingChars))]
|
||||
}
|
||||
addressAndPort := c.Target.NetAddr()
|
||||
addressLen := len(addressAndPort)
|
||||
if addressLen > hyProtocol.MaxAddressLength {
|
||||
return newError("address length too large: ", addressLen)
|
||||
}
|
||||
size := QuicLen(addressLen) + addressLen + QuicLen(paddingLen) + paddingLen
|
||||
|
||||
buf := make([]byte, size)
|
||||
i := hyProtocol.VarintPut(buf, uint64(addressLen))
|
||||
i += copy(buf[i:], addressAndPort)
|
||||
i += hyProtocol.VarintPut(buf[i:], uint64(paddingLen))
|
||||
copy(buf[i:], padding)
|
||||
|
||||
_, err := c.Writer.Write(buf)
|
||||
return err
|
||||
}
|
||||
|
||||
// PacketWriter UDP Connection Writer Wrapper
|
||||
type PacketWriter struct {
|
||||
io.Writer
|
||||
HyConn *hyTransport.HyConn
|
||||
Target net.Destination
|
||||
}
|
||||
|
||||
// WriteMultiBuffer implements buf.Writer
|
||||
func (w *PacketWriter) WriteMultiBuffer(mb buf.MultiBuffer) error {
|
||||
for _, b := range mb {
|
||||
if b.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
if _, err := w.writePacket(b.Bytes(), w.Target); err != nil {
|
||||
buf.ReleaseMulti(mb)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteMultiBufferWithMetadata writes udp packet with destination specified
|
||||
func (w *PacketWriter) WriteMultiBufferWithMetadata(mb buf.MultiBuffer, dest net.Destination) error {
|
||||
for _, b := range mb {
|
||||
if b.IsEmpty() {
|
||||
continue
|
||||
}
|
||||
if _, err := w.writePacket(b.Bytes(), dest); err != nil {
|
||||
buf.ReleaseMulti(mb)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *PacketWriter) WriteTo(payload []byte, addr net.Addr) (int, error) {
|
||||
dest := net.DestinationFromAddr(addr)
|
||||
|
||||
return w.writePacket(payload, dest)
|
||||
}
|
||||
|
||||
func (w *PacketWriter) writePacket(payload []byte, dest net.Destination) (int, error) {
|
||||
return w.HyConn.WritePacket(payload, dest)
|
||||
}
|
||||
|
||||
// ConnReader is TCP Connection Reader Wrapper
|
||||
type ConnReader struct {
|
||||
io.Reader
|
||||
Target net.Destination
|
||||
}
|
||||
|
||||
// Read implements io.Reader
|
||||
func (c *ConnReader) Read(p []byte) (int, error) {
|
||||
return c.Reader.Read(p)
|
||||
}
|
||||
|
||||
// ReadMultiBuffer implements buf.Reader
|
||||
func (c *ConnReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
b := buf.New()
|
||||
_, err := b.ReadFrom(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.MultiBuffer{b}, nil
|
||||
}
|
||||
|
||||
// PacketPayload combines udp payload and destination
|
||||
type PacketPayload struct {
|
||||
Target net.Destination
|
||||
Buffer buf.MultiBuffer
|
||||
}
|
||||
|
||||
// PacketReader is UDP Connection Reader Wrapper
|
||||
type PacketReader struct {
|
||||
io.Reader
|
||||
HyConn *hyTransport.HyConn
|
||||
}
|
||||
|
||||
// ReadMultiBuffer implements buf.Reader
|
||||
func (r *PacketReader) ReadMultiBuffer() (buf.MultiBuffer, error) {
|
||||
p, err := r.ReadMultiBufferWithMetadata()
|
||||
if p != nil {
|
||||
return p.Buffer, err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ReadMultiBufferWithMetadata reads udp packet with destination
|
||||
func (r *PacketReader) ReadMultiBufferWithMetadata() (*PacketPayload, error) {
|
||||
_, data, dest, err := r.HyConn.ReadPacket()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := buf.FromBytes(data)
|
||||
return &PacketPayload{Target: *dest, Buffer: buf.MultiBuffer{b}}, nil
|
||||
}
|
||||
|
||||
type PacketConnectionReader struct {
|
||||
reader *PacketReader
|
||||
payload *PacketPayload
|
||||
}
|
||||
|
||||
func (r *PacketConnectionReader) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
|
||||
if r.payload == nil || r.payload.Buffer.IsEmpty() {
|
||||
r.payload, err = r.reader.ReadMultiBufferWithMetadata()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
addr = &net.UDPAddr{
|
||||
IP: r.payload.Target.Address.IP(),
|
||||
Port: int(r.payload.Target.Port),
|
||||
}
|
||||
|
||||
r.payload.Buffer, n = buf.SplitFirstBytes(r.payload.Buffer, p)
|
||||
|
||||
return
|
||||
}
|
@ -1,216 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
hyProtocol "github.com/apernet/hysteria/core/v2/international/protocol"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||
"github.com/v2fly/v2ray-core/v5/common/errors"
|
||||
"github.com/v2fly/v2ray-core/v5/common/log"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net/packetaddr"
|
||||
udp_proto "github.com/v2fly/v2ray-core/v5/common/protocol/udp"
|
||||
"github.com/v2fly/v2ray-core/v5/common/session"
|
||||
"github.com/v2fly/v2ray-core/v5/common/signal"
|
||||
"github.com/v2fly/v2ray-core/v5/common/task"
|
||||
"github.com/v2fly/v2ray-core/v5/features/policy"
|
||||
"github.com/v2fly/v2ray-core/v5/features/routing"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
hyTransport "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/udp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
common.Must(common.RegisterConfig((*ServerConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
|
||||
return NewServer(ctx, config.(*ServerConfig))
|
||||
}))
|
||||
}
|
||||
|
||||
// Server is an inbound connection handler that handles messages in protocol.
|
||||
type Server struct {
|
||||
policyManager policy.Manager
|
||||
packetEncoding packetaddr.PacketAddrType
|
||||
}
|
||||
|
||||
// NewServer creates a new inbound handler.
|
||||
func NewServer(ctx context.Context, config *ServerConfig) (*Server, error) {
|
||||
v := core.MustFromContext(ctx)
|
||||
server := &Server{
|
||||
policyManager: v.GetFeature(policy.ManagerType()).(policy.Manager),
|
||||
packetEncoding: config.PacketEncoding,
|
||||
}
|
||||
return server, nil
|
||||
}
|
||||
|
||||
// Network implements proxy.Inbound.Network().
|
||||
func (s *Server) Network() []net.Network {
|
||||
return []net.Network{net.Network_TCP, net.Network_UNIX}
|
||||
}
|
||||
|
||||
// Process implements proxy.Inbound.Process().
|
||||
func (s *Server) Process(ctx context.Context, network net.Network, conn internet.Connection, dispatcher routing.Dispatcher) error {
|
||||
sid := session.ExportIDToError(ctx)
|
||||
|
||||
iConn := conn
|
||||
if statConn, ok := conn.(*internet.StatCouterConnection); ok {
|
||||
iConn = statConn.Connection // will not count the UDP traffic.
|
||||
}
|
||||
hyConn, IsHy2Transport := iConn.(*hyTransport.HyConn)
|
||||
|
||||
if IsHy2Transport && hyConn.IsUDPExtension {
|
||||
network = net.Network_UDP
|
||||
}
|
||||
|
||||
if !IsHy2Transport && network == net.Network_UDP {
|
||||
return newError(hyTransport.CanNotUseUdpExtension)
|
||||
}
|
||||
|
||||
sessionPolicy := s.policyManager.ForLevel(0)
|
||||
if err := conn.SetReadDeadline(time.Now().Add(sessionPolicy.Timeouts.Handshake)); err != nil {
|
||||
return newError("unable to set read deadline").Base(err).AtWarning()
|
||||
}
|
||||
|
||||
bufferedReader := &buf.BufferedReader{
|
||||
Reader: buf.NewReader(conn),
|
||||
}
|
||||
clientReader := &ConnReader{Reader: bufferedReader}
|
||||
|
||||
if err := conn.SetReadDeadline(time.Time{}); err != nil {
|
||||
return newError("unable to set read deadline").Base(err).AtWarning()
|
||||
}
|
||||
|
||||
if network == net.Network_UDP { // handle udp request
|
||||
return s.handleUDPPayload(ctx,
|
||||
&PacketReader{Reader: clientReader, HyConn: hyConn},
|
||||
&PacketWriter{Writer: conn, HyConn: hyConn}, dispatcher)
|
||||
}
|
||||
|
||||
var reqAddr string
|
||||
var err error
|
||||
reqAddr, err = hyProtocol.ReadTCPRequest(conn)
|
||||
if err != nil {
|
||||
return newError("failed to parse header").Base(err)
|
||||
}
|
||||
err = hyProtocol.WriteTCPResponse(conn, true, "")
|
||||
if err != nil {
|
||||
return newError("failed to send response").Base(err)
|
||||
}
|
||||
|
||||
address, stringPort, err := net.SplitHostPort(reqAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
port, err := net.PortFromString(stringPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
destination := net.Destination{Network: network, Address: net.ParseAddress(address), Port: port}
|
||||
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
if inbound == nil {
|
||||
panic("no inbound metadata")
|
||||
}
|
||||
sessionPolicy = s.policyManager.ForLevel(0)
|
||||
|
||||
ctx = log.ContextWithAccessMessage(ctx, &log.AccessMessage{
|
||||
From: conn.RemoteAddr(),
|
||||
To: destination,
|
||||
Status: log.AccessAccepted,
|
||||
Reason: "",
|
||||
})
|
||||
|
||||
newError("received request for ", destination).WriteToLog(sid)
|
||||
return s.handleConnection(ctx, sessionPolicy, destination, clientReader, buf.NewWriter(conn), dispatcher)
|
||||
}
|
||||
|
||||
func (s *Server) handleConnection(ctx context.Context, sessionPolicy policy.Session,
|
||||
destination net.Destination,
|
||||
clientReader buf.Reader,
|
||||
clientWriter buf.Writer, dispatcher routing.Dispatcher,
|
||||
) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
timer := signal.CancelAfterInactivity(ctx, cancel, sessionPolicy.Timeouts.ConnectionIdle)
|
||||
ctx = policy.ContextWithBufferPolicy(ctx, sessionPolicy.Buffer)
|
||||
|
||||
link, err := dispatcher.Dispatch(ctx, destination)
|
||||
if err != nil {
|
||||
return newError("failed to dispatch request to ", destination).Base(err)
|
||||
}
|
||||
|
||||
requestDone := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.DownlinkOnly)
|
||||
|
||||
if err := buf.Copy(clientReader, link.Writer, buf.UpdateActivity(timer)); err != nil {
|
||||
return newError("failed to transfer request").Base(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
responseDone := func() error {
|
||||
defer timer.SetTimeout(sessionPolicy.Timeouts.UplinkOnly)
|
||||
|
||||
if err := buf.Copy(link.Reader, clientWriter, buf.UpdateActivity(timer)); err != nil {
|
||||
return newError("failed to write response").Base(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
requestDonePost := task.OnSuccess(requestDone, task.Close(link.Writer))
|
||||
if err := task.Run(ctx, requestDonePost, responseDone); err != nil {
|
||||
common.Must(common.Interrupt(link.Reader))
|
||||
common.Must(common.Interrupt(link.Writer))
|
||||
return newError("connection ends").Base(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Server) handleUDPPayload(ctx context.Context, clientReader *PacketReader, clientWriter *PacketWriter, dispatcher routing.Dispatcher) error {
|
||||
udpDispatcherConstructor := udp.NewSplitDispatcher
|
||||
switch s.packetEncoding {
|
||||
case packetaddr.PacketAddrType_None:
|
||||
case packetaddr.PacketAddrType_Packet:
|
||||
packetAddrDispatcherFactory := udp.NewPacketAddrDispatcherCreator(ctx)
|
||||
udpDispatcherConstructor = packetAddrDispatcherFactory.NewPacketAddrDispatcher
|
||||
}
|
||||
|
||||
udpServer := udpDispatcherConstructor(dispatcher, func(ctx context.Context, packet *udp_proto.Packet) {
|
||||
if err := clientWriter.WriteMultiBufferWithMetadata(buf.MultiBuffer{packet.Payload}, packet.Source); err != nil {
|
||||
newError("failed to write response").Base(err).AtWarning().WriteToLog(session.ExportIDToError(ctx))
|
||||
}
|
||||
})
|
||||
|
||||
inbound := session.InboundFromContext(ctx)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
default:
|
||||
p, err := clientReader.ReadMultiBufferWithMetadata()
|
||||
if err != nil {
|
||||
if errors.Cause(err) != io.EOF {
|
||||
return newError("unexpected EOF").Base(err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
currentPacketCtx := ctx
|
||||
currentPacketCtx = log.ContextWithAccessMessage(currentPacketCtx, &log.AccessMessage{
|
||||
From: inbound.Source,
|
||||
To: p.Target,
|
||||
Status: log.AccessAccepted,
|
||||
Reason: "",
|
||||
})
|
||||
newError("tunnelling request to ", p.Target).WriteToLog(session.ExportIDToError(ctx))
|
||||
|
||||
for _, b := range p.Buffer {
|
||||
udpServer.Dispatch(currentPacketCtx, p.Target, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,468 +0,0 @@
|
||||
package scenarios
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
|
||||
core "github.com/v2fly/v2ray-core/v5"
|
||||
"github.com/v2fly/v2ray-core/v5/app/log"
|
||||
"github.com/v2fly/v2ray-core/v5/app/proxyman"
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
clog "github.com/v2fly/v2ray-core/v5/common/log"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol"
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol/tls/cert"
|
||||
"github.com/v2fly/v2ray-core/v5/common/serial"
|
||||
"github.com/v2fly/v2ray-core/v5/common/uuid"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/dokodemo"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/freedom"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/hysteria2"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/vmess"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/vmess/inbound"
|
||||
"github.com/v2fly/v2ray-core/v5/proxy/vmess/outbound"
|
||||
"github.com/v2fly/v2ray-core/v5/testing/servers/tcp"
|
||||
"github.com/v2fly/v2ray-core/v5/testing/servers/udp"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/headers/http"
|
||||
hyTransport "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
tcpTransport "github.com/v2fly/v2ray-core/v5/transport/internet/tcp"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tls"
|
||||
)
|
||||
|
||||
func TestVMessHysteria2Congestion(t *testing.T) {
|
||||
for _, v := range []string{"bbr", "brutal"} {
|
||||
testVMessHysteria2(t, v)
|
||||
}
|
||||
}
|
||||
|
||||
func testVMessHysteria2(t *testing.T, congestionType string) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err := tcpServer.Start()
|
||||
common.Must(err)
|
||||
defer tcpServer.Close()
|
||||
|
||||
userID := protocol.NewID(uuid.New())
|
||||
serverPort := udp.PickPort()
|
||||
serverConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(serverPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
ProtocolName: "hysteria2",
|
||||
Settings: serial.ToTypedMessage(&hyTransport.Config{
|
||||
Congestion: &hyTransport.Congestion{Type: congestionType, UpMbps: 100, DownMbps: 100},
|
||||
Password: "password",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&inbound.Config{
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&vmess.Account{
|
||||
Id: userID.String(),
|
||||
AlterId: 0,
|
||||
}),
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
clientPort := tcp.PickPort()
|
||||
clientConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(clientPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
Address: net.NewIPOrDomain(dest.Address),
|
||||
Port: uint32(dest.Port),
|
||||
NetworkList: &net.NetworkList{
|
||||
Network: []net.Network{net.Network_TCP},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
ServerName: "www.v2fly.org",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
ProtocolName: "hysteria2",
|
||||
Settings: serial.ToTypedMessage(&hyTransport.Config{
|
||||
Congestion: &hyTransport.Congestion{Type: congestionType, UpMbps: 100, DownMbps: 100},
|
||||
Password: "password",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&outbound.Config{
|
||||
Receiver: []*protocol.ServerEndpoint{
|
||||
{
|
||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||
Port: uint32(serverPort),
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&vmess.Account{
|
||||
Id: userID.String(),
|
||||
AlterId: 0,
|
||||
SecuritySettings: &protocol.SecurityConfig{
|
||||
Type: protocol.SecurityType_NONE,
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to initialize all servers: ", err.Error())
|
||||
}
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
var errg errgroup.Group
|
||||
for i := 0; i < 10; i++ {
|
||||
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*40))
|
||||
}
|
||||
|
||||
if err := errg.Wait(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHysteria2Offical(t *testing.T) {
|
||||
for _, v := range []bool{true, false} {
|
||||
testHysteria2Offical(t, v)
|
||||
}
|
||||
}
|
||||
|
||||
func testHysteria2Offical(t *testing.T, isUDP bool) {
|
||||
var dest net.Destination
|
||||
var err error
|
||||
if isUDP {
|
||||
udpServer := udp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err = udpServer.Start()
|
||||
common.Must(err)
|
||||
defer udpServer.Close()
|
||||
} else {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err = tcpServer.Start()
|
||||
common.Must(err)
|
||||
defer tcpServer.Close()
|
||||
}
|
||||
|
||||
serverPort := udp.PickPort()
|
||||
serverConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(serverPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
ProtocolName: "hysteria2",
|
||||
Settings: serial.ToTypedMessage(&hyTransport.Config{
|
||||
Congestion: &hyTransport.Congestion{Type: "brutal", UpMbps: 100, DownMbps: 100},
|
||||
UseUdpExtension: true,
|
||||
Password: "password",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&hysteria2.ServerConfig{}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
clientPort := tcp.PickPort()
|
||||
clientConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(clientPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
Address: net.NewIPOrDomain(dest.Address),
|
||||
Port: uint32(dest.Port),
|
||||
NetworkList: &net.NetworkList{
|
||||
Network: []net.Network{net.Network_TCP, net.Network_UDP},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
ServerName: "www.v2fly.org",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
ProtocolName: "hysteria2",
|
||||
Settings: serial.ToTypedMessage(&hyTransport.Config{
|
||||
Congestion: &hyTransport.Congestion{Type: "brutal", UpMbps: 100, DownMbps: 100},
|
||||
UseUdpExtension: true,
|
||||
Password: "password",
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&hysteria2.ClientConfig{
|
||||
Server: []*protocol.ServerEndpoint{
|
||||
{
|
||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||
Port: uint32(serverPort),
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&hysteria2.Account{}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to initialize all servers: ", err.Error())
|
||||
}
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
var errg errgroup.Group
|
||||
for i := 0; i < 10; i++ {
|
||||
if isUDP {
|
||||
errg.Go(testUDPConn(clientPort, 1024, time.Second*4))
|
||||
} else {
|
||||
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*40))
|
||||
}
|
||||
}
|
||||
|
||||
if err := errg.Wait(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHysteria2OnTCP(t *testing.T) {
|
||||
tcpServer := tcp.Server{
|
||||
MsgProcessor: xor,
|
||||
}
|
||||
dest, err := tcpServer.Start()
|
||||
common.Must(err)
|
||||
defer tcpServer.Close()
|
||||
|
||||
serverPort := udp.PickPort()
|
||||
serverConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(serverPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
Certificate: []*tls.Certificate{tls.ParseCertificate(cert.MustGenerate(nil))},
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
Protocol: internet.TransportProtocol_TCP,
|
||||
Settings: serial.ToTypedMessage(&tcpTransport.Config{
|
||||
HeaderSettings: serial.ToTypedMessage(&http.Config{}),
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&hysteria2.ServerConfig{}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
ProxySettings: serial.ToTypedMessage(&freedom.Config{}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
clientPort := tcp.PickPort()
|
||||
clientConfig := &core.Config{
|
||||
App: []*anypb.Any{
|
||||
serial.ToTypedMessage(&log.Config{
|
||||
Error: &log.LogSpecification{Level: clog.Severity_Debug, Type: log.LogType_Console},
|
||||
}),
|
||||
},
|
||||
Inbound: []*core.InboundHandlerConfig{
|
||||
{
|
||||
ReceiverSettings: serial.ToTypedMessage(&proxyman.ReceiverConfig{
|
||||
PortRange: net.SinglePortRange(clientPort),
|
||||
Listen: net.NewIPOrDomain(net.LocalHostIP),
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&dokodemo.Config{
|
||||
Address: net.NewIPOrDomain(dest.Address),
|
||||
Port: uint32(dest.Port),
|
||||
NetworkList: &net.NetworkList{
|
||||
Network: []net.Network{net.Network_TCP},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
Outbound: []*core.OutboundHandlerConfig{
|
||||
{
|
||||
SenderSettings: serial.ToTypedMessage(&proxyman.SenderConfig{
|
||||
StreamSettings: &internet.StreamConfig{
|
||||
SecurityType: serial.GetMessageType(&tls.Config{}),
|
||||
SecuritySettings: []*anypb.Any{
|
||||
serial.ToTypedMessage(
|
||||
&tls.Config{
|
||||
ServerName: "www.v2fly.org",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
),
|
||||
},
|
||||
TransportSettings: []*internet.TransportConfig{
|
||||
{
|
||||
Protocol: internet.TransportProtocol_TCP,
|
||||
Settings: serial.ToTypedMessage(&tcpTransport.Config{
|
||||
HeaderSettings: serial.ToTypedMessage(&http.Config{}),
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
ProxySettings: serial.ToTypedMessage(&hysteria2.ClientConfig{
|
||||
Server: []*protocol.ServerEndpoint{
|
||||
{
|
||||
Address: net.NewIPOrDomain(net.LocalHostIP),
|
||||
Port: uint32(serverPort),
|
||||
User: []*protocol.User{
|
||||
{
|
||||
Account: serial.ToTypedMessage(&hysteria2.Account{}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
servers, err := InitializeServerConfigs(serverConfig, clientConfig)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to initialize all servers: ", err.Error())
|
||||
}
|
||||
defer CloseAllServers(servers)
|
||||
|
||||
var errg errgroup.Group
|
||||
for i := 0; i < 1; i++ {
|
||||
errg.Go(testTCPConn(clientPort, 10240*1024, time.Second*40))
|
||||
}
|
||||
|
||||
if err := errg.Wait(); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
@ -1,271 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
_ "github.com/v2fly/v2ray-core/v5/common/protoext"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type Congestion struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
|
||||
UpMbps uint64 `protobuf:"varint,2,opt,name=up_mbps,json=upMbps,proto3" json:"up_mbps,omitempty"`
|
||||
DownMbps uint64 `protobuf:"varint,3,opt,name=down_mbps,json=downMbps,proto3" json:"down_mbps,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Congestion) Reset() {
|
||||
*x = Congestion{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_transport_internet_hysteria2_config_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Congestion) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Congestion) ProtoMessage() {}
|
||||
|
||||
func (x *Congestion) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_hysteria2_config_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Congestion.ProtoReflect.Descriptor instead.
|
||||
func (*Congestion) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_hysteria2_config_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *Congestion) GetType() string {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Congestion) GetUpMbps() uint64 {
|
||||
if x != nil {
|
||||
return x.UpMbps
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Congestion) GetDownMbps() uint64 {
|
||||
if x != nil {
|
||||
return x.DownMbps
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"`
|
||||
Congestion *Congestion `protobuf:"bytes,4,opt,name=congestion,proto3" json:"congestion,omitempty"`
|
||||
IgnoreClientBandwidth bool `protobuf:"varint,5,opt,name=ignore_client_bandwidth,json=ignoreClientBandwidth,proto3" json:"ignore_client_bandwidth,omitempty"`
|
||||
UseUdpExtension bool `protobuf:"varint,6,opt,name=use_udp_extension,json=useUdpExtension,proto3" json:"use_udp_extension,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Config) Reset() {
|
||||
*x = Config{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_transport_internet_hysteria2_config_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Config) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Config) ProtoMessage() {}
|
||||
|
||||
func (x *Config) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_transport_internet_hysteria2_config_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Config.ProtoReflect.Descriptor instead.
|
||||
func (*Config) Descriptor() ([]byte, []int) {
|
||||
return file_transport_internet_hysteria2_config_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *Config) GetPassword() string {
|
||||
if x != nil {
|
||||
return x.Password
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Config) GetCongestion() *Congestion {
|
||||
if x != nil {
|
||||
return x.Congestion
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Config) GetIgnoreClientBandwidth() bool {
|
||||
if x != nil {
|
||||
return x.IgnoreClientBandwidth
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *Config) GetUseUdpExtension() bool {
|
||||
if x != nil {
|
||||
return x.UseUdpExtension
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var File_transport_internet_hysteria2_config_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_transport_internet_hysteria2_config_proto_rawDesc = []byte{
|
||||
0x0a, 0x29, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65,
|
||||
0x72, 0x6e, 0x65, 0x74, 0x2f, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x2f, 0x63,
|
||||
0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x27, 0x76, 0x32, 0x72,
|
||||
0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72,
|
||||
0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x79, 0x73, 0x74, 0x65,
|
||||
0x72, 0x69, 0x61, 0x32, 0x1a, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x65, 0x78, 0x74, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x73,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x67, 0x65, 0x73,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x70, 0x5f, 0x6d,
|
||||
0x62, 0x70, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x75, 0x70, 0x4d, 0x62, 0x70,
|
||||
0x73, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x6f, 0x77, 0x6e, 0x5f, 0x6d, 0x62, 0x70, 0x73, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x64, 0x6f, 0x77, 0x6e, 0x4d, 0x62, 0x70, 0x73, 0x22, 0xf9,
|
||||
0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x53, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x76, 0x32, 0x72, 0x61,
|
||||
0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72,
|
||||
0x69, 0x61, 0x32, 0x2e, 0x43, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a,
|
||||
0x63, 0x6f, 0x6e, 0x67, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x17, 0x69, 0x67,
|
||||
0x6e, 0x6f, 0x72, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x62, 0x61, 0x6e, 0x64,
|
||||
0x77, 0x69, 0x64, 0x74, 0x68, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x15, 0x69, 0x67, 0x6e,
|
||||
0x6f, 0x72, 0x65, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x64, 0x77, 0x69, 0x64,
|
||||
0x74, 0x68, 0x12, 0x2a, 0x0a, 0x11, 0x75, 0x73, 0x65, 0x5f, 0x75, 0x64, 0x70, 0x5f, 0x65, 0x78,
|
||||
0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x75,
|
||||
0x73, 0x65, 0x55, 0x64, 0x70, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3a, 0x1a,
|
||||
0x82, 0xb5, 0x18, 0x16, 0x0a, 0x09, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x12,
|
||||
0x09, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x42, 0x96, 0x01, 0x0a, 0x2b, 0x63,
|
||||
0x6f, 0x6d, 0x2e, 0x76, 0x32, 0x72, 0x61, 0x79, 0x2e, 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x74, 0x72,
|
||||
0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74,
|
||||
0x2e, 0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0x50, 0x01, 0x5a, 0x3b, 0x67, 0x69,
|
||||
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x76, 0x32, 0x66, 0x6c, 0x79, 0x2f, 0x76,
|
||||
0x32, 0x72, 0x61, 0x79, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x35, 0x2f, 0x74, 0x72, 0x61,
|
||||
0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2f,
|
||||
0x68, 0x79, 0x73, 0x74, 0x65, 0x72, 0x69, 0x61, 0x32, 0xaa, 0x02, 0x27, 0x56, 0x32, 0x52, 0x61,
|
||||
0x79, 0x2e, 0x43, 0x6f, 0x72, 0x65, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x6f, 0x72, 0x74,
|
||||
0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x2e, 0x48, 0x79, 0x73, 0x74, 0x65, 0x72,
|
||||
0x69, 0x61, 0x32, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_transport_internet_hysteria2_config_proto_rawDescOnce sync.Once
|
||||
file_transport_internet_hysteria2_config_proto_rawDescData = file_transport_internet_hysteria2_config_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_transport_internet_hysteria2_config_proto_rawDescGZIP() []byte {
|
||||
file_transport_internet_hysteria2_config_proto_rawDescOnce.Do(func() {
|
||||
file_transport_internet_hysteria2_config_proto_rawDescData = protoimpl.X.CompressGZIP(file_transport_internet_hysteria2_config_proto_rawDescData)
|
||||
})
|
||||
return file_transport_internet_hysteria2_config_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_transport_internet_hysteria2_config_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
|
||||
var file_transport_internet_hysteria2_config_proto_goTypes = []any{
|
||||
(*Congestion)(nil), // 0: v2ray.core.transport.internet.hysteria2.Congestion
|
||||
(*Config)(nil), // 1: v2ray.core.transport.internet.hysteria2.Config
|
||||
}
|
||||
var file_transport_internet_hysteria2_config_proto_depIdxs = []int32{
|
||||
0, // 0: v2ray.core.transport.internet.hysteria2.Config.congestion:type_name -> v2ray.core.transport.internet.hysteria2.Congestion
|
||||
1, // [1:1] is the sub-list for method output_type
|
||||
1, // [1:1] is the sub-list for method input_type
|
||||
1, // [1:1] is the sub-list for extension type_name
|
||||
1, // [1:1] is the sub-list for extension extendee
|
||||
0, // [0:1] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_transport_internet_hysteria2_config_proto_init() }
|
||||
func file_transport_internet_hysteria2_config_proto_init() {
|
||||
if File_transport_internet_hysteria2_config_proto != nil {
|
||||
return
|
||||
}
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_transport_internet_hysteria2_config_proto_msgTypes[0].Exporter = func(v any, i int) any {
|
||||
switch v := v.(*Congestion); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_transport_internet_hysteria2_config_proto_msgTypes[1].Exporter = func(v any, i int) any {
|
||||
switch v := v.(*Config); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_transport_internet_hysteria2_config_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 2,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_transport_internet_hysteria2_config_proto_goTypes,
|
||||
DependencyIndexes: file_transport_internet_hysteria2_config_proto_depIdxs,
|
||||
MessageInfos: file_transport_internet_hysteria2_config_proto_msgTypes,
|
||||
}.Build()
|
||||
File_transport_internet_hysteria2_config_proto = out.File
|
||||
file_transport_internet_hysteria2_config_proto_rawDesc = nil
|
||||
file_transport_internet_hysteria2_config_proto_goTypes = nil
|
||||
file_transport_internet_hysteria2_config_proto_depIdxs = nil
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package v2ray.core.transport.internet.hysteria2;
|
||||
option csharp_namespace = "V2Ray.Core.Transport.Internet.Hysteria2";
|
||||
option go_package = "github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2";
|
||||
option java_package = "com.v2ray.core.transport.internet.hysteria2";
|
||||
option java_multiple_files = true;
|
||||
|
||||
import "common/protoext/extensions.proto";
|
||||
|
||||
message Congestion{
|
||||
string type = 1;
|
||||
|
||||
uint64 up_mbps = 2;
|
||||
uint64 down_mbps = 3;
|
||||
}
|
||||
|
||||
message Config {
|
||||
option (v2ray.core.common.protoext.message_opt).type = "transport";
|
||||
option (v2ray.core.common.protoext.message_opt).short_name = "hysteria2";
|
||||
|
||||
string password = 3;
|
||||
Congestion congestion = 4;
|
||||
bool ignore_client_bandwidth = 5;
|
||||
bool use_udp_extension = 6;
|
||||
}
|
@ -1,127 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
hyClient "github.com/apernet/hysteria/core/v2/client"
|
||||
"github.com/apernet/hysteria/core/v2/international/protocol"
|
||||
hyServer "github.com/apernet/hysteria/core/v2/server"
|
||||
"github.com/apernet/quic-go"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
)
|
||||
|
||||
const CanNotUseUdpExtension = "Only hysteria2 proxy protocol can use udpExtension."
|
||||
const Hy2MustNeedTLS = "Hysteria2 based on QUIC that requires TLS."
|
||||
|
||||
type HyConn struct {
|
||||
IsUDPExtension bool
|
||||
IsServer bool
|
||||
ClientUDPSession hyClient.HyUDPConn
|
||||
ServerUDPSession *hyServer.UdpSessionEntry
|
||||
|
||||
stream quic.Stream
|
||||
local net.Addr
|
||||
remote net.Addr
|
||||
}
|
||||
|
||||
func (c *HyConn) Read(b []byte) (int, error) {
|
||||
if c.IsUDPExtension {
|
||||
n, data, _, err := c.ReadPacket()
|
||||
copy(b, data)
|
||||
return n, err
|
||||
}
|
||||
return c.stream.Read(b)
|
||||
}
|
||||
|
||||
func (c *HyConn) Write(b []byte) (int, error) {
|
||||
if c.IsUDPExtension {
|
||||
dest, _ := net.ParseDestination("udp:v2fly.org:6666")
|
||||
return c.WritePacket(b, dest)
|
||||
}
|
||||
return c.stream.Write(b)
|
||||
}
|
||||
|
||||
func (c *HyConn) WritePacket(b []byte, dest net.Destination) (int, error) {
|
||||
if !c.IsUDPExtension {
|
||||
return 0, newError(CanNotUseUdpExtension)
|
||||
}
|
||||
|
||||
if c.IsServer {
|
||||
msg := &protocol.UDPMessage{
|
||||
SessionID: c.ServerUDPSession.ID,
|
||||
PacketID: 0,
|
||||
FragID: 0,
|
||||
FragCount: 1,
|
||||
Addr: dest.NetAddr(),
|
||||
Data: b,
|
||||
}
|
||||
c.ServerUDPSession.SendCh <- msg
|
||||
return len(b), nil
|
||||
}
|
||||
return len(b), c.ClientUDPSession.Send(b, dest.NetAddr())
|
||||
}
|
||||
|
||||
func (c *HyConn) ReadPacket() (int, []byte, *net.Destination, error) {
|
||||
if !c.IsUDPExtension {
|
||||
return 0, nil, nil, newError(CanNotUseUdpExtension)
|
||||
}
|
||||
|
||||
if c.IsServer {
|
||||
msg := <-c.ServerUDPSession.ReceiveCh
|
||||
dest, err := net.ParseDestination("udp:" + msg.Addr)
|
||||
return len(msg.Data), msg.Data, &dest, err
|
||||
}
|
||||
data, address, err := c.ClientUDPSession.Receive()
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
dest, err := net.ParseDestination("udp:" + address)
|
||||
if err != nil {
|
||||
return 0, nil, nil, err
|
||||
}
|
||||
return len(data), data, &dest, nil
|
||||
}
|
||||
|
||||
func (c *HyConn) Close() error {
|
||||
if c.IsUDPExtension {
|
||||
if !c.IsServer && c.ClientUDPSession == nil || (c.IsServer && c.ServerUDPSession == nil) {
|
||||
return newError(CanNotUseUdpExtension)
|
||||
}
|
||||
if c.IsServer {
|
||||
c.ServerUDPSession.Close()
|
||||
return c.ServerUDPSession.Conn.Close()
|
||||
}
|
||||
return c.ClientUDPSession.Close()
|
||||
}
|
||||
return c.stream.Close()
|
||||
}
|
||||
|
||||
func (c *HyConn) LocalAddr() net.Addr {
|
||||
return c.local
|
||||
}
|
||||
|
||||
func (c *HyConn) RemoteAddr() net.Addr {
|
||||
return c.remote
|
||||
}
|
||||
|
||||
func (c *HyConn) SetDeadline(t time.Time) error {
|
||||
if c.IsUDPExtension {
|
||||
return nil
|
||||
}
|
||||
return c.stream.SetDeadline(t)
|
||||
}
|
||||
|
||||
func (c *HyConn) SetReadDeadline(t time.Time) error {
|
||||
if c.IsUDPExtension {
|
||||
return nil
|
||||
}
|
||||
return c.stream.SetReadDeadline(t)
|
||||
}
|
||||
|
||||
func (c *HyConn) SetWriteDeadline(t time.Time) error {
|
||||
if c.IsUDPExtension {
|
||||
return nil
|
||||
}
|
||||
return c.stream.SetWriteDeadline(t)
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
hyClient "github.com/apernet/hysteria/core/v2/client"
|
||||
hyProtocol "github.com/apernet/hysteria/core/v2/international/protocol"
|
||||
"github.com/apernet/quic-go/quicvarint"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/session"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tls"
|
||||
)
|
||||
|
||||
type dialerConf struct {
|
||||
net.Destination
|
||||
*internet.MemoryStreamConfig
|
||||
}
|
||||
|
||||
var RunningClient map[dialerConf](hyClient.Client)
|
||||
var ClientMutex sync.Mutex
|
||||
var MBps uint64 = 1000000 / 8 // MByte
|
||||
|
||||
func GetClientTLSConfig(dest net.Destination, streamSettings *internet.MemoryStreamConfig) (*hyClient.TLSConfig, error) {
|
||||
config := tls.ConfigFromStreamSettings(streamSettings)
|
||||
if config == nil {
|
||||
return nil, newError(Hy2MustNeedTLS)
|
||||
}
|
||||
tlsConfig := config.GetTLSConfig(tls.WithDestination(dest))
|
||||
|
||||
return &hyClient.TLSConfig{
|
||||
RootCAs: tlsConfig.RootCAs,
|
||||
ServerName: tlsConfig.ServerName,
|
||||
InsecureSkipVerify: tlsConfig.InsecureSkipVerify,
|
||||
VerifyPeerCertificate: tlsConfig.VerifyPeerCertificate,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ResolveAddress(dest net.Destination) (net.Addr, error) {
|
||||
var destAddr *net.UDPAddr
|
||||
if dest.Address.Family().IsIP() {
|
||||
destAddr = &net.UDPAddr{
|
||||
IP: dest.Address.IP(),
|
||||
Port: int(dest.Port),
|
||||
}
|
||||
} else {
|
||||
addr, err := net.ResolveUDPAddr("udp", dest.NetAddr())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
destAddr = addr
|
||||
}
|
||||
return destAddr, nil
|
||||
}
|
||||
|
||||
type connFactory struct {
|
||||
hyClient.ConnFactory
|
||||
|
||||
NewFunc func(addr net.Addr) (net.PacketConn, error)
|
||||
}
|
||||
|
||||
func (f *connFactory) New(addr net.Addr) (net.PacketConn, error) {
|
||||
return f.NewFunc(addr)
|
||||
}
|
||||
|
||||
func NewHyClient(dest net.Destination, streamSettings *internet.MemoryStreamConfig) (hyClient.Client, error) {
|
||||
tlsConfig, err := GetClientTLSConfig(dest, streamSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
serverAddr, err := ResolveAddress(dest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := streamSettings.ProtocolSettings.(*Config)
|
||||
client, _, err := hyClient.NewClient(&hyClient.Config{
|
||||
Auth: config.GetPassword(),
|
||||
TLSConfig: *tlsConfig,
|
||||
ServerAddr: serverAddr,
|
||||
ConnFactory: &connFactory{
|
||||
NewFunc: func(addr net.Addr) (net.PacketConn, error) {
|
||||
rawConn, err := internet.ListenSystemPacket(context.Background(), &net.UDPAddr{
|
||||
IP: []byte{0, 0, 0, 0},
|
||||
Port: 0,
|
||||
}, streamSettings.SocketSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rawConn.(*net.UDPConn), nil
|
||||
},
|
||||
},
|
||||
BandwidthConfig: hyClient.BandwidthConfig{MaxTx: config.Congestion.GetUpMbps() * MBps, MaxRx: config.GetCongestion().GetDownMbps() * MBps},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func CloseHyClient(dest net.Destination, streamSettings *internet.MemoryStreamConfig) error {
|
||||
ClientMutex.Lock()
|
||||
defer ClientMutex.Unlock()
|
||||
|
||||
client, found := RunningClient[dialerConf{dest, streamSettings}]
|
||||
if found {
|
||||
delete(RunningClient, dialerConf{dest, streamSettings})
|
||||
return client.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetHyClient(dest net.Destination, streamSettings *internet.MemoryStreamConfig) (hyClient.Client, error) {
|
||||
var err error
|
||||
var client hyClient.Client
|
||||
|
||||
ClientMutex.Lock()
|
||||
client, found := RunningClient[dialerConf{dest, streamSettings}]
|
||||
ClientMutex.Unlock()
|
||||
if !found || !CheckHyClientHealthy(client) {
|
||||
if found {
|
||||
// retry
|
||||
CloseHyClient(dest, streamSettings)
|
||||
}
|
||||
client, err = NewHyClient(dest, streamSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ClientMutex.Lock()
|
||||
RunningClient[dialerConf{dest, streamSettings}] = client
|
||||
ClientMutex.Unlock()
|
||||
}
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func CheckHyClientHealthy(client hyClient.Client) bool {
|
||||
quicConn := client.GetQuicConn()
|
||||
if quicConn == nil {
|
||||
return false
|
||||
}
|
||||
select {
|
||||
case <-quicConn.Context().Done():
|
||||
return false
|
||||
default:
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func Dial(ctx context.Context, dest net.Destination, streamSettings *internet.MemoryStreamConfig) (internet.Connection, error) {
|
||||
config := streamSettings.ProtocolSettings.(*Config)
|
||||
|
||||
client, err := GetHyClient(dest, streamSettings)
|
||||
if err != nil {
|
||||
CloseHyClient(dest, streamSettings)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
quicConn := client.GetQuicConn()
|
||||
conn := &HyConn{
|
||||
local: quicConn.LocalAddr(),
|
||||
remote: quicConn.RemoteAddr(),
|
||||
}
|
||||
|
||||
outbound := session.OutboundFromContext(ctx)
|
||||
network := net.Network_TCP
|
||||
if outbound != nil {
|
||||
network = outbound.Target.Network
|
||||
}
|
||||
|
||||
if network == net.Network_UDP && config.GetUseUdpExtension() { // only hysteria2 can use udpExtension
|
||||
conn.IsUDPExtension = true
|
||||
conn.IsServer = false
|
||||
conn.ClientUDPSession, err = client.UDP()
|
||||
if err != nil {
|
||||
CloseHyClient(dest, streamSettings)
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
conn.stream, err = client.OpenStream()
|
||||
if err != nil {
|
||||
CloseHyClient(dest, streamSettings)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// write TCP frame type
|
||||
frameSize := int(quicvarint.Len(hyProtocol.FrameTypeTCPRequest))
|
||||
buf := make([]byte, frameSize)
|
||||
hyProtocol.VarintPut(buf, hyProtocol.FrameTypeTCPRequest)
|
||||
_, err = conn.stream.Write(buf)
|
||||
if err != nil {
|
||||
CloseHyClient(dest, streamSettings)
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
RunningClient = make(map[dialerConf]hyClient.Client)
|
||||
common.Must(internet.RegisterTransportDialer(protocolName, Dial))
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import "github.com/v2fly/v2ray-core/v5/common/errors"
|
||||
|
||||
type errPathObjHolder struct{}
|
||||
|
||||
func newError(values ...interface{}) *errors.Error {
|
||||
return errors.New(values...).WithPathObj(errPathObjHolder{})
|
||||
}
|
@ -1,128 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
hyServer "github.com/apernet/hysteria/core/v2/server"
|
||||
"github.com/apernet/quic-go"
|
||||
"github.com/apernet/quic-go/http3"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tls"
|
||||
)
|
||||
|
||||
// Listener is an internet.Listener that listens for TCP connections.
|
||||
type Listener struct {
|
||||
hyServer hyServer.Server
|
||||
rawConn net.PacketConn
|
||||
addConn internet.ConnHandler
|
||||
}
|
||||
|
||||
// Addr implements internet.Listener.Addr.
|
||||
func (l *Listener) Addr() net.Addr {
|
||||
return l.rawConn.LocalAddr()
|
||||
}
|
||||
|
||||
// Close implements internet.Listener.Close.
|
||||
func (l *Listener) Close() error {
|
||||
return l.hyServer.Close()
|
||||
}
|
||||
|
||||
func (l *Listener) StreamHijacker(ft http3.FrameType, conn quic.Connection, stream quic.Stream, err error) (bool, error) {
|
||||
// err always == nil
|
||||
|
||||
tcpConn := &HyConn{
|
||||
stream: stream,
|
||||
local: conn.LocalAddr(),
|
||||
remote: conn.RemoteAddr(),
|
||||
}
|
||||
l.addConn(tcpConn)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (l *Listener) UdpHijacker(entry *hyServer.UdpSessionEntry, originalAddr string) {
|
||||
addr, err := net.ResolveUDPAddr("udp", originalAddr)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
udpConn := &HyConn{
|
||||
IsUDPExtension: true,
|
||||
IsServer: true,
|
||||
ServerUDPSession: entry,
|
||||
remote: addr,
|
||||
local: l.rawConn.LocalAddr(),
|
||||
}
|
||||
l.addConn(udpConn)
|
||||
}
|
||||
|
||||
// Listen creates a new Listener based on configurations.
|
||||
func Listen(ctx context.Context, address net.Address, port net.Port, streamSettings *internet.MemoryStreamConfig, handler internet.ConnHandler) (internet.Listener, error) {
|
||||
tlsConfig, err := GetServerTLSConfig(streamSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if address.Family().IsDomain() {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
config := streamSettings.ProtocolSettings.(*Config)
|
||||
rawConn, err := internet.ListenSystemPacket(context.Background(),
|
||||
&net.UDPAddr{
|
||||
IP: address.IP(),
|
||||
Port: int(port),
|
||||
}, streamSettings.SocketSettings)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener := &Listener{
|
||||
rawConn: rawConn,
|
||||
addConn: handler,
|
||||
}
|
||||
|
||||
hyServer, err := hyServer.NewServer(&hyServer.Config{
|
||||
Conn: rawConn,
|
||||
TLSConfig: *tlsConfig,
|
||||
DisableUDP: !config.GetUseUdpExtension(),
|
||||
Authenticator: &Authenticator{Password: config.GetPassword()},
|
||||
StreamHijacker: listener.StreamHijacker, // acceptStreams
|
||||
BandwidthConfig: hyServer.BandwidthConfig{MaxTx: config.Congestion.GetUpMbps() * MBps, MaxRx: config.GetCongestion().GetDownMbps() * MBps},
|
||||
UdpSessionHijacker: listener.UdpHijacker, // acceptUDPSession
|
||||
IgnoreClientBandwidth: config.GetIgnoreClientBandwidth(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listener.hyServer = hyServer
|
||||
go hyServer.Serve()
|
||||
return listener, nil
|
||||
}
|
||||
|
||||
func GetServerTLSConfig(streamSettings *internet.MemoryStreamConfig) (*hyServer.TLSConfig, error) {
|
||||
config := tls.ConfigFromStreamSettings(streamSettings)
|
||||
if config == nil {
|
||||
return nil, newError(Hy2MustNeedTLS)
|
||||
}
|
||||
tlsConfig := config.GetTLSConfig()
|
||||
|
||||
return &hyServer.TLSConfig{Certificates: tlsConfig.Certificates, GetCertificate: tlsConfig.GetCertificate}, nil
|
||||
}
|
||||
|
||||
type Authenticator struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
func (a *Authenticator) Authenticate(addr net.Addr, auth string, tx uint64) (ok bool, id string) {
|
||||
if auth == a.Password || a.Password == "" {
|
||||
return true, "user"
|
||||
}
|
||||
return false, ""
|
||||
}
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterTransportListener(protocolName, Listen))
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
package hysteria2_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/common/buf"
|
||||
"github.com/v2fly/v2ray-core/v5/common/net"
|
||||
"github.com/v2fly/v2ray-core/v5/common/protocol/tls/cert"
|
||||
"github.com/v2fly/v2ray-core/v5/common/session"
|
||||
"github.com/v2fly/v2ray-core/v5/testing/servers/udp"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/hysteria2"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet/tls"
|
||||
)
|
||||
|
||||
func TestTCP(t *testing.T) {
|
||||
port := udp.PickPort()
|
||||
|
||||
listener, err := hysteria2.Listen(context.Background(), net.LocalHostIP, port, &internet.MemoryStreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
ProtocolSettings: &hysteria2.Config{Password: "123"},
|
||||
SecurityType: "tls",
|
||||
SecuritySettings: &tls.Config{
|
||||
Certificate: []*tls.Certificate{
|
||||
tls.ParseCertificate(
|
||||
cert.MustGenerate(nil,
|
||||
cert.DNSNames("www.v2fly.org"),
|
||||
),
|
||||
),
|
||||
},
|
||||
},
|
||||
}, func(conn internet.Connection) {
|
||||
go func() {
|
||||
defer conn.Close()
|
||||
|
||||
b := buf.New()
|
||||
defer b.Release()
|
||||
|
||||
for {
|
||||
b.Clear()
|
||||
if _, err := b.ReadFrom(conn); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
common.Must2(conn.Write(b.Bytes()))
|
||||
}
|
||||
}()
|
||||
})
|
||||
common.Must(err)
|
||||
|
||||
defer listener.Close()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
dctx := context.Background()
|
||||
conn, err := hysteria2.Dial(dctx, net.TCPDestination(net.LocalHostIP, port), &internet.MemoryStreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
ProtocolSettings: &hysteria2.Config{Password: "123"},
|
||||
SecurityType: "tls",
|
||||
SecuritySettings: &tls.Config{
|
||||
ServerName: "www.v2fly.org",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
})
|
||||
common.Must(err)
|
||||
defer conn.Close()
|
||||
|
||||
const N = 1000
|
||||
b1 := make([]byte, N)
|
||||
common.Must2(rand.Read(b1))
|
||||
b2 := buf.New()
|
||||
|
||||
common.Must2(conn.Write(b1))
|
||||
|
||||
b2.Clear()
|
||||
common.Must2(b2.ReadFullFrom(conn, N))
|
||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
||||
t.Error(r)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUDP(t *testing.T) {
|
||||
port := udp.PickPort()
|
||||
|
||||
listener, err := hysteria2.Listen(context.Background(), net.LocalHostIP, port, &internet.MemoryStreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
ProtocolSettings: &hysteria2.Config{Password: "123", UseUdpExtension: true},
|
||||
SecurityType: "tls",
|
||||
SecuritySettings: &tls.Config{
|
||||
Certificate: []*tls.Certificate{
|
||||
tls.ParseCertificate(
|
||||
cert.MustGenerate(nil,
|
||||
cert.DNSNames("www.v2fly.org"),
|
||||
),
|
||||
),
|
||||
},
|
||||
},
|
||||
}, func(conn internet.Connection) {
|
||||
fmt.Println("incoming")
|
||||
go func() {
|
||||
defer conn.Close()
|
||||
|
||||
b := buf.New()
|
||||
defer b.Release()
|
||||
|
||||
for {
|
||||
b.Clear()
|
||||
if _, err := b.ReadFrom(conn); err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
common.Must2(conn.Write(b.Bytes()))
|
||||
}
|
||||
}()
|
||||
})
|
||||
common.Must(err)
|
||||
|
||||
defer listener.Close()
|
||||
|
||||
time.Sleep(time.Second)
|
||||
|
||||
address, err := net.ParseDestination("udp:127.0.0.1:1180")
|
||||
dctx := session.ContextWithOutbound(context.Background(), &session.Outbound{Target: address})
|
||||
|
||||
conn, err := hysteria2.Dial(dctx, net.TCPDestination(net.LocalHostIP, port), &internet.MemoryStreamConfig{
|
||||
ProtocolName: "hysteria2",
|
||||
ProtocolSettings: &hysteria2.Config{Password: "123", UseUdpExtension: true},
|
||||
SecurityType: "tls",
|
||||
SecuritySettings: &tls.Config{
|
||||
ServerName: "www.v2fly.org",
|
||||
AllowInsecure: true,
|
||||
},
|
||||
})
|
||||
common.Must(err)
|
||||
defer conn.Close()
|
||||
|
||||
const N = 1000
|
||||
b1 := make([]byte, N)
|
||||
common.Must2(rand.Read(b1))
|
||||
common.Must2(conn.Write(b1))
|
||||
|
||||
b2 := buf.New()
|
||||
b2.Clear()
|
||||
common.Must2(b2.ReadFullFrom(conn, N))
|
||||
if r := cmp.Diff(b2.Bytes(), b1); r != "" {
|
||||
t.Error(r)
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package hysteria2
|
||||
|
||||
import (
|
||||
"github.com/v2fly/v2ray-core/v5/common"
|
||||
"github.com/v2fly/v2ray-core/v5/transport/internet"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/v2fly/v2ray-core/v5/common/errors/errorgen
|
||||
|
||||
const (
|
||||
protocolName = "hysteria2"
|
||||
)
|
||||
|
||||
func init() {
|
||||
common.Must(internet.RegisterProtocolConfigCreator(protocolName, func() interface{} {
|
||||
return new(Config)
|
||||
}))
|
||||
}
|
Loading…
Reference in New Issue
Block a user