diff --git a/config.ini.default b/config.ini.default index 93527f27..5578736a 100644 --- a/config.ini.default +++ b/config.ini.default @@ -99,3 +99,5 @@ versioncheck = # Check if Lantern client matches the semantic version range, l versioncheck-redirect-percentage = 1 # The percentage of requests to be redirected in version check. Defaults to 1 (100%) versioncheck-redirect-url = # The URL to redirect if client is below certain version. Always used along with versioncheck wss-addr = # Address at which to listen for WSS connections. +vmess-addr = # Address at which to listen for vmess connections +vmess-uuids = # UUIDs for vmess connections as a comma separated list \ No newline at end of file diff --git a/go.mod b/go.mod index 768fa3f0..2dbdeae7 100644 --- a/go.mod +++ b/go.mod @@ -37,6 +37,7 @@ require ( github.com/getlantern/psmux v1.5.15 github.com/getlantern/quicwrapper v0.0.0-20231117185542-d951689c4970 github.com/getlantern/ratelimit v0.0.0-20220926192648-933ab81a6fc7 + github.com/getlantern/sing-vmess v0.0.0-20241209111030-0f2c02b4eb9a github.com/getlantern/tinywss v0.0.0-20211216020538-c10008a7d461 github.com/getlantern/tlsdefaults v0.0.0-20171004213447-cf35cfd0b1b4 github.com/getlantern/tlsmasq v0.4.7-0.20230302000139-6e479a593298 @@ -50,6 +51,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/refraction-networking/utls v1.6.7 github.com/refraction-networking/water v0.7.0-alpha + github.com/sagernet/sing v0.6.0-alpha.18 github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726 github.com/spaolacci/murmur3 v1.1.0 github.com/stretchr/testify v1.9.0 @@ -111,23 +113,27 @@ require ( github.com/getlantern/uuid v1.2.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/gofrs/uuid/v5 v5.3.0 // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/google/uuid v1.6.0 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.2 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect + github.com/josharian/native v1.1.0 // indirect github.com/klauspost/compress v1.17.4 // indirect github.com/klauspost/cpuid v1.3.1 // indirect github.com/klauspost/pgzip v1.2.5 // indirect github.com/klauspost/reedsolomon v1.9.9 // indirect github.com/libp2p/go-buffer-pool v0.0.2 // indirect - github.com/mdlayher/netlink v1.1.0 // indirect + github.com/mdlayher/netlink v1.7.2 // indirect + github.com/mdlayher/socket v0.4.1 // indirect github.com/mholt/archiver/v3 v3.5.1 // indirect github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 // indirect github.com/nwaples/rardecode v1.1.2 // indirect @@ -135,7 +141,7 @@ require ( github.com/oschwald/geoip2-golang v1.9.0 // indirect github.com/oschwald/maxminddb-golang v1.11.0 // indirect github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c // indirect - github.com/pierrec/lz4/v4 v4.1.12 // indirect + github.com/pierrec/lz4/v4 v4.1.14 // indirect github.com/pion/datachannel v1.5.5 // indirect github.com/pion/dtls/v2 v2.2.7 // indirect github.com/pion/ice/v2 v2.3.5 // indirect @@ -172,6 +178,7 @@ require ( github.com/tklauser/go-sysconf v0.3.9 // indirect github.com/tklauser/numcpus v0.3.0 // indirect github.com/ulikunitz/xz v0.5.11 // indirect + github.com/vishvananda/netns v0.0.4 // indirect github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect gitlab.com/yawning/edwards25519-extra.git v0.0.0-20211229043746-2f91fcc9fbdb // indirect @@ -182,13 +189,13 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.8.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.29.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/oauth2 v0.20.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect + golang.org/x/text v0.20.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect diff --git a/go.sum b/go.sum index 09a297a0..4909eedd 100644 --- a/go.sum +++ b/go.sum @@ -200,6 +200,8 @@ github.com/getlantern/quicwrapper v0.0.0-20231117185542-d951689c4970 h1:ekTCi+m1 github.com/getlantern/quicwrapper v0.0.0-20231117185542-d951689c4970/go.mod h1:PEDykM1SIU8PTVRrShJ9/WVb/uBpGyl4XBgT+LKw+X4= github.com/getlantern/ratelimit v0.0.0-20220926192648-933ab81a6fc7 h1:47FJ5kTeXc3I1VPpi2hWW9I16/Y3K0cpUq/B7oWJGF8= github.com/getlantern/ratelimit v0.0.0-20220926192648-933ab81a6fc7/go.mod h1:OOqKCIkspqXtIWEex4uhH1H9l7NGekT9i3Hs591ZDk4= +github.com/getlantern/sing-vmess v0.0.0-20241209111030-0f2c02b4eb9a h1:EaWmH5vANbKEXCdfgTChyEpWWwLsSrLPKqO6j0h+IB8= +github.com/getlantern/sing-vmess v0.0.0-20241209111030-0f2c02b4eb9a/go.mod h1:eyj3LXZUf1aYph1WD19MKwbj5kMUQR92WBQfOAYpb/4= github.com/getlantern/telemetry v0.0.0-20230523155019-be7c1d8cd8cb h1:6XZ3Q4oD6A1Tjq6QLgzzQrdQ8FvulzW16HhNQOSECAM= github.com/getlantern/telemetry v0.0.0-20230523155019-be7c1d8cd8cb/go.mod h1:nGOdDc0aD/LRTaY2SGKQ7nsYcWFXrhgkrhIhJuYN614= github.com/getlantern/testify v0.0.0-20160317154340-2eeb3906e78f h1:R6iv+VzCrbxlBm2TcgyJi9c7tQguNXi9JmIvuUJKrdc= @@ -225,8 +227,9 @@ 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/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -235,6 +238,8 @@ github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk= +github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/golang/gddo v0.0.0-20180823221919-9d8ff1c67be5 h1:yrv1uUvgXH/tEat+wdvJMRJ4g51GlIydtDpU9pFjaaI= github.com/golang/gddo v0.0.0-20180823221919-9d8ff1c67be5/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -272,8 +277,8 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= -github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f h1:pDhu5sgp8yJlEF/g6osliIIpF9K4F5jvkULXa4daRDQ= -github.com/google/pprof v0.0.0-20230821062121-407c9e7a662f/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= +github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -290,8 +295,9 @@ github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= +github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= -github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4 h1:nwOc1YaOrYJ37sEBrtWZrdqzK22hiJs3GpDmP3sR2Yw= github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= github.com/kataras/golog v0.1.9 h1:vLvSDpP7kihFGKFAvBSofYo7qZNULYSHOH2D7rPTKJk= github.com/kataras/golog v0.1.9/go.mod h1:jlpk/bOaYCyqDqH18pgDHdaJab72yBE6i0O3s30hpWY= @@ -320,8 +326,11 @@ github.com/libp2p/go-buffer-pool v0.0.2 h1:QNK2iAFa8gjAe1SPz6mHSMuCcjs+X1wlHzeOS github.com/libp2p/go-buffer-pool v0.0.2/go.mod h1:MvaB6xw5vOrDl8rYZGLFdKAuk/hRoRZd1Vi32+RXyFM= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= -github.com/mdlayher/netlink v1.1.0 h1:mpdLgm+brq10nI9zM1BpX1kpDbh3NLl3RSnVq6ZSkfg= github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= github.com/mitchellh/go-server-timing v1.0.0 h1:cdHk4f7lxjwbRqTSGZFw8PCeoNYXGp4T4Sdr8wT+Xlw= @@ -357,8 +366,8 @@ github.com/oschwald/maxminddb-golang v1.11.0/go.mod h1:YmVI+H0zh3ySFR3w+oz8PCfgl github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrec/lz4/v4 v4.1.12 h1:44l88ehTZAUGW4VlO1QC4zkilL99M6Y9MXNwEs0uzP8= -github.com/pierrec/lz4/v4 v4.1.12/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE= +github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8= github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0= github.com/pion/dtls/v2 v2.2.6/go.mod h1:t8fWJCIquY5rlQZwA2yWxUS1+OCrAdXrhVKXB5oD/wY= @@ -430,6 +439,8 @@ 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/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/sagernet/sing v0.6.0-alpha.18 h1:ih4CurU8KvbhfagYjSqVrE2LR0oBSXSZTNH2sAGPGiM= +github.com/sagernet/sing v0.6.0-alpha.18/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/shadowsocks/go-shadowsocks2 v0.1.5 h1:PDSQv9y2S85Fl7VBeOMF9StzeXZyK1HakRm86CUbr28= github.com/shadowsocks/go-shadowsocks2 v0.1.5/go.mod h1:AGGpIoek4HRno4xzyFiAtLHkOpcoznZEkAccaI/rplM= @@ -477,8 +488,9 @@ github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/vharitonsky/iniflags v0.0.0-20180513140207-a33cd0b5f3de h1:fkw+7JkxF3U1GzQoX9h69Wvtvxajo5Rbzy6+YMMzPIg= github.com/vharitonsky/iniflags v0.0.0-20180513140207-a33cd0b5f3de/go.mod h1:irMhzlTz8+fVFj6CH2AN2i+WI5S6wWFtK3MBCIxIpyI= -github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc h1:R83G5ikgLMxrBvLh22JhdfI8K6YXEPHx5P03Uu3DRs4= github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= +github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= +github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM= @@ -550,8 +562,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= @@ -606,8 +618,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -645,8 +657,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -665,8 +677,8 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/http-proxy/main.go b/http-proxy/main.go index a4cbb241..36c7d771 100644 --- a/http-proxy/main.go +++ b/http-proxy/main.go @@ -192,6 +192,11 @@ var ( waterTransport = flag.String("water-transport", "", "WATER based transport name") waterMismatchProtocol = flag.String("water-mismatch-protocol", "", "Mismatch protocol is used to force the executution of a different protocol listener than WATER") + vmessAddr = flag.String("vmess-addr", "", "Address at which to listen for vmess connections.") + vmessUUIDs = flag.String("vmess-uuids", "", "Comma separated list of UUIDs for vmess connections.") + + disablePanicWrap = flag.Bool("disable-panicwrap", false, "Disable panicwrap (for debugging)") + track = flag.String("track", "", "The track this proxy is running on") ) @@ -219,52 +224,53 @@ func main() { } } - // panicwrap works by re-executing the running program (retaining arguments, - // environmental variables, etc.) and monitoring the stderr of the program. - exitStatus, panicWrapErr := panicwrap.Wrap( - &panicwrap.WrapConfig{ - DetectDuration: time.Second, - Handler: func(msg string) { - if reporter != nil { - // heuristically separate the error message from the stack trace - separator := "\ngoroutine " - splitted := strings.SplitN(msg, separator, 2) - err := errors.New(splitted[0]) - var maybeStack []byte - if len(splitted) > 1 { - maybeStack = []byte(separator + splitted[1]) - } - reporter.Report(golog.FATAL, err, maybeStack) - } - if strings.Contains(msg, "maxmind") { - log.Debugf("Panic possibly related to maxmind, delete maxmind database files") - if err := os.Remove(cityDBFile); err != nil { - log.Errorf("Unable to delete city DB file %v: %v", cityDBFile, err) + if !*disablePanicWrap { + // panicwrap works by re-executing the running program (retaining arguments, + // environmental variables, etc.) and monitoring the stderr of the program. + exitStatus, panicWrapErr := panicwrap.Wrap( + &panicwrap.WrapConfig{ + DetectDuration: time.Second, + Handler: func(msg string) { + if reporter != nil { + // heuristically separate the error message from the stack trace + separator := "\ngoroutine " + splitted := strings.SplitN(msg, separator, 2) + err := errors.New(splitted[0]) + var maybeStack []byte + if len(splitted) > 1 { + maybeStack = []byte(separator + splitted[1]) + } + reporter.Report(golog.FATAL, err, maybeStack) } - if err := os.Remove(*geoip2ISPDBFile); err != nil { - log.Errorf("Unable to delete ISP DB file %v: %v", *geoip2ISPDBFile, err) + if strings.Contains(msg, "maxmind") { + log.Debugf("Panic possibly related to maxmind, delete maxmind database files") + if err := os.Remove(cityDBFile); err != nil { + log.Errorf("Unable to delete city DB file %v: %v", cityDBFile, err) + } + if err := os.Remove(*geoip2ISPDBFile); err != nil { + log.Errorf("Unable to delete ISP DB file %v: %v", *geoip2ISPDBFile, err) + } } - } - os.Exit(1) - }, - // Just forward signals to the child process - ForwardSignals: []os.Signal{ - syscall.SIGHUP, - syscall.SIGTERM, - syscall.SIGQUIT, - syscall.SIGINT, - syscall.SIGUSR1, - }, - }) - if panicWrapErr != nil { - log.Fatalf("Error setting up panic wrapper: %v", panicWrapErr) - } else { - // If exitStatus >= 0, then we're the parent process. - if exitStatus >= 0 { - os.Exit(exitStatus) + os.Exit(1) + }, + // Just forward signals to the child process + ForwardSignals: []os.Signal{ + syscall.SIGHUP, + syscall.SIGTERM, + syscall.SIGQUIT, + syscall.SIGINT, + syscall.SIGUSR1, + }, + }) + if panicWrapErr != nil { + log.Fatalf("Error setting up panic wrapper: %v", panicWrapErr) + } else { + // If exitStatus >= 0, then we're the parent process. + if exitStatus >= 0 { + os.Exit(exitStatus) + } } } - // We're in the child (wrapped) process now // Capture signals and exit normally because when relying on the default @@ -478,6 +484,8 @@ func main() { WaterWASMAvailableAt: *waterWASMAvailableAt, WaterTransport: *waterTransport, WaterMismatchProtocol: *waterMismatchProtocol, + VMessAddr: *vmessAddr, + VMessUUIDs: strings.Split(*vmessUUIDs, ","), } if *maxmindLicenseKey != "" { log.Debug("Will use Maxmind for geolocating clients") diff --git a/http_proxy.go b/http_proxy.go index 287f38bd..453f717f 100644 --- a/http_proxy.go +++ b/http_proxy.go @@ -31,8 +31,9 @@ import ( "github.com/getlantern/http-proxy-lantern/v2/broflake" "github.com/getlantern/http-proxy-lantern/v2/opsfilter" "github.com/getlantern/http-proxy-lantern/v2/otel" - shadowsocks "github.com/getlantern/http-proxy-lantern/v2/shadowsocks" + "github.com/getlantern/http-proxy-lantern/v2/shadowsocks" "github.com/getlantern/http-proxy-lantern/v2/starbridge" + "github.com/getlantern/http-proxy-lantern/v2/v2ray/vmess" "github.com/xtaci/smux" @@ -194,6 +195,9 @@ type Proxy struct { WaterAddr string WaterMismatchProtocol string + VMessAddr string + VMessUUIDs []string + throttleConfig throttle.Config instrument instrument.Instrument } @@ -667,6 +671,8 @@ func (p *Proxy) buildOTELOpts(endpoint string, includeProxyName bool) *otel.Opts opts.Addr = p.AlgenevaAddr } else if p.WaterAddr != "" { opts.Addr = p.WaterAddr + } else if p.VMessAddr != "" { + opts.Addr = p.VMessAddr } if includeProxyName { opts.ProxyName = proxyName @@ -989,6 +995,23 @@ func (p *Proxy) listenAlgeneva(baseListen func(string) (net.Listener, error)) li } } +func (p *Proxy) listenVMess(baseListen func(string) (net.Listener, error)) listenerBuilderFN { + return func(addr string) (net.Listener, error) { + base, err := baseListen(addr) + if err != nil { + return nil, err + } + log.Debugf("Listening for vmess at %v", base.Addr()) + wrapper, err := vmess.NewVMessListener(base, p.VMessUUIDs) + if err != nil { + base.Close() + return nil, fmt.Errorf("vmess wrapping error: %w", err) + } + + return wrapper, nil + } +} + // listenWATER start a WATER listener and return it // Currently water doesn't support customized TCP connections and we need to listen and receive requests directly from the WATER listener func (p *Proxy) listenWATER(addr string) (net.Listener, error) { diff --git a/protoListeners.go b/protoListeners.go index d9c45bb0..7f51c75b 100644 --- a/protoListeners.go +++ b/protoListeners.go @@ -30,5 +30,6 @@ func getProtoListenersArgs(p *Proxy) []protoListenerArgs { p.wrapMultiplexing(p.listenShadowsocks), }, {"water", p.WaterAddr, p.wrapMultiplexing(p.listenWATER)}, + {"vmess", p.VMessAddr, p.wrapMultiplexing(p.listenVMess(p.listenTCP))}, } } diff --git a/v2ray/vmess/listener.go b/v2ray/vmess/listener.go new file mode 100644 index 00000000..30e936f5 --- /dev/null +++ b/v2ray/vmess/listener.go @@ -0,0 +1,67 @@ +package vmess + +import ( + "context" + "net" + + vmess "github.com/getlantern/sing-vmess" + N "github.com/getlantern/sing-vmess/network" + "github.com/sagernet/sing/common/metadata" +) + +type listener struct { + net.Listener + service *vmess.Service[int] +} + +func NewVMessListener(baseListener net.Listener, uuids []string) (net.Listener, error) { + var userNum []int + var userAlt []int + for i := range uuids { + userNum = append(userNum, i) + userAlt = append(userAlt, 0) // we don't use altId + } + + l := &listener{baseListener, nil} + l.service = vmess.NewService[int]() + + if err := l.service.UpdateUsers(userNum, uuids, userAlt); err != nil { + return nil, err + } + return l, l.service.Start() +} + +func (l *listener) Close() error { + return l.service.Close() +} + +// handler is a connection handler for VMess inbound connections. +// it's only purpose is to implement N.ConnectionHandler and store the connection +type handler struct { + conn net.Conn + source metadata.Socksaddr + destination metadata.Socksaddr +} + +func (h *handler) NewConnectionEx(_ context.Context, conn net.Conn, source metadata.Socksaddr, destination metadata.Socksaddr, _ N.CloseHandlerFunc) { + h.conn = conn + h.source = source + h.destination = destination +} + +func (h *handler) NewPacketConnectionEx(_ context.Context, _ N.PacketConn, _ metadata.Socksaddr, _ metadata.Socksaddr, _ N.CloseHandlerFunc) { + // not used +} + +func (l *listener) Accept() (net.Conn, error) { + conn, err := l.Listener.Accept() + if err != nil { + return nil, err + } + h := &handler{} + err = l.service.NewConnection(context.Background(), conn, metadata.Socksaddr{}, nil, h) + if err != nil { + return nil, err + } + return h.conn, nil +} diff --git a/v2ray/vmess/listener_test.go b/v2ray/vmess/listener_test.go new file mode 100644 index 00000000..c79d067a --- /dev/null +++ b/v2ray/vmess/listener_test.go @@ -0,0 +1,167 @@ +package vmess + +import ( + "fmt" + "net" + "testing" + "time" + + vmess "github.com/getlantern/sing-vmess" + "github.com/sagernet/sing/common/metadata" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestWrap(t *testing.T) { + securityOptions := []string{"zero", "auto", "none", "aes-128-gcm", "chacha20-poly1305"} + for _, securityOption := range securityOptions { + t.Run(securityOption, func(t *testing.T) { + uuid := "3fed9a96-900c-4dd4-9fd2-f333a566768c" + var ( + clientMsg = "hello from the client" + serverMsg = "hello from the server" + ) + + tcpListener, err := net.Listen("tcp", "localhost:0") + require.NoError(t, err) + defer tcpListener.Close() + + l, err := NewVMessListener(tcpListener, []string{uuid}) + require.NoError(t, err) + defer l.Close() + + type result struct { + msg string + err error + } + + serverResC := make(chan result) + go func() { + serverResC <- func() result { + conn, err := l.Accept() + if err != nil { + return result{err: fmt.Errorf("accept error: %w", err)} + } + defer conn.Close() + + buf := make([]byte, 1024) + n, err := conn.Read(buf) + if err != nil { + return result{err: fmt.Errorf("read error: %w", err)} + } + + if _, err := conn.Write([]byte(serverMsg)); err != nil { + return result{err: fmt.Errorf("write error: %w", err)} + } + + return result{msg: string(buf[:n])} + }() + }() + + clientResC := make(chan result) + go func() { + clientResC <- func() result { + tcpConn, err := net.Dial("tcp", l.Addr().String()) + if err != nil { + return result{err: fmt.Errorf("dial error: %w", err)} + } + defer tcpConn.Close() + + client, err := vmess.NewClient(uuid, securityOption, 0) + require.NoError(t, err) + + target := metadata.ParseSocksaddrHostPort("random.stuff.com", 443) + + conn := client.DialEarlyConn(tcpConn, target) + + _, err = conn.Write([]byte(clientMsg)) + if err != nil { + return result{err: fmt.Errorf("write error: %w", err)} + } + + buf := make([]byte, 1024) + n, err := conn.Read(buf) + if err != nil { + return result{err: fmt.Errorf("read error: %w", err)} + } + + return result{msg: string(buf[:n])} + }() + }() + + for i := 0; i < 2; i++ { + select { + case res := <-clientResC: + if assert.NoError(t, res.err) { + assert.Equal(t, serverMsg, res.msg) + } + case res := <-serverResC: + if assert.NoError(t, res.err) { + assert.Equal(t, clientMsg, res.msg) + } + } + } + }) + } +} + +func TestUUIDMismatch(t *testing.T) { + uuid1 := "3fed9a96-900c-4dd4-9fd2-f333a5667681" + uuid2 := "3fed9a96-900c-4dd4-9fd2-f333a5667682" + + tcpListener, err := net.Listen("tcp", "localhost:0") + require.NoError(t, err) + defer tcpListener.Close() + + l, err := NewVMessListener(tcpListener, []string{uuid1}) + require.NoError(t, err) + defer l.Close() + + serverResC := make(chan error) + go func() { + serverResC <- func() error { + _, err := l.Accept() + require.Error(t, err) + return nil + }() + }() + + clientResC := make(chan error) + go func() { + clientResC <- func() error { + tcpConn, err := net.Dial("tcp", l.Addr().String()) + if err != nil { + return err + } + defer tcpConn.Close() + + client, err := vmess.NewClient(uuid2, "auto", 0) + require.NoError(t, err) + + target := metadata.ParseSocksaddrHostPort("random.stuff.com", 443) + + conn := client.DialEarlyConn(tcpConn, target) + + _, err = conn.Write([]byte("test that will fail")) + if err != nil { + return fmt.Errorf("write error: %w", err) + } + + buf := make([]byte, 1024) + _ = conn.SetDeadline(time.Now().Add(100 * time.Millisecond)) + _, err = conn.Read(buf) + require.Error(t, err) + return nil + }() + }() + + for i := 0; i < 2; i++ { + select { + case res := <-clientResC: + require.NoError(t, res) + case res := <-serverResC: + assert.NoError(t, res) + + } + } +}