diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 34aad372..3b66b7db 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,4 +1,4 @@ -* @OutlineFoundation/outline-dev +* @Jigsaw-Code/outline-dev /src/server_manager/model/ @fortuna /src/shadowbox/ @fortuna diff --git a/.github/workflows/build_and_test_debug.yml b/.github/workflows/build_and_test_debug.yml index 441bc05e..39bd1af0 100644 --- a/.github/workflows/build_and_test_debug.yml +++ b/.github/workflows/build_and_test_debug.yml @@ -43,16 +43,8 @@ jobs: node-version: 18 cache: npm - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - cache: false - - name: Install NPM Dependencies run: npm ci - env: - PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: 'true' - name: Lint run: ./task lint @@ -89,40 +81,6 @@ jobs: files: | src/shadowbox/server/api.yml - shadowbox-arm64: - name: Shadowbox (arm64) - runs-on: ubuntu-22.04-arm - needs: lint - steps: - - name: Checkout - uses: actions/checkout@v2.3.4 - - - name: Install Node - uses: actions/setup-node@v3 - with: - node-version: 18 - cache: npm - - - name: Install Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - cache: false - - - name: Install NPM Dependencies - run: npm ci - env: - PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: 'true' - - - name: Shadowbox Debug Build (arm64) - run: TARGET_ARCH=aarch64 ./task shadowbox:build - - - name: Shadowbox Unit Test - run: ./task shadowbox:test - - - name: Shadowbox Docker Build (arm64) - run: TARGET_ARCH=aarch64 ./task shadowbox:docker:build - manual-install-script: name: Manual Install Script runs-on: ubuntu-latest @@ -161,8 +119,7 @@ jobs: sentry-webhook: name: Sentry Webhook - # TODO(puppeteer/puppeteer#12818): Update when chromium bug is resolved. - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest needs: lint steps: - name: Checkout diff --git a/.github/workflows/pull_request_checks.yml b/.github/workflows/pull_request_checks.yml index 3b27ae42..f10203bc 100644 --- a/.github/workflows/pull_request_checks.yml +++ b/.github/workflows/pull_request_checks.yml @@ -37,10 +37,10 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - name: Clone Repository - uses: actions/checkout@v4 + uses: actions/checkout@v2 - name: Install Node - uses: actions/setup-node@v6.1.0 + uses: actions/setup-node@v2.2.0 with: node-version: 18 cache: npm @@ -49,7 +49,7 @@ jobs: run: npm ci - name: Ensure Commitizen Format - uses: JulienKode/pull-request-name-linter-action@v20.1.0 + uses: JulienKode/pull-request-name-linter-action@98794a8b815ec05560813c42e55fd8d32d3fd248 size_label: name: Change Size Label diff --git a/README.md b/README.md index dfb518e4..9ab5ac45 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # Outline Server -![Build and Test](https://github.com/OutlineFoundation/outline-server/actions/workflows/build_and_test_debug.yml/badge.svg?branch=master) [![Mattermost](https://badgen.net/badge/Mattermost/Outline%20Community/blue)](https://community.internetfreedomfestival.org/community/channels/outline-community) [![Reddit](https://badgen.net/badge/Reddit/r%2Foutlinevpn/orange)](https://www.reddit.com/r/outlinevpn/) +![Build and Test](https://github.com/Jigsaw-Code/outline-server/actions/workflows/build_and_test_debug.yml/badge.svg?branch=master) [![Mattermost](https://badgen.net/badge/Mattermost/Outline%20Community/blue)](https://community.internetfreedomfestival.org/community/channels/outline-community) [![Reddit](https://badgen.net/badge/Reddit/r%2Foutlinevpn/orange)](https://www.reddit.com/r/outlinevpn/) -Outline Server is the component that provides the Shadowsocks service (via [outline-ss-server](https://github.com/OutlineFoundation/tunnel-server/)) and a service management API. You can deploy this server directly following simple instructions in this repository, or if you prefer a ready-to-use graphical interface you can use the [Outline Manager](https://github.com/OutlineFoundation/outline-apps/). +Outline Server is the component that provides the Shadowsocks service (via [outline-ss-server](https://github.com/Jigsaw-Code/outline-ss-server/)) and a service management API. You can deploy this server directly following simple instructions in this repository, or if you prefer a ready-to-use graphical interface you can use the [Outline Manager](https://github.com/Jigsaw-Code/outline-apps/). **Components:** -- **Outline Server** ([`src/shadowbox`](src/shadowbox)): The core proxy server that runs and manages [outline-ss-server](https://github.com/OutlineFoundation/tunnel-server/), a Shadowsocks backend. It provides a REST API for access key management. +- **Outline Server** ([`src/shadowbox`](src/shadowbox)): The core proxy server that runs and manages [outline-ss-server](https://github.com/Jigsaw-Code/outline-ss-server/), a Shadowsocks backend. It provides a REST API for access key management. - **Metrics Server** ([`src/metrics_server`](src/metrics_server)): A REST service for optional, anonymous metrics sharing. diff --git a/docs/shadowsocks.md b/docs/shadowsocks.md index 35b899f4..e8f426e9 100644 --- a/docs/shadowsocks.md +++ b/docs/shadowsocks.md @@ -20,6 +20,6 @@ The censors used to block Shadowsocks, but Shadowsocks has evolved, and in 2021, In 2022 China started blocking seemingly random traffic ([report](https://www.opentech.fund/news/exposing-the-great-firewalls-dynamic-blocking-of-fully-encrypted-traffic/)). While there is no evidence they could detect Shadowsocks, the protocol ended up blocked. -As a reponse, we [added a feature to the Outline Client](https://github.com/OutlineFoundation/outline-apps/pull/1454) that allows service managers to specify a **[connection prefix disguise](https://www.reddit.com/r/outlinevpn/wiki/index/prefixing/)** to be used in the Shadowsocks initialization, which can be used to bypass the blocking in China by making it look like a protocol that is allowed. +As a reponse, we [added a feature to the Outline Client](https://github.com/Jigsaw-Code/outline-apps/pull/1454) that allows service managers to specify a **[connection prefix disguise](https://www.reddit.com/r/outlinevpn/wiki/index/prefixing/)** to be used in the Shadowsocks initialization, which can be used to bypass the blocking in China by making it look like a protocol that is allowed. Shadowsocks remains our protocol of choice because it's simple, well understood and very performant. Furthermore, it has an enthusiastic community of very smart people behind it. diff --git a/go.mod b/go.mod index f5572f2c..49855d17 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,16 @@ module localhost -go 1.26.3 +go 1.22 require ( - github.com/Jigsaw-Code/outline-ss-server v1.7.3 + github.com/Jigsaw-Code/outline-ss-server v1.9.2-0.20250218165321-888b9dcbdf1c github.com/go-task/task/v3 v3.36.0 github.com/google/addlicense v1.1.1 ) require ( - github.com/Jigsaw-Code/outline-sdk v0.0.14 // indirect + github.com/Jigsaw-Code/outline-sdk v0.0.18-0.20241106233708-faffebb12629 // indirect + github.com/Jigsaw-Code/outline-sdk/x v0.0.0-20250130222646-80b6430a1fc8 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bmatcuk/doublestar/v4 v4.0.2 // indirect @@ -17,7 +18,10 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.16.0 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/go-viper/mapstructure/v2 v2.2.1 // indirect github.com/golang/protobuf v1.5.3 // indirect + github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 // indirect + github.com/gorilla/websocket v1.5.3 // indirect github.com/joho/godotenv v1.5.1 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/lmittmann/tint v1.0.5 // indirect @@ -37,11 +41,11 @@ require ( github.com/shadowsocks/go-shadowsocks2 v0.1.5 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/zeebo/xxh3 v1.0.2 // indirect - golang.org/x/crypto v0.45.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.38.0 // indirect - golang.org/x/term v0.37.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.23.0 // indirect + golang.org/x/term v0.23.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect mvdan.cc/sh/v3 v3.8.0 // indirect ) diff --git a/go.sum b/go.sum index f86ef755..a7475566 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,9 @@ -github.com/Jigsaw-Code/outline-sdk v0.0.14 h1:uJLvIne7YJNolbX7KDacd8gLidrUzRuweBO2APmQEmI= -github.com/Jigsaw-Code/outline-sdk v0.0.14/go.mod h1:9cEaF6sWWMzY8orcUI9pV5D0oFp2FZArTSyJiYtMQQs= -github.com/Jigsaw-Code/outline-ss-server v1.7.3 h1:UF8AaOV2agRb6edF0U0CtTcwpyIxm6NVDa5QLkQh28E= -github.com/Jigsaw-Code/outline-ss-server v1.7.3/go.mod h1:cKPicPWlLWZKJfkQ3CBpQm8a3gXrA2+dpQvsECqBVz8= +github.com/Jigsaw-Code/outline-sdk v0.0.18-0.20241106233708-faffebb12629 h1:sHi1X4vwtNNBUDCbxynGXe7cM/inwTbavowHziaxlbk= +github.com/Jigsaw-Code/outline-sdk v0.0.18-0.20241106233708-faffebb12629/go.mod h1:CFDKyGZA4zatKE4vMLe8TyQpZCyINOeRFbMAmYHxodw= +github.com/Jigsaw-Code/outline-sdk/x v0.0.0-20250130222646-80b6430a1fc8 h1:TsWEVm5XU/SalHlZ6VztE9YwHmN0akCgbWFgQ0j7Mys= +github.com/Jigsaw-Code/outline-sdk/x v0.0.0-20250130222646-80b6430a1fc8/go.mod h1:aFUEz6Z/eD0NS3c3fEIX+JO2D9aIrXCmWTb1zJFlItw= +github.com/Jigsaw-Code/outline-ss-server v1.9.2-0.20250218165321-888b9dcbdf1c h1:e8G2DgRGZmhJCgrJw//+IQYkBckmGA4ZeOP4GjkQEDw= +github.com/Jigsaw-Code/outline-ss-server v1.9.2-0.20250218165321-888b9dcbdf1c/go.mod h1:ArtQJ43aUTB5r1gr27E6aMj4nDOZz5vG4WY4NNKJ6ZM= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -22,6 +24,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/task/v3 v3.36.0 h1:XVJ5hQ5hdzTAulHpAGzbUMUuYr9MUOEQFOFazI3hUsY= github.com/go-task/task/v3 v3.36.0/go.mod h1:XBCIAzuyG/mgZVHMUm3cCznz4+IpsBQRlW1gw7OA5sA= +github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss= +github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= @@ -32,6 +36,10 @@ github.com/google/addlicense v1.1.1/go.mod h1:Sm/DHu7Jk+T5miFHHehdIjbi4M5+dJDRS3 github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33 h1:893HsJqtxp9z1SF76gg6hY70hRY1wVlTSnC/h1yUDCo= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= @@ -91,28 +99,28 @@ github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= -golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.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.37.0 h1:8EGAD0qCmHYZg6J17DvsMy9/wJ7/D/4pV/wfnld5lTU= -golang.org/x/term v0.37.0/go.mod h1:5pB4lxRNYYVZuTLmy8oR2BH8dflOR+IbTYFD8fi3254= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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= diff --git a/package-lock.json b/package-lock.json index 30073280..b4d82a70 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1891,19 +1891,6 @@ "concat-map": "0.0.1" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/browserslist": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", @@ -3832,19 +3819,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/finalhandler": { "version": "1.1.2", "dev": true, @@ -4800,16 +4774,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, "node_modules/is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -5246,6 +5210,17 @@ "node": ">=8" } }, + "node_modules/karma/node_modules/braces": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/karma/node_modules/chokidar": { "version": "3.5.3", "dev": true, @@ -5272,6 +5247,17 @@ "fsevents": "~2.3.2" } }, + "node_modules/karma/node_modules/fill-range": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/karma/node_modules/fsevents": { "version": "2.3.2", "dev": true, @@ -5306,6 +5292,14 @@ "node": ">=8" } }, + "node_modules/karma/node_modules/is-number": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/karma/node_modules/readdirp": { "version": "3.6.0", "dev": true, @@ -5331,6 +5325,17 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/karma/node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -5609,6 +5614,51 @@ "node": ">=8.6" } }, + "node_modules/micromatch/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/micromatch/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/micromatch/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/micromatch/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/mime": { "version": "2.6.0", "dev": true, @@ -6044,7 +6094,8 @@ }, "node_modules/outline-shadowsocksconfig": { "version": "0.2.0", - "resolved": "git+ssh://git@github.com/OutlineFoundation/shadowsocksconfig.git#add590ed57277653d02dd2031ae301500ae881e1", + "resolved": "git+ssh://git@github.com/Jigsaw-Code/outline-shadowsocksconfig.git#add590ed57277653d02dd2031ae301500ae881e1", + "license": "Apache-2.0", "dependencies": { "ipaddr.js": "^2.0.0", "js-base64": "^3.5.2", @@ -8080,19 +8131,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, "node_modules/toidentifier": { "version": "1.0.1", "license": "MIT", @@ -9018,7 +9056,7 @@ "dependencies": { "ip-regex": "^4.1.0", "js-yaml": "^3.12.0", - "outline-shadowsocksconfig": "github:OutlineFoundation/shadowsocksconfig#v0.2.0", + "outline-shadowsocksconfig": "github:Jigsaw-Code/outline-shadowsocksconfig#v0.2.0", "prom-client": "^11.1.3", "randomstring": "^1.1.5", "restify": "^11.1.0", @@ -10385,15 +10423,6 @@ "concat-map": "0.0.1" } }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "requires": { - "fill-range": "^7.1.1" - } - }, "browserslist": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", @@ -11702,15 +11731,6 @@ "flat-cache": "^3.0.4" } }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, "finalhandler": { "version": "1.1.2", "dev": true, @@ -12332,12 +12352,6 @@ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", "dev": true }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, "is-number-object": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", @@ -12574,6 +12588,13 @@ "version": "2.2.0", "dev": true }, + "braces": { + "version": "3.0.2", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "chokidar": { "version": "3.5.3", "dev": true, @@ -12588,6 +12609,13 @@ "readdirp": "~3.6.0" } }, + "fill-range": { + "version": "7.0.1", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, "fsevents": { "version": "2.3.2", "dev": true, @@ -12607,6 +12635,10 @@ "binary-extensions": "^2.0.0" } }, + "is-number": { + "version": "7.0.0", + "dev": true + }, "readdirp": { "version": "3.6.0", "dev": true, @@ -12620,6 +12652,13 @@ "requires": { "glob": "^7.1.3" } + }, + "to-regex-range": { + "version": "5.0.1", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } } } }, @@ -12887,6 +12926,41 @@ "requires": { "braces": "^3.0.2", "picomatch": "^2.3.1" + }, + "dependencies": { + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } } }, "mime": { @@ -13190,7 +13264,7 @@ "@types/tmp": "^0.2.1", "ip-regex": "^4.1.0", "js-yaml": "^3.12.0", - "outline-shadowsocksconfig": "github:OutlineFoundation/shadowsocksconfig#v0.2.0", + "outline-shadowsocksconfig": "github:Jigsaw-Code/outline-shadowsocksconfig#v0.2.0", "prom-client": "^11.1.3", "randomstring": "^1.1.5", "restify": "^11.1.0", @@ -13210,8 +13284,8 @@ } }, "outline-shadowsocksconfig": { - "version": "git+ssh://git@github.com/OutlineFoundation/shadowsocksconfig.git#add590ed57277653d02dd2031ae301500ae881e1", - "from": "outline-shadowsocksconfig@github:OutlineFoundation/shadowsocksconfig#v0.2.0", + "version": "git+ssh://git@github.com/Jigsaw-Code/outline-shadowsocksconfig.git#add590ed57277653d02dd2031ae301500ae881e1", + "from": "outline-shadowsocksconfig@github:Jigsaw-Code/outline-shadowsocksconfig#v0.2.0", "requires": { "ipaddr.js": "^2.0.0", "js-base64": "^3.5.2", @@ -14667,15 +14741,6 @@ } } }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, "toidentifier": { "version": "1.0.1" }, diff --git a/src/metrics_server/connection_metrics.spec.ts b/src/metrics_server/connection_metrics.spec.ts index 41aa3af4..15fb97ca 100644 --- a/src/metrics_server/connection_metrics.spec.ts +++ b/src/metrics_server/connection_metrics.spec.ts @@ -34,7 +34,7 @@ const VALID_USER_REPORT2: HourlyUserConnectionMetricsReport = { /* * Legacy access key user reports to ensure backwards compatibility with servers not - * synced past https://github.com/OutlineFoundation/outline-server/pull/1529). + * synced past https://github.com/Jigsaw-Code/outline-server/pull/1529). */ const LEGACY_PER_KEY_USER_REPORT: HourlyUserConnectionMetricsReport = { userId: 'foo', @@ -43,7 +43,7 @@ const LEGACY_PER_KEY_USER_REPORT: HourlyUserConnectionMetricsReport = { /* * Legacy multiple countries user reports to ensure backwards compatibility with servers - * not synced past https://github.com/OutlineFoundation/outline-server/pull/1242. + * not synced past https://github.com/Jigsaw-Code/outline-server/pull/1242. */ const LEGACY_PER_LOCATION_USER_REPORT: HourlyUserConnectionMetricsReport = { userId: 'foobar', diff --git a/src/server_manager/README.md b/src/server_manager/README.md index c0a8a86d..2672de2d 100644 --- a/src/server_manager/README.md +++ b/src/server_manager/README.md @@ -1,5 +1,5 @@ # Outline Manager -> THIS PROJECT HAS MOVED TO A [NEW LOCATION](https://github.com/OutlineFoundation/outline-apps/tree/master/server_manager): Outline Manager is now part of the [Outline Apps repository](https://github.com/OutlineFoundation/outline-apps). +> THIS PROJECT HAS MOVED TO A [NEW LOCATION](https://github.com/Jigsaw-Code/outline-apps/tree/master/): Outline Manager is now part of the [Outline Apps repository](https://github.com/Jigsaw-Code/outline-apps). -We are keeping this folder to support legacy versions of the app that point to the old [server install script](https://github.com/OutlineFoundation/outline-server/blob/master/src/server_manager/install_scripts/install_server.sh). +We are keeping this folder to support legacy versions of the app that point to the old [server install script](https://github.com/Jigsaw-Code/outline-server/blob/master/src/server_manager/install_scripts/install_server.sh). diff --git a/src/server_manager/install_scripts/install_server.sh b/src/server_manager/install_scripts/install_server.sh index 9bf72a09..39ba2b0d 100755 --- a/src/server_manager/install_scripts/install_server.sh +++ b/src/server_manager/install_scripts/install_server.sh @@ -160,7 +160,7 @@ function fetch() { function install_docker() { ( # Change umask so that /usr/share/keyrings/docker-archive-keyring.gpg has the right permissions. - # See https://github.com/OutlineFoundation/outline-server/issues/951. + # See https://github.com/Jigsaw-Code/outline-server/issues/951. # We do this in a subprocess so the umask for the calling process is unaffected. umask 0022 fetch https://get.docker.com/ | sh @@ -376,7 +376,7 @@ function start_watchtower() { -v /var/run/docker.sock:/var/run/docker.sock) # By itself, local messes up the return code. local STDERR_OUTPUT - STDERR_OUTPUT="$(docker run -d "${docker_watchtower_flags[@]}" nickfedor/watchtower --cleanup --label-enable --scope=outline --tlsverify --interval "${WATCHTOWER_REFRESH_SECONDS}" 2>&1 >/dev/null)" && return + STDERR_OUTPUT="$(docker run -d "${docker_watchtower_flags[@]}" containrrr/watchtower --cleanup --label-enable --scope=outline --tlsverify --interval "${WATCHTOWER_REFRESH_SECONDS}" 2>&1 >/dev/null)" && return readonly STDERR_OUTPUT log_error "FAILED" if docker_container_exists watchtower; then @@ -440,7 +440,7 @@ Make sure to open the following ports on your firewall, router or cloud provider function set_hostname() { # These are URLs that return the client's apparent IP address. # We have more than one to try in case one starts failing - # (e.g. https://github.com/OutlineFoundation/outline-server/issues/776). + # (e.g. https://github.com/Jigsaw-Code/outline-server/issues/776). local -ar urls=( 'https://icanhazip.com/' 'https://ipinfo.io/ip' @@ -456,8 +456,8 @@ function set_hostname() { install_shadowbox() { local MACHINE_TYPE MACHINE_TYPE="$(uname -m)" - if [[ "${MACHINE_TYPE}" != "x86_64" && "${MACHINE_TYPE}" != "aarch64" && "${MACHINE_TYPE}" != "arm64" ]]; then - log_error "Unsupported machine type: ${MACHINE_TYPE}. Supported architectures: x86_64, aarch64/arm64." + if [[ "${MACHINE_TYPE}" != "x86_64" ]]; then + log_error "Unsupported machine type: ${MACHINE_TYPE}. Please run this script on a x86_64 machine" exit 1 fi diff --git a/src/shadowbox/CHANGELOG.md b/src/shadowbox/CHANGELOG.md index 8074d6af..af5a38eb 100644 --- a/src/shadowbox/CHANGELOG.md +++ b/src/shadowbox/CHANGELOG.md @@ -1,22 +1,20 @@ # 1.7.2 - - Fixes - - Fix reporting of country metrics and improve logging output (https://github.com/OutlineFoundation/outline-server/pull/1242) + - Fix reporting of country metrics and improve logging output (https://github.com/Jigsaw-Code/outline-server/pull/1242) # 1.7.1 - - Fixes - - Corner case of isPortUsed that could result in infinite restart loop (https://github.com/OutlineFoundation/outline-server/pull/1238) - - Prevent excessive logging (https://github.com/OutlineFoundation/outline-server/pull/1232) + - Corner case of isPortUsed that could result in infinite restart loop (https://github.com/Jigsaw-Code/outline-server/pull/1238) + - Prevent excessive logging (https://github.com/Jigsaw-Code/outline-server/pull/1232) # 1.7.0 - Features - - Add encryption cipher selection to create access key API (https://github.com/OutlineFoundation/outline-server/pull/1002) - - Make access key secrets longer (https://github.com/OutlineFoundation/outline-server/pull/1098) + - Add encryption cipher selection to create access key API (https://github.com/Jigsaw-Code/outline-server/pull/1002) + - Make access key secrets longer (https://github.com/Jigsaw-Code/outline-server/pull/1098) - Fixes - - Race condition on concurrent API calls (https://github.com/OutlineFoundation/outline-server/pull/995) -- Upgrades (https://github.com/OutlineFoundation/outline-server/pull/1211) + - Race condition on concurrent API calls (https://github.com/Jigsaw-Code/outline-server/pull/995) +- Upgrades (https://github.com/Jigsaw-Code/outline-server/pull/1211) - Base image to `node:16.18.0-alpine3.16` - - outline-ss-server from 1.3.5 to [1.4.0](https://github.com/OutlineFoundation/outline-ss-server/releases/tag/v1.4.0) + - outline-ss-server from 1.3.5 to [1.4.0](https://github.com/Jigsaw-Code/outline-ss-server/releases/tag/v1.4.0) - Prometheus from 2.33.5 to [2.37.1](https://github.com/prometheus/prometheus/releases/tag/v2.37.1) diff --git a/src/shadowbox/README.md b/src/shadowbox/README.md index 8462adf7..c0519aa2 100644 --- a/src/shadowbox/README.md +++ b/src/shadowbox/README.md @@ -1,6 +1,6 @@ # Outline Server (Shadowbox) -The Outline Server, internal name "Shadowbox," is designed to streamline the setup and sharing of Shadowsocks servers. It includes a user management API and creates Shadowsocks instances when needed. It's managed by the [Outline Manager](https://github.com/OutlineFoundation/outline-apps/) and used as proxy by the [Outline Client](https://github.com/OutlineFoundation/outline-apps/) apps. Shadowbox is also compatible with standard Shadowsocks clients. +The Outline Server, internal name "Shadowbox," is designed to streamline the setup and sharing of Shadowsocks servers. It includes a user management API and creates Shadowsocks instances when needed. It's managed by the [Outline Manager](https://github.com/Jigsaw-Code/outline-apps/) and used as proxy by the [Outline Client](https://github.com/Jigsaw-Code/outline-apps/) apps. Shadowbox is also compatible with standard Shadowsocks clients. ## Installation @@ -9,7 +9,7 @@ The Outline Server, internal name "Shadowbox," is designed to streamline the set 1. **Run the Installation Script** ```sh - sudo bash -c "$(wget -qO- https://raw.githubusercontent.com/OutlineFoundation/outline-apps/master/server_manager/install_scripts/install_server.sh)" + sudo bash -c "$(wget -qO- https://raw.githubusercontent.com/Jigsaw-Code/outline-apps/master/server_manager/install_scripts/install_server.sh)" ``` 1. **Customize (Optional)** @@ -17,7 +17,7 @@ The Outline Server, internal name "Shadowbox," is designed to streamline the set Add flags for hostname, port, etc. Example: ```sh - sudo bash -c "$(wget -qO- https://raw.githubusercontent.com/OutlineFoundation/outline-apps/master/server_manager/install_scripts/install_server.sh)" install_server.sh \ + sudo bash -c "$(wget -qO- https://raw.githubusercontent.com/Jigsaw-Code/outline-apps/master/server_manager/install_scripts/install_server.sh)" install_server.sh \ --hostname=myserver.com \ --keys-port=443 ``` @@ -113,7 +113,7 @@ The Outline Server provides a REST API for access key management. If you know th 1. **Further Options:** - Consult the [OpenAPI spec](./server/api.yml) and [documentation](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/OutlineFoundation/outline-server/master/src/shadowbox/server/api.yml) for more options. + Consult the [OpenAPI spec](./server/api.yml) and [documentation](https://redocly.github.io/redoc/?url=https://raw.githubusercontent.com/Jigsaw-Code/outline-server/master/src/shadowbox/server/api.yml) for more options. ## Testing diff --git a/src/shadowbox/Taskfile.yml b/src/shadowbox/Taskfile.yml index adec26d4..fb72a9b8 100644 --- a/src/shadowbox/Taskfile.yml +++ b/src/shadowbox/Taskfile.yml @@ -23,7 +23,7 @@ tasks: vars: TARGET_OS: '{{.TARGET_OS | default "linux"}}' TARGET_ARCH: '{{.TARGET_ARCH | default "x86_64"}}' - GOARCH: '{{get (dict "x86_64" "amd64" "aarch64" "arm64") .TARGET_ARCH | default .TARGET_ARCH}}' + GOARCH: '{{get (dict "x86_64" "amd64") .TARGET_ARCH | default .TARGET_ARCH}}' TARGET_DIR: '{{.TARGET_DIR | default (joinPath .OUTPUT_BASE .TARGET_OS .TARGET_ARCH)}}' NODE_DIR: '{{joinPath .TARGET_DIR "app"}}' BIN_DIR: '{{joinPath .TARGET_DIR "bin"}}' @@ -76,21 +76,13 @@ tasks: IMAGE_NAME: '{{.IMAGE_NAME | default "localhost/outline/shadowbox"}}' TARGET_ARCH: '{{.TARGET_ARCH | default "x86_64"}}' IMAGE_ROOT: '{{joinPath .OUTPUT_BASE "image_root" .TARGET_ARCH}}' - # Pin the image node:18.20.8-alpine3.21 by hash. - # See image at https://hub.docker.com/_/node/tags?page=1&name=18.20.8-alpine3.21 - # Note: "aarch64" is an alias for "arm64" — Linux ARM64 hosts report "aarch64" via uname -m. + # Newer node images have no valid content trust data. + # Pin the image node:16.18.0-alpine3.16 by hash. + # See image at https://hub.docker.com/_/node/tags?page=1&name=18.18.0-alpine3.18 NODE_IMAGE: '{{get (dict - "x86_64" "node@sha256:929b04d7c782f04f615cf785488fed452b6569f87c73ff666ad553a7554f0006" - "arm64" "node@sha256:c2281c62c4aadf92ea71a6c05e6c8e640634b6a99dc52a6e54575f9cb298a037" - "aarch64" "node@sha256:c2281c62c4aadf92ea71a6c05e6c8e640634b6a99dc52a6e54575f9cb298a037" - ) .TARGET_ARCH - }}' - DOCKER_PLATFORM: '{{get - (dict - "x86_64" "linux/amd64" - "arm64" "linux/arm64" - "aarch64" "linux/arm64" + "x86_64" "node@sha256:a0b787b0d53feacfa6d606fb555e0dbfebab30573277f1fe25148b05b66fa097" + "arm64" "node@sha256:b4b7a1dd149c65ee6025956ac065a843b4409a62068bd2b0cbafbb30ca2fab3b" ) .TARGET_ARCH }}' env: @@ -111,7 +103,6 @@ tasks: # Build image with given root - | "${DOCKER:-docker}" build --force-rm \ - --platform '{{.DOCKER_PLATFORM}}' \ --build-arg NODE_IMAGE='{{.NODE_IMAGE}}' \ --build-arg VERSION='{{.VERSION}}' \ -f '{{joinPath .TASKFILE_DIR "docker" "Dockerfile"}}' \ diff --git a/src/shadowbox/docker/Dockerfile b/src/shadowbox/docker/Dockerfile index 671c421a..c9d27db7 100644 --- a/src/shadowbox/docker/Dockerfile +++ b/src/shadowbox/docker/Dockerfile @@ -18,17 +18,16 @@ FROM ${NODE_IMAGE} ARG VERSION # Save metadata on the software versions we are using. -LABEL shadowbox.node_version=18.20.8 +LABEL shadowbox.node_version=16.18.0 LABEL shadowbox.github.release=${VERSION} # The user management service doesn't quit with SIGTERM. STOPSIGNAL SIGKILL -# Upgrade installed Alpine packages to pick up security fixes (musl-utils, busybox, ssl_client, etc.). # We use curl to detect the server's public IP. We need to use the --date option in `date` to # safely grab the ip-to-country database. -RUN apk upgrade --no-cache && apk add --no-cache --upgrade coreutils curl +RUN apk add --no-cache --upgrade coreutils curl COPY . / diff --git a/src/shadowbox/integration_test/client/Dockerfile b/src/shadowbox/integration_test/client/Dockerfile index f2915cdf..31a51bb6 100644 --- a/src/shadowbox/integration_test/client/Dockerfile +++ b/src/shadowbox/integration_test/client/Dockerfile @@ -14,7 +14,7 @@ # Alpine 3.19 curl is using the c-ares resolver instead of the system resolver, # which caused DNS issues. Upgrade once the Alpine image includes the fix. See -# https://github.com/OutlineFoundation/outline-server/pull/1566. +# https://github.com/Jigsaw-Code/outline-server/pull/1566. FROM docker.io/golang:1-alpine3.18 # curl for fetching pages using the local proxy diff --git a/src/shadowbox/package.json b/src/shadowbox/package.json index 62e4ddd4..89a2ef5d 100644 --- a/src/shadowbox/package.json +++ b/src/shadowbox/package.json @@ -11,7 +11,7 @@ "dependencies": { "ip-regex": "^4.1.0", "js-yaml": "^3.12.0", - "outline-shadowsocksconfig": "github:OutlineFoundation/shadowsocksconfig#v0.2.0", + "outline-shadowsocksconfig": "github:Jigsaw-Code/outline-shadowsocksconfig#v0.2.0", "prom-client": "^11.1.3", "randomstring": "^1.1.5", "restify": "^11.1.0", diff --git a/src/shadowbox/server/main.ts b/src/shadowbox/server/main.ts index 5d1be776..8f52c18d 100644 --- a/src/shadowbox/server/main.ts +++ b/src/shadowbox/server/main.ts @@ -48,7 +48,6 @@ const MMDB_LOCATION_ASN = '/var/lib/libmaxminddb/ip-asn.mmdb'; async function exportPrometheusMetrics(registry: prometheus.Registry, port): Promise { return new Promise((resolve, _) => { const server = http.createServer((_, res) => { - res.setHeader('Content-Type', registry.contentType); res.write(registry.metrics()); res.end(); }); @@ -123,7 +122,7 @@ async function main() { const prometheusPort = await portProvider.reserveFirstFreePort(9090); // Use 127.0.0.1 instead of localhost for Prometheus because it's resolving incorrectly for some users. - // See https://github.com/OutlineFoundation/outline-server/issues/341 + // See https://github.com/Jigsaw-Code/outline-server/issues/341 const prometheusLocation = `127.0.0.1:${prometheusPort}`; const nodeMetricsPort = await portProvider.reserveFirstFreePort(prometheusPort + 1); diff --git a/src/shadowbox/server/manager_metrics.ts b/src/shadowbox/server/manager_metrics.ts index 422f1162..3969ac39 100644 --- a/src/shadowbox/server/manager_metrics.ts +++ b/src/shadowbox/server/manager_metrics.ts @@ -16,7 +16,6 @@ import { PrometheusClient, PrometheusMetric, PrometheusValue, - QueryResultData, } from '../infrastructure/prometheus_scraper'; import {DataUsageByUser, DataUsageTimeframe} from '../model/metrics'; @@ -112,9 +111,8 @@ export class PrometheusManagerMetrics implements ManagerMetrics { Math.ceil(now / PROMETHEUS_RANGE_QUERY_STEP_SECONDS) * PROMETHEUS_RANGE_QUERY_STEP_SECONDS; const start = end - timeframe.seconds; - this.prunePrometheusCache(); - const [ + bandwidth, bandwidthRange, dataTransferredByLocation, tunnelTimeByLocation, @@ -123,31 +121,34 @@ export class PrometheusManagerMetrics implements ManagerMetrics { dataTransferredByAccessKeyRange, tunnelTimeByAccessKeyRange, ] = await Promise.all([ - this.cachedPrometheusClient.queryRange( + this.prometheusClient.query( + `sum(rate(shadowsocks_data_bytes_per_location{dir=~"ct"}[${PROMETHEUS_RANGE_QUERY_STEP_SECONDS}s]))` + ), + this.prometheusClient.queryRange( `sum(rate(shadowsocks_data_bytes_per_location{dir=~"ct"}[${PROMETHEUS_RANGE_QUERY_STEP_SECONDS}s]))`, start, end, `${PROMETHEUS_RANGE_QUERY_STEP_SECONDS}s` ), - this.cachedPrometheusClient.query( + this.prometheusClient.query( `sum(increase(shadowsocks_data_bytes_per_location{dir=~"ct"}[${timeframe.seconds}s])) by (location, asn, asorg)` ), - this.cachedPrometheusClient.query( + this.prometheusClient.query( `sum(increase(shadowsocks_tunnel_time_seconds_per_location[${timeframe.seconds}s])) by (location, asn, asorg)` ), - this.cachedPrometheusClient.query( + this.prometheusClient.query( `sum(increase(shadowsocks_data_bytes{dir=~"ct"}[${timeframe.seconds}s])) by (access_key)` ), - this.cachedPrometheusClient.query( + this.prometheusClient.query( `sum(increase(shadowsocks_tunnel_time_seconds[${timeframe.seconds}s])) by (access_key)` ), - this.cachedPrometheusClient.queryRange( + this.prometheusClient.queryRange( `sum(increase(shadowsocks_data_bytes{dir=~"ct"}[${PROMETHEUS_RANGE_QUERY_STEP_SECONDS}s])) by (access_key)`, start, end, `${PROMETHEUS_RANGE_QUERY_STEP_SECONDS}s` ), - this.cachedPrometheusClient.queryRange( + this.prometheusClient.queryRange( `sum(increase(shadowsocks_tunnel_time_seconds[${PROMETHEUS_RANGE_QUERY_STEP_SECONDS}s])) by (access_key)`, start, end, @@ -164,15 +165,13 @@ export class PrometheusManagerMetrics implements ManagerMetrics { }, locations: [], }; - - const bandwidthRangeValues = bandwidthRange.result[0].values ?? []; - const currentBandwidth = bandwidthRangeValues[bandwidthRangeValues.length - 1]; - - if (currentBandwidth) { - serverMetrics.bandwidth.current.data.bytes = parseFloat(currentBandwidth[1]); - serverMetrics.bandwidth.current.timestamp = currentBandwidth[0]; + for (const result of bandwidth.result) { + if (result.value) { + serverMetrics.bandwidth.current.data.bytes = parseFloat(result.value[1]); + serverMetrics.bandwidth.current.timestamp = result.value[0]; + } + break; // There should only be one result. } - for (const result of bandwidthRange.result) { const peakDataTransferred = findPeak(result.values ?? []); if (peakDataTransferred !== null) { @@ -232,41 +231,6 @@ export class PrometheusManagerMetrics implements ManagerMetrics { accessKeys: Array.from(accessKeyMap.values()), }; } - - private prometheusCache = new Map(); - - private get cachedPrometheusClient() { - return new Proxy(this.prometheusClient, { - get: (target, prop) => { - if (typeof target[prop] !== 'function') { - return target[prop]; - } - - return async (query, ...args) => { - const cacheId = `${String(prop)}: ${query} (args: ${args.join(', ')}))`; - - if (this.prometheusCache.has(cacheId)) { - return this.prometheusCache.get(cacheId).result; - } - - const result = await (target[prop] as Function)(query, ...args); - - this.prometheusCache.set(cacheId, {timestamp: Date.now(), result}); - - return result; - }; - }, - }); - } - - private prunePrometheusCache() { - const now = Date.now(); - for (const [key, value] of this.prometheusCache) { - if (now - value.timestamp > PROMETHEUS_RANGE_QUERY_STEP_SECONDS * 1000) { - this.prometheusCache.delete(key); - } - } - } } function getServerMetricsLocationEntry( diff --git a/src/shadowbox/server/outline_shadowsocks_server.ts b/src/shadowbox/server/outline_shadowsocks_server.ts index e7c40370..ab60e451 100644 --- a/src/shadowbox/server/outline_shadowsocks_server.ts +++ b/src/shadowbox/server/outline_shadowsocks_server.ts @@ -21,12 +21,26 @@ import * as file from '../infrastructure/file'; import * as logging from '../infrastructure/logging'; import {ShadowsocksAccessKey, ShadowsocksServer} from '../model/shadowsocks_server'; +/** Represents an outline-ss-server configuration with multiple services. */ +export interface OutlineSSServerConfig { + services: { + listeners: { + type: string; + address: string; + }[]; + keys: { + id: string; + cipher: string; + secret: string; + }[]; + }[]; +} + // Runs outline-ss-server. export class OutlineShadowsocksServer implements ShadowsocksServer { private ssProcess: child_process.ChildProcess; private ipCountryFilename?: string; private ipAsnFilename?: string; - private isAsnMetricsEnabled = false; private isReplayProtectionEnabled = false; /** @@ -81,22 +95,42 @@ export class OutlineShadowsocksServer implements ShadowsocksServer { private writeConfigFile(keys: ShadowsocksAccessKey[]): Promise { return new Promise((resolve, reject) => { - const keysJson = {keys: [] as ShadowsocksAccessKey[]}; - for (const key of keys) { + const validKeys: ShadowsocksAccessKey[] = keys.filter((key) => { if (!isAeadCipher(key.cipher)) { logging.error( `Cipher ${key.cipher} for access key ${key.id} is not supported: use an AEAD cipher instead.` ); - continue; + return false; } + return true; + }); - keysJson.keys.push(key); + const config: OutlineSSServerConfig = {services: []}; + const keysByPort: Record = {}; + for (const key of validKeys) { + (keysByPort[key.port] ??= []).push(key); + } + for (const port in keysByPort) { + const service = { + listeners: [ + // NOTE: We explicitly specify the address string with only the port + // number. This will result in an address that listens on all + // available network interfaces (both IPv4 and IPv6). + {type: 'tcp', address: `:${port}`}, + {type: 'udp', address: `:${port}`}, + ], + keys: keysByPort[port].map((key) => ({ + id: key.id, + cipher: key.cipher, + secret: key.secret, + })), + }; + config.services.push(service); } mkdirp.sync(path.dirname(this.configFilename)); - try { - file.atomicWriteFileSync(this.configFilename, jsyaml.safeDump(keysJson, {sortKeys: true})); + file.atomicWriteFileSync(this.configFilename, jsyaml.safeDump(config, {sortKeys: true})); resolve(); } catch (error) { reject(error); diff --git a/third_party/Taskfile.yml b/third_party/Taskfile.yml index bdcc6807..a2749545 100644 --- a/third_party/Taskfile.yml +++ b/third_party/Taskfile.yml @@ -11,17 +11,17 @@ tasks: prometheus:download-*-*: desc: Download and extract prometheus binary vars: - VERSION: '2.53.4' + VERSION: '2.37.1' GOOS: '{{index .MATCH 0}}' GOARCH: '{{index .MATCH 1}}' TEMPFILE: {sh: mktemp} SHA256: '{{printf "%v/%v" .GOOS .GOARCH | get (dict - "linux/amd64" "b8b497c4610d1b93208252b60c8f20f6b2e78596ae8df43397a2e805aa53d475" - "linux/arm64" "ec7236ecea7154d0bfe142921708b1ae7b5e921e100e0ee85ab92b7c444357e0" - "darwin/amd64" "10066a1aa21c4ddb8d5e61c31b52e898d8ac42c7e99fd757e2fc4b6c20b8075f" - "darwin/arm64" "cb3e638d8e9b4b27a6aa1f45a4faa3741b548aac67d4649aea7a2fad3c09f0a1" - ) + "linux/amd64" "753f66437597cf52ada98c2f459aa8c03745475c249c9f2b40ac7b3919131ba6" + "linux/arm64" "b59a66fb5c7ec5acf6bf426793528a5789a1478a0dad8c64edc2843caf31b1b8" + "darwin/amd64" "e03a43d98955ac3500f57353ea74b5df829074205f195ea6b3b88f55c4575c79" + "darwin/arm64" "eb8a174c82a0fb6c84e81d9a73214318fb4a605115ad61505d7883d02e5a6f52" + ) }}' TARGET_DIR: '{{joinPath .OUTPUT_BASE "prometheus" .GOOS .GOARCH}}' TARGET: '{{joinPath .TARGET_DIR "prometheus"}}' diff --git a/third_party/prometheus/METADATA b/third_party/prometheus/METADATA index 4712de71..6b603f4f 100644 --- a/third_party/prometheus/METADATA +++ b/third_party/prometheus/METADATA @@ -10,21 +10,13 @@ third_party { } url { type: ARCHIVE - value: "https://github.com/prometheus/prometheus/releases/download/v2.53.4/prometheus-2.53.4.linux-amd64.tar.gz" + value: "https://github.com/prometheus/prometheus/releases/download/2.37.1/prometheus-2.37.1.linux-amd64.tar.gz" } url { type: ARCHIVE - value: "https://github.com/prometheus/prometheus/releases/download/v2.53.4/prometheus-2.53.4.linux-arm64.tar.gz" + value: "https://github.com/prometheus/prometheus/releases/download/2.37.1/prometheus-2.37.1.darwin-amd64.tar.gz" } - url { - type: ARCHIVE - value: "https://github.com/prometheus/prometheus/releases/download/v2.53.4/prometheus-2.53.4.darwin-amd64.tar.gz" - } - url { - type: ARCHIVE - value: "https://github.com/prometheus/prometheus/releases/download/v2.53.4/prometheus-2.53.4.darwin-arm64.tar.gz" - } - version: "2.53.4" - last_upgrade_date { year: 2025 month: 3 day: 20 } + version: "2.37.1" + last_upgrade_date { year: 2022 month: 10 day: 24 } license_type: PERMISSIVE }