diff --git a/go.mod b/go.mod index e7cd5d8..5dba05e 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module goodlink -go 1.25.0 +go 1.25.1 require ( fyne.io/fyne v1.4.3 @@ -14,11 +14,11 @@ require ( github.com/quic-go/quic-go v0.54.0 github.com/sirupsen/logrus v1.9.3 go2 v0.0.0 - golang.org/x/net v0.44.0 golang.org/x/sys v0.36.0 golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb goodlink2 v0.0.0 gvisor.dev/gvisor v0.0.0-20250915223456-0bb00ae3d273 + proxy v0.0.0 ) require ( @@ -71,6 +71,7 @@ require ( golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect golang.org/x/image v0.31.0 // indirect golang.org/x/mod v0.28.0 // indirect + golang.org/x/net v0.44.0 // indirect golang.org/x/sync v0.17.0 // indirect golang.org/x/text v0.29.0 // indirect golang.org/x/time v0.13.0 // indirect @@ -83,6 +84,8 @@ replace go2 => ../go2 replace goodlink2 => ../goodlink2 +replace proxy => ../proxy + replace github.com/quic-go/quic-go => github.com/quic-go/quic-go v0.50.1 replace github.com/imroc/req/v3 => github.com/imroc/req/v3 v3.50.0 diff --git a/go.sum b/go.sum index 26b2046..977d621 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,5 @@ fyne.io/fyne v1.4.3 h1:356CnXCiYrrfaLGsB7qLK3c6ktzyh8WR05v/2RBu51I= fyne.io/fyne v1.4.3/go.mod h1:8kiPBNSDmuplxs9WnKCkaWYqbcXFy0DeAzwa6PBO9Z8= -fyne.io/fyne/v2 v2.6.2 h1:RPgwmXWn+EuP/TKwO7w5p73ILVC26qHD9j3CZUZNwgM= -fyne.io/fyne/v2 v2.6.2/go.mod h1:9IJ8uWgzfcMossFoUkLiOrUIEtaDvF4nML114WiCtXU= fyne.io/fyne/v2 v2.6.3 h1:cvtM2KHeRuH+WhtHiA63z5wJVBkQ9+Ay0UMl9PxFHyA= fyne.io/fyne/v2 v2.6.3/go.mod h1:NGSurpRElVoI1G3h+ab2df3O5KLGh1CGbsMMcX0bPIs= fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg= @@ -21,8 +19,6 @@ 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= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= -github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8= -github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4= github.com/fredbi/uri v1.1.1 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko= github.com/fredbi/uri v1.1.1/go.mod h1:4+DZQ5zBjEwQCDmXW5JdIjz0PUA+yJbvtBv+u+adr5o= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -43,12 +39,10 @@ github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVin github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 h1:RkGhqHxEVAvPM0/R+8g7XRwQnHatO0KAuVcwHo8q9W8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728/go.mod h1:SyRD8YfuKk+ZXlDqYiqe1qMSqjNgtHzBTG810KUagMc= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc= @@ -65,8 +59,6 @@ github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5 h1:xhMrHhTJ6zxu3gA4enFM9MLn9AY7613teCdFnlUVbSQ= -github.com/google/pprof v0.0.0-20250630185457-6e76a2b096b5/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= github.com/google/pprof v0.0.0-20250903194437-c28834ac2320 h1:c7ayAhbRP9HnEl/hg/WQOM9s0snWztfW6feWXZbGHw0= github.com/google/pprof v0.0.0-20250903194437-c28834ac2320/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A= @@ -103,13 +95,10 @@ github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= -github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= github.com/onsi/ginkgo/v2 v2.25.3 h1:Ty8+Yi/ayDAGtk4XxmmfUy4GabvM+MegeB4cDLRi6nw= github.com/onsi/ginkgo/v2 v2.25.3/go.mod h1:43uiyQC4Ed2tkOzLsEYm7hnrb7UJTWHYNsuy3bG/snE= -github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY= -github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o= github.com/onsi/gomega v1.38.2 h1:eZCjf2xjZAqe+LeWvKb5weQ+NcPwX84kqJ0cZNxok2A= +github.com/onsi/gomega v1.38.2/go.mod h1:W2MJcYxRGV63b418Ai34Ud0hEdTVXq9NW9+Sx6uXf3k= github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= github.com/pion/dtls/v2 v2.2.12 h1:KP7H5/c1EiVAAKUmXyCzPiQe5+bCJrpOeKg/L05dunk= github.com/pion/dtls/v2 v2.2.12/go.mod h1:d9SYc9fch0CqK90mRk1dC7AkzzpwJj6u2GU3u+9pqFE= @@ -161,8 +150,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/wlynxg/anet v0.0.3/go.mod h1:eay5PRQr7fIVAMbTbchTnO9gG65Hg/uYGdc7mguHxoA= @@ -178,35 +165,27 @@ go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFX go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= -go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko= -go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= -golang.org/x/exp v0.0.0-20250718183923-645b1fa84792 h1:R9PFI6EUdfVKgwKjZef7QIwGcBKu86OEFpJ9nUEP2l4= -golang.org/x/exp v0.0.0-20250718183923-645b1fa84792/go.mod h1:A+z0yzpGtvnG90cToK5n2tu8UJVP2XUATh+r+sfOOOc= golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU= golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.29.0 h1:HcdsyR4Gsuys/Axh0rDEmlBmB68rW1U9BUdB3UVHsas= -golang.org/x/image v0.29.0/go.mod h1:RVJROnf3SLK8d26OW91j4FrIHGbsJ8QnbEocVTOWQDA= golang.org/x/image v0.31.0 h1:mLChjE2MV6g1S7oqbXC0/UcKijjm5fnJLUYKIYrLESA= golang.org/x/image v0.31.0/go.mod h1:R9ec5Lcp96v9FTF+ajwaH3uGxPH4fKfHHAVbUILxghA= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= -golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -220,16 +199,12 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -247,8 +222,6 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -266,12 +239,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -280,8 +249,6 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -291,9 +258,8 @@ golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeu golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb h1:whnFRlWMcXI9d+ZbWg+4sHnLp52d5yiIPUxMBSt4X9A= golang.zx2c4.com/wireguard v0.0.0-20250521234502-f333402bd9cb/go.mod h1:rpwXGsirqLqN2L0JDJQlwOboGHmptD5ZD6T2VmcqhTw= -google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= -google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A= +google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 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= diff --git a/proxy/proxy_r.go b/proxy/proxy_r.go index 8cf9586..d4171a5 100644 --- a/proxy/proxy_r.go +++ b/proxy/proxy_r.go @@ -3,12 +3,11 @@ package proxy import ( "context" "encoding/binary" + "go2/log" pool2 "go2/pool" - "goodlink/socks5" - "goodlink/utils" "io" - "log" "net" + proxy_handle "proxy/handle" "github.com/quic-go/quic-go" ) @@ -18,12 +17,8 @@ func ProcessProxyServer(stun_quic_conn quic.Connection) { buf := pool2.Malloc(head_len) defer pool2.Free(buf) - socks5_svr, err := socks5.New(&socks5.Config{}) - if err != nil { - utils.Log().DebugF("代理模式: %v\n", err) - return - } - log.Println("开启代理模式") + proxy_handle.Init() + log.Info("开启代理模式") for { fewfgwegwe: @@ -34,7 +29,7 @@ func ProcessProxyServer(stun_quic_conn quic.Connection) { _, err = io.ReadFull(new_quic_stream, buf[:head_len]) if err != nil { - log.Println("read quic head: ", err) + log.Error("read quic head: ", err) new_quic_stream.Close() goto fewfgwegwe } @@ -45,8 +40,9 @@ func ProcessProxyServer(stun_quic_conn quic.Connection) { switch remotePort { case 1080: go func() { + defer new_quic_stream.Close() remoteAddr := stun_quic_conn.RemoteAddr().(*net.UDPAddr) - socks5_svr.ServeConnQuic(new_quic_stream, remoteAddr.IP, remoteAddr.Port) + proxy_handle.Serve(new_quic_stream, remoteAddr.String()) }() default: // 用户反馈无法连接3389端口,修改端口后可以连接 diff --git a/socks5/.gitignore b/socks5/.gitignore deleted file mode 100644 index 0026861..0000000 --- a/socks5/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe diff --git a/socks5/auth.go b/socks5/auth.go deleted file mode 100644 index 9ceb2cb..0000000 --- a/socks5/auth.go +++ /dev/null @@ -1,153 +0,0 @@ -package socks5 - -import ( - "fmt" - pool2 "go2/pool" - "io" -) - -const ( - NoAuth = uint8(0) - noAcceptable = uint8(255) - UserPassAuth = uint8(2) - userAuthVersion = uint8(1) - authSuccess = uint8(0) - authFailure = uint8(1) -) - -var ( - UserAuthFailed = fmt.Errorf("User authentication failed") - NoSupportedAuth = fmt.Errorf("No supported authentication mechanism") -) - -// A Request encapsulates authentication state provided -// during negotiation -type AuthContext struct { - // Provided auth method - Method uint8 - // Payload provided during negotiation. - // Keys depend on the used auth method. - // For UserPassauth contains Username - Payload map[string]string -} - -type Authenticator interface { - Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error) - GetCode() uint8 -} - -// NoAuthAuthenticator is used to handle the "No Authentication" mode -type NoAuthAuthenticator struct{} - -func (a NoAuthAuthenticator) GetCode() uint8 { - return NoAuth -} - -func (a NoAuthAuthenticator) Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error) { - _, err := writer.Write([]byte{socks5Version, NoAuth}) - return &AuthContext{NoAuth, nil}, err -} - -// UserPassAuthenticator is used to handle username/password based -// authentication -type UserPassAuthenticator struct { - Credentials CredentialStore -} - -func (a UserPassAuthenticator) GetCode() uint8 { - return UserPassAuth -} - -func (a UserPassAuthenticator) Authenticate(reader io.Reader, writer io.Writer) (*AuthContext, error) { - // Tell the client to use user/pass auth - if _, err := writer.Write([]byte{socks5Version, UserPassAuth}); err != nil { - return nil, err - } - - // Get the version and username length - header := []byte{0, 0} - if _, err := io.ReadAtLeast(reader, header, 2); err != nil { - return nil, err - } - - // Ensure we are compatible - if header[0] != userAuthVersion { - return nil, fmt.Errorf("Unsupported auth version: %v", header[0]) - } - - // Get the user name - userLen := int(header[1]) - user := make([]byte, userLen) - if _, err := io.ReadAtLeast(reader, user, userLen); err != nil { - return nil, err - } - - // Get the password length - if _, err := reader.Read(header[:1]); err != nil { - return nil, err - } - - // Get the password - passLen := int(header[0]) - pass := pool2.Malloc(passLen) //make([]byte, passLen) - defer pool2.Free(pass) - if _, err := io.ReadAtLeast(reader, pass, passLen); err != nil { - return nil, err - } - - // Verify the password - if a.Credentials.Valid(string(user), string(pass)) { - if _, err := writer.Write([]byte{userAuthVersion, authSuccess}); err != nil { - return nil, err - } - } else { - if _, err := writer.Write([]byte{userAuthVersion, authFailure}); err != nil { - return nil, err - } - return nil, UserAuthFailed - } - - // Done - return &AuthContext{UserPassAuth, map[string]string{"Username": string(user)}}, nil -} - -// authenticate is used to handle connection authentication -func (s *Server) authenticate(conn io.Writer, bufConn io.Reader) (*AuthContext, error) { - // Get the methods - methods, err := readMethods(bufConn) - if err != nil { - return nil, fmt.Errorf("Failed to get auth methods: %v", err) - } - - // Select a usable method - for _, method := range methods { - cator, found := s.authMethods[method] - if found { - return cator.Authenticate(bufConn, conn) - } - } - - // No usable method found - return nil, noAcceptableAuth(conn) -} - -// noAcceptableAuth is used to handle when we have no eligible -// authentication mechanism -func noAcceptableAuth(conn io.Writer) error { - conn.Write([]byte{socks5Version, noAcceptable}) - return NoSupportedAuth -} - -// readMethods is used to read the number of methods -// and proceeding auth methods -func readMethods(r io.Reader) ([]byte, error) { - header := []byte{0} - if _, err := r.Read(header); err != nil { - return nil, err - } - - numMethods := int(header[0]) - methods := make([]byte, numMethods) - _, err := io.ReadAtLeast(r, methods, numMethods) - return methods, err -} diff --git a/socks5/credentials.go b/socks5/credentials.go deleted file mode 100644 index 9666427..0000000 --- a/socks5/credentials.go +++ /dev/null @@ -1,17 +0,0 @@ -package socks5 - -// CredentialStore is used to support user/pass authentication -type CredentialStore interface { - Valid(user, password string) bool -} - -// StaticCredentials enables using a map directly as a credential store -type StaticCredentials map[string]string - -func (s StaticCredentials) Valid(user, password string) bool { - pass, ok := s[user] - if !ok { - return false - } - return password == pass -} diff --git a/socks5/request.go b/socks5/request.go deleted file mode 100644 index 04d5261..0000000 --- a/socks5/request.go +++ /dev/null @@ -1,372 +0,0 @@ -package socks5 - -import ( - "fmt" - pool2 "go2/pool" - "io" - "net" - "strconv" - "strings" - - "github.com/quic-go/quic-go" - "golang.org/x/net/context" -) - -const ( - ConnectCommand = uint8(1) - BindCommand = uint8(2) - AssociateCommand = uint8(3) - ipv4Address = uint8(1) - fqdnAddress = uint8(3) - ipv6Address = uint8(4) -) - -const ( - successReply uint8 = iota - serverFailure - ruleFailure - networkUnreachable - hostUnreachable - connectionRefused - ttlExpired - commandNotSupported - addrTypeNotSupported -) - -var ( - unrecognizedAddrType = fmt.Errorf("Unrecognized address type") -) - -// AddressRewriter is used to rewrite a destination transparently -type AddressRewriter interface { - Rewrite(ctx context.Context, request *Request) (context.Context, *AddrSpec) -} - -// AddrSpec is used to return the target AddrSpec -// which may be specified as IPv4, IPv6, or a FQDN -type AddrSpec struct { - FQDN string - IP net.IP - Port int -} - -func (a *AddrSpec) String() string { - if a.FQDN != "" { - return fmt.Sprintf("%s (%s):%d", a.FQDN, a.IP, a.Port) - } - return fmt.Sprintf("%s:%d", a.IP, a.Port) -} - -// Address returns a string suitable to dial; prefer returning IP-based -// address, fallback to FQDN -func (a AddrSpec) Address() string { - if 0 != len(a.IP) { - return net.JoinHostPort(a.IP.String(), strconv.Itoa(a.Port)) - } - return net.JoinHostPort(a.FQDN, strconv.Itoa(a.Port)) -} - -// A Request represents request received by a server -type Request struct { - // Protocol version - Version uint8 - // Requested command - Command uint8 - // AuthContext provided during negotiation - AuthContext *AuthContext - // AddrSpec of the the network that sent the request - RemoteAddr *AddrSpec - // AddrSpec of the desired destination - DestAddr *AddrSpec - // AddrSpec of the actual destination (might be affected by rewrite) - realDestAddr *AddrSpec - bufConn io.Reader -} - -type conn interface { - Write([]byte) (int, error) - RemoteAddr() net.Addr -} - -// NewRequest creates a new Request from the tcp connection -func NewRequest(bufConn io.Reader) (*Request, error) { - // Read the version byte - header := []byte{0, 0, 0} - if _, err := io.ReadAtLeast(bufConn, header, 3); err != nil { - return nil, fmt.Errorf("Failed to get command version: %v", err) - } - - // Ensure we are compatible - if header[0] != socks5Version { - return nil, fmt.Errorf("Unsupported command version: %v", header[0]) - } - - // Read in the destination address - dest, err := readAddrSpec(bufConn) - if err != nil { - return nil, err - } - - request := &Request{ - Version: socks5Version, - Command: header[1], - DestAddr: dest, - bufConn: bufConn, - } - - return request, nil -} - -// handleRequest is used for request processing after authentication -func (s *Server) handleRequest(req *Request, conn quic.Stream) error { - ctx := context.Background() - - // Resolve the address if we have a FQDN - dest := req.DestAddr - if dest.FQDN != "" { - ctx_, addr, err := s.config.Resolver.Resolve(ctx, dest.FQDN) - if err != nil { - if err := sendReply(conn, hostUnreachable, nil); err != nil { - return fmt.Errorf("Failed to send reply: %v", err) - } - return fmt.Errorf("Failed to resolve destination '%v': %v", dest.FQDN, err) - } - ctx = ctx_ - dest.IP = addr - } - - // Apply any address rewrites - req.realDestAddr = req.DestAddr - if s.config.Rewriter != nil { - ctx, req.realDestAddr = s.config.Rewriter.Rewrite(ctx, req) - } - - // Switch on the command - switch req.Command { - case ConnectCommand: - return s.handleConnect(ctx, conn, req) - case BindCommand: - return s.handleBind(ctx, conn, req) - case AssociateCommand: - return s.handleAssociate(ctx, conn, req) - default: - if err := sendReply(conn, commandNotSupported, nil); err != nil { - return fmt.Errorf("Failed to send reply: %v", err) - } - return fmt.Errorf("Unsupported command: %v", req.Command) - } -} - -// handleConnect is used to handle a connect command -func (s *Server) handleConnect(ctx context.Context, conn quic.Stream, req *Request) error { - // Check if this is allowed - if ctx_, ok := s.config.Rules.Allow(ctx, req); !ok { - if err := sendReply(conn, ruleFailure, nil); err != nil { - return fmt.Errorf("Failed to send reply: %v", err) - } - return fmt.Errorf("Connect to %v blocked by rules", req.DestAddr) - } else { - ctx = ctx_ - } - - // Attempt to connect - dial := s.config.Dial - if dial == nil { - dial = func(ctx context.Context, net_, addr string) (net.Conn, error) { - return net.Dial(net_, addr) - } - } - target, err := dial(ctx, "tcp", req.realDestAddr.Address()) - if err != nil { - msg := err.Error() - resp := hostUnreachable - if strings.Contains(msg, "refused") { - resp = connectionRefused - } else if strings.Contains(msg, "network is unreachable") { - resp = networkUnreachable - } - if err := sendReply(conn, resp, nil); err != nil { - return fmt.Errorf("Failed to send reply: %v", err) - } - return fmt.Errorf("Connect to %v failed: %v", req.DestAddr, err) - } - defer target.Close() - - // Send success - local := target.LocalAddr().(*net.TCPAddr) - bind := AddrSpec{IP: local.IP, Port: local.Port} - if err := sendReply(conn, successReply, &bind); err != nil { - return fmt.Errorf("Failed to send reply: %v", err) - } - - // Start proxying - errCh := make(chan error, 2) - go proxy(target, req.bufConn, errCh) - go proxy(conn, target, errCh) - - // Wait - for i := 0; i < 2; i++ { - e := <-errCh - if e != nil { - // return from this function closes target (and conn). - return e - } - } - return nil -} - -// handleBind is used to handle a connect command -func (s *Server) handleBind(ctx context.Context, conn quic.Stream, req *Request) error { - // Check if this is allowed - if ctx_, ok := s.config.Rules.Allow(ctx, req); !ok { - if err := sendReply(conn, ruleFailure, nil); err != nil { - return fmt.Errorf("Failed to send reply: %v", err) - } - return fmt.Errorf("Bind to %v blocked by rules", req.DestAddr) - } else { - ctx = ctx_ - } - - // TODO: Support bind - if err := sendReply(conn, commandNotSupported, nil); err != nil { - return fmt.Errorf("Failed to send reply: %v", err) - } - return nil -} - -// handleAssociate is used to handle a connect command -func (s *Server) handleAssociate(ctx context.Context, conn quic.Stream, req *Request) error { - // Check if this is allowed - if ctx_, ok := s.config.Rules.Allow(ctx, req); !ok { - if err := sendReply(conn, ruleFailure, nil); err != nil { - return fmt.Errorf("Failed to send reply: %v", err) - } - return fmt.Errorf("Associate to %v blocked by rules", req.DestAddr) - } else { - ctx = ctx_ - } - - // TODO: Support associate - if err := sendReply(conn, commandNotSupported, nil); err != nil { - return fmt.Errorf("Failed to send reply: %v", err) - } - return nil -} - -// readAddrSpec is used to read AddrSpec. -// Expects an address type byte, follwed by the address and port -func readAddrSpec(r io.Reader) (*AddrSpec, error) { - d := &AddrSpec{} - - // Get the address type - addrType := []byte{0} - if _, err := r.Read(addrType); err != nil { - return nil, err - } - - // Handle on a per type basis - switch addrType[0] { - case ipv4Address: - addr := pool2.Malloc(4) //make([]byte, 4) - defer pool2.Free(addr) - if _, err := io.ReadAtLeast(r, addr, len(addr)); err != nil { - return nil, err - } - d.IP = net.IP(addr) - - case ipv6Address: - addr := pool2.Malloc(16) //make([]byte, 16) - defer pool2.Free(addr) - if _, err := io.ReadAtLeast(r, addr, len(addr)); err != nil { - return nil, err - } - d.IP = net.IP(addr) - - case fqdnAddress: - if _, err := r.Read(addrType); err != nil { - return nil, err - } - addrLen := int(addrType[0]) - fqdn := pool2.Malloc(addrLen) //make([]byte, addrLen) - defer pool2.Free(fqdn) - if _, err := io.ReadAtLeast(r, fqdn, addrLen); err != nil { - return nil, err - } - d.FQDN = string(fqdn) - - default: - return nil, unrecognizedAddrType - } - - // Read the port - port := []byte{0, 0} - if _, err := io.ReadAtLeast(r, port, 2); err != nil { - return nil, err - } - d.Port = (int(port[0]) << 8) | int(port[1]) - - return d, nil -} - -// sendReply is used to send a reply message -func sendReply(w io.Writer, resp uint8, addr *AddrSpec) error { - // Format the address - var addrType uint8 - var addrBody []byte - var addrPort uint16 - switch { - case addr == nil: - addrType = ipv4Address - addrBody = []byte{0, 0, 0, 0} - addrPort = 0 - - case addr.FQDN != "": - addrType = fqdnAddress - addrBody = append([]byte{byte(len(addr.FQDN))}, addr.FQDN...) - addrPort = uint16(addr.Port) - - case addr.IP.To4() != nil: - addrType = ipv4Address - addrBody = []byte(addr.IP.To4()) - addrPort = uint16(addr.Port) - - case addr.IP.To16() != nil: - addrType = ipv6Address - addrBody = []byte(addr.IP.To16()) - addrPort = uint16(addr.Port) - - default: - return fmt.Errorf("Failed to format address: %v", addr) - } - - // Format the message - msg := pool2.Malloc(6 + len(addrBody)) //make([]byte, 6+len(addrBody)) - defer pool2.Free(msg) - msg[0] = socks5Version - msg[1] = resp - msg[2] = 0 // Reserved - msg[3] = addrType - copy(msg[4:], addrBody) - msg[4+len(addrBody)] = byte(addrPort >> 8) - msg[4+len(addrBody)+1] = byte(addrPort & 0xff) - - // Send the message - _, err := w.Write(msg) - return err -} - -type closeWriter interface { - CloseWrite() error -} - -// proxy is used to suffle data from src to destination, and sends errors -// down a dedicated channel -func proxy(dst io.Writer, src io.Reader, errCh chan error) { - buf := pool2.Malloc(32 * 1024) // 32KB缓冲区提升性能 - defer pool2.Free(buf) - _, err := io.CopyBuffer(dst, src, buf) - if tcpConn, ok := dst.(closeWriter); ok { - tcpConn.CloseWrite() - } - errCh <- err -} diff --git a/socks5/resolver.go b/socks5/resolver.go deleted file mode 100644 index b75a5c4..0000000 --- a/socks5/resolver.go +++ /dev/null @@ -1,23 +0,0 @@ -package socks5 - -import ( - "net" - - "golang.org/x/net/context" -) - -// NameResolver is used to implement custom name resolution -type NameResolver interface { - Resolve(ctx context.Context, name string) (context.Context, net.IP, error) -} - -// DNSResolver uses the system DNS to resolve host names -type DNSResolver struct{} - -func (d DNSResolver) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) { - addr, err := net.ResolveIPAddr("ip", name) - if err != nil { - return ctx, nil, err - } - return ctx, addr.IP, err -} diff --git a/socks5/ruleset.go b/socks5/ruleset.go deleted file mode 100644 index ba0e353..0000000 --- a/socks5/ruleset.go +++ /dev/null @@ -1,41 +0,0 @@ -package socks5 - -import ( - "golang.org/x/net/context" -) - -// RuleSet is used to provide custom rules to allow or prohibit actions -type RuleSet interface { - Allow(ctx context.Context, req *Request) (context.Context, bool) -} - -// PermitAll returns a RuleSet which allows all types of connections -func PermitAll() RuleSet { - return &PermitCommand{true, true, true} -} - -// PermitNone returns a RuleSet which disallows all types of connections -func PermitNone() RuleSet { - return &PermitCommand{false, false, false} -} - -// PermitCommand is an implementation of the RuleSet which -// enables filtering supported commands -type PermitCommand struct { - EnableConnect bool - EnableBind bool - EnableAssociate bool -} - -func (p *PermitCommand) Allow(ctx context.Context, req *Request) (context.Context, bool) { - switch req.Command { - case ConnectCommand: - return ctx, p.EnableConnect - case BindCommand: - return ctx, p.EnableBind - case AssociateCommand: - return ctx, p.EnableAssociate - } - - return ctx, false -} diff --git a/socks5/socks5.go b/socks5/socks5.go deleted file mode 100644 index 980d821..0000000 --- a/socks5/socks5.go +++ /dev/null @@ -1,146 +0,0 @@ -package socks5 - -import ( - "bufio" - "fmt" - "log" - "net" - "os" - - "github.com/quic-go/quic-go" - "golang.org/x/net/context" -) - -const ( - socks5Version = uint8(5) -) - -// Config is used to setup and configure a Server -type Config struct { - // AuthMethods can be provided to implement custom authentication - // By default, "auth-less" mode is enabled. - // For password-based auth use UserPassAuthenticator. - AuthMethods []Authenticator - - // If provided, username/password authentication is enabled, - // by appending a UserPassAuthenticator to AuthMethods. If not provided, - // and AUthMethods is nil, then "auth-less" mode is enabled. - Credentials CredentialStore - - // Resolver can be provided to do custom name resolution. - // Defaults to DNSResolver if not provided. - Resolver NameResolver - - // Rules is provided to enable custom logic around permitting - // various commands. If not provided, PermitAll is used. - Rules RuleSet - - // Rewriter can be used to transparently rewrite addresses. - // This is invoked before the RuleSet is invoked. - // Defaults to NoRewrite. - Rewriter AddressRewriter - - // BindIP is used for bind or udp associate - BindIP net.IP - - // Logger can be used to provide a custom log target. - // Defaults to stdout. - Logger *log.Logger - - // Optional function for dialing out - Dial func(ctx context.Context, network, addr string) (net.Conn, error) -} - -// Server is reponsible for accepting connections and handling -// the details of the SOCKS5 protocol -type Server struct { - config *Config - authMethods map[uint8]Authenticator -} - -// New creates a new Server and potentially returns an error -func New(conf *Config) (*Server, error) { - // Ensure we have at least one authentication method enabled - if len(conf.AuthMethods) == 0 { - if conf.Credentials != nil { - conf.AuthMethods = []Authenticator{&UserPassAuthenticator{conf.Credentials}} - } else { - conf.AuthMethods = []Authenticator{&NoAuthAuthenticator{}} - } - } - - // Ensure we have a DNS resolver - if conf.Resolver == nil { - conf.Resolver = DNSResolver{} - } - - // Ensure we have a rule set - if conf.Rules == nil { - conf.Rules = PermitAll() - } - - // Ensure we have a log target - if conf.Logger == nil { - conf.Logger = log.New(os.Stdout, "", log.LstdFlags) - } - - server := &Server{ - config: conf, - } - - server.authMethods = make(map[uint8]Authenticator) - - for _, a := range conf.AuthMethods { - server.authMethods[a.GetCode()] = a - } - - return server, nil -} - -func (s *Server) ServeConnQuic(conn quic.Stream, client_ip net.IP, client_port int) error { - defer conn.Close() - bufConn := bufio.NewReader(conn) - - // Read the version byte - version := []byte{0} - if _, err := bufConn.Read(version); err != nil { - s.config.Logger.Printf("[ERR] socks: Failed to get version byte: %v", err) - return err - } - - // Ensure we are compatible - if version[0] != socks5Version { - err := fmt.Errorf("Unsupported SOCKS version: %v", version) - s.config.Logger.Printf("[ERR] socks: %v", err) - return err - } - - // Authenticate the connection - authContext, err := s.authenticate(conn, bufConn) - if err != nil { - err = fmt.Errorf("Failed to authenticate: %v", err) - s.config.Logger.Printf("[ERR] socks: %v", err) - return err - } - - request, err := NewRequest(bufConn) - if err != nil { - if err == unrecognizedAddrType { - if err := sendReply(conn, addrTypeNotSupported, nil); err != nil { - return fmt.Errorf("Failed to send reply: %v", err) - } - } - return fmt.Errorf("Failed to read destination address: %v", err) - } - request.AuthContext = authContext - request.RemoteAddr = &AddrSpec{IP: client_ip, Port: client_port} - - // Process the client request - if err := s.handleRequest(request, conn); err != nil { - err = fmt.Errorf("Failed to handle request: %v", err) - s.config.Logger.Printf("[ERR] socks: %v", err) - return err - } - - return nil -}