@@ -2,12 +2,15 @@ package handler
22
33import (
44 "context"
5+ "encoding/binary"
56 "errors"
67 "fmt"
78 "io"
89 "log"
10+ "math/rand/v2"
911 "net"
1012 "net/http"
13+ "strconv"
1114 "strings"
1215 "sync"
1316
@@ -170,6 +173,25 @@ func (s *ProxyHandler) HandleRequest(wr http.ResponseWriter, req *http.Request,
170173 s .forward (req .Context (), username , wrapH1RespWriter (wr ), wrapH1ReqBody (resp .Body ))
171174}
172175
176+ func (s * ProxyHandler ) HandleGetRandom (wr http.ResponseWriter , req * http.Request , username string ) {
177+ if len (req .URL .Path ) <= 1 || req .URL .Path [0 ] != '/' {
178+ http .Error (wr , "Incorrect requested random data length" , http .StatusBadRequest )
179+ }
180+ length , err := strconv .ParseInt (req .URL .Path [1 :], 10 , 64 )
181+ if err != nil || length < 0 {
182+ http .Error (wr , "Incorrect requested random data length" , http .StatusBadRequest )
183+ }
184+ var seed [32 ]byte
185+ binary .NativeEndian .PutUint64 (seed [0 :], rand .Uint64 ())
186+ binary .NativeEndian .PutUint64 (seed [8 :], rand .Uint64 ())
187+ binary .NativeEndian .PutUint64 (seed [16 :], rand .Uint64 ())
188+ binary .NativeEndian .PutUint64 (seed [24 :], rand .Uint64 ())
189+ rng := rand .NewChaCha8 (seed )
190+ wr .Header ().Set ("Content-Length" , strconv .FormatInt (length , 10 ))
191+ wr .WriteHeader (http .StatusOK )
192+ io .Copy (wr , io .LimitReader (rng , length ))
193+ }
194+
173195func (s * ProxyHandler ) isLoopback (req * http.Request ) (string , bool ) {
174196 s .outboundMux .RLock ()
175197 originator , found := s .outbound [req .RemoteAddr ]
@@ -185,8 +207,8 @@ func (s *ProxyHandler) ServeHTTP(wr http.ResponseWriter, req *http.Request) {
185207 return
186208 }
187209
188- isConnect := strings .ToUpper (req .Method ) == "CONNECT"
189- if (req .URL .Host == "" || req .URL .Scheme == "" && ! isConnect ) && req .ProtoMajor < 2 ||
210+ method := strings .ToUpper (req .Method )
211+ if (req .URL .Host == "" || req .URL .Scheme == "" && method != "CONNECT" ) && req .ProtoMajor < 2 ||
190212 req .Host == "" && req .ProtoMajor == 2 {
191213 http .Error (wr , auth .BAD_REQ_MSG , http .StatusBadRequest )
192214 return
@@ -213,9 +235,12 @@ func (s *ProxyHandler) ServeHTTP(wr http.ResponseWriter, req *http.Request) {
213235 ctx = ddto .FilterParamsToContext (ctx , req , username )
214236 req = req .WithContext (ctx )
215237 delHopHeaders (req .Header )
216- if isConnect {
238+ switch method {
239+ case "CONNECT" :
217240 s .HandleTunnel (wr , req , username )
218- } else {
241+ case "GETRANDOM" :
242+ s .HandleGetRandom (wr , req , username )
243+ default :
219244 s .HandleRequest (wr , req , username )
220245 }
221246}
0 commit comments