mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Merge branch 'main' into rama-integration-beta
This commit is contained in:
commit
9f0e1aeab0
9 changed files with 232 additions and 10 deletions
37
.github/workflows/build-and-release.yml
vendored
37
.github/workflows/build-and-release.yml
vendored
|
|
@ -60,12 +60,43 @@ jobs:
|
||||||
mv binaries/safe-chain-win-x64/safe-chain.exe release-artifacts/safe-chain-win-x64.exe
|
mv binaries/safe-chain-win-x64/safe-chain.exe release-artifacts/safe-chain-win-x64.exe
|
||||||
mv binaries/safe-chain-win-arm64/safe-chain.exe release-artifacts/safe-chain-win-arm64.exe
|
mv binaries/safe-chain-win-arm64/safe-chain.exe release-artifacts/safe-chain-win-arm64.exe
|
||||||
|
|
||||||
- name: Move install scripts and hard-code version
|
- name: Move install scripts and hard-code version and checksums
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ needs.set-version.outputs.version }}
|
VERSION: ${{ needs.set-version.outputs.version }}
|
||||||
run: |
|
run: |
|
||||||
sed "s/\$(fetch_latest_version)/${VERSION}/" install-scripts/install-safe-chain.sh > release-artifacts/install-safe-chain.sh
|
SHA_MACOS_X64=$(sha256sum release-artifacts/safe-chain-macos-x64 | awk '{print $1}')
|
||||||
sed "s/\$Version = Get-LatestVersion/\$Version = \"${VERSION}\"/" install-scripts/install-safe-chain.ps1 > release-artifacts/install-safe-chain.ps1
|
SHA_MACOS_ARM64=$(sha256sum release-artifacts/safe-chain-macos-arm64 | awk '{print $1}')
|
||||||
|
SHA_LINUX_X64=$(sha256sum release-artifacts/safe-chain-linux-x64 | awk '{print $1}')
|
||||||
|
SHA_LINUX_ARM64=$(sha256sum release-artifacts/safe-chain-linux-arm64 | awk '{print $1}')
|
||||||
|
SHA_LINUXSTATIC_X64=$(sha256sum release-artifacts/safe-chain-linuxstatic-x64 | awk '{print $1}')
|
||||||
|
SHA_LINUXSTATIC_ARM64=$(sha256sum release-artifacts/safe-chain-linuxstatic-arm64 | awk '{print $1}')
|
||||||
|
SHA_WIN_X64=$(sha256sum release-artifacts/safe-chain-win-x64.exe | awk '{print $1}')
|
||||||
|
SHA_WIN_ARM64=$(sha256sum release-artifacts/safe-chain-win-arm64.exe | awk '{print $1}')
|
||||||
|
|
||||||
|
sed \
|
||||||
|
-e "s/\$(fetch_latest_version)/${VERSION}/" \
|
||||||
|
-e "s|^SHA256_MACOS_X64=\"\"|SHA256_MACOS_X64=\"${SHA_MACOS_X64}\"|" \
|
||||||
|
-e "s|^SHA256_MACOS_ARM64=\"\"|SHA256_MACOS_ARM64=\"${SHA_MACOS_ARM64}\"|" \
|
||||||
|
-e "s|^SHA256_LINUX_X64=\"\"|SHA256_LINUX_X64=\"${SHA_LINUX_X64}\"|" \
|
||||||
|
-e "s|^SHA256_LINUX_ARM64=\"\"|SHA256_LINUX_ARM64=\"${SHA_LINUX_ARM64}\"|" \
|
||||||
|
-e "s|^SHA256_LINUXSTATIC_X64=\"\"|SHA256_LINUXSTATIC_X64=\"${SHA_LINUXSTATIC_X64}\"|" \
|
||||||
|
-e "s|^SHA256_LINUXSTATIC_ARM64=\"\"|SHA256_LINUXSTATIC_ARM64=\"${SHA_LINUXSTATIC_ARM64}\"|" \
|
||||||
|
-e "s|^SHA256_WIN_X64=\"\"|SHA256_WIN_X64=\"${SHA_WIN_X64}\"|" \
|
||||||
|
-e "s|^SHA256_WIN_ARM64=\"\"|SHA256_WIN_ARM64=\"${SHA_WIN_ARM64}\"|" \
|
||||||
|
install-scripts/install-safe-chain.sh > release-artifacts/install-safe-chain.sh
|
||||||
|
|
||||||
|
sed \
|
||||||
|
-e "s/\$Version = Get-LatestVersion/\$Version = \"${VERSION}\"/" \
|
||||||
|
-e "s|^\$SHA256_MACOS_X64 = \"\"|\$SHA256_MACOS_X64 = \"${SHA_MACOS_X64}\"|" \
|
||||||
|
-e "s|^\$SHA256_MACOS_ARM64 = \"\"|\$SHA256_MACOS_ARM64 = \"${SHA_MACOS_ARM64}\"|" \
|
||||||
|
-e "s|^\$SHA256_LINUX_X64 = \"\"|\$SHA256_LINUX_X64 = \"${SHA_LINUX_X64}\"|" \
|
||||||
|
-e "s|^\$SHA256_LINUX_ARM64 = \"\"|\$SHA256_LINUX_ARM64 = \"${SHA_LINUX_ARM64}\"|" \
|
||||||
|
-e "s|^\$SHA256_LINUXSTATIC_X64 = \"\"|\$SHA256_LINUXSTATIC_X64 = \"${SHA_LINUXSTATIC_X64}\"|" \
|
||||||
|
-e "s|^\$SHA256_LINUXSTATIC_ARM64 = \"\"|\$SHA256_LINUXSTATIC_ARM64 = \"${SHA_LINUXSTATIC_ARM64}\"|" \
|
||||||
|
-e "s|^\$SHA256_WIN_X64 = \"\"|\$SHA256_WIN_X64 = \"${SHA_WIN_X64}\"|" \
|
||||||
|
-e "s|^\$SHA256_WIN_ARM64 = \"\"|\$SHA256_WIN_ARM64 = \"${SHA_WIN_ARM64}\"|" \
|
||||||
|
install-scripts/install-safe-chain.ps1 > release-artifacts/install-safe-chain.ps1
|
||||||
|
|
||||||
cp install-scripts/uninstall-safe-chain.sh release-artifacts/uninstall-safe-chain.sh
|
cp install-scripts/uninstall-safe-chain.sh release-artifacts/uninstall-safe-chain.sh
|
||||||
cp install-scripts/uninstall-safe-chain.ps1 release-artifacts/uninstall-safe-chain.ps1
|
cp install-scripts/uninstall-safe-chain.ps1 release-artifacts/uninstall-safe-chain.ps1
|
||||||
cp install-scripts/install-endpoint-mac.sh release-artifacts/install-endpoint-mac.sh
|
cp install-scripts/install-endpoint-mac.sh release-artifacts/install-endpoint-mac.sh
|
||||||
|
|
|
||||||
|
|
@ -290,6 +290,12 @@ You can set custom registries through environment variable or config file. Both
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## PYPI Configuration File
|
||||||
|
|
||||||
|
If you rely on a `pip.conf` file for pip configuration you must point pip at it explicitly via the `PIP_CONFIG_FILE` environment variable so Safe Chain can merge it.
|
||||||
|
|
||||||
|
Safe Chain runs pip behind its MITM proxy and writes a temporary pip configuration file to inject its certificate and proxy settings. When `PIP_CONFIG_FILE` is set, Safe Chain merges its settings into a copy of your file (your original file is never modified) so your `index-url`, credentials, and other options are preserved. When `PIP_CONFIG_FILE` is not set, pip's user-level config (e.g. `~/.config/pip/pip.conf`) might be overridden by Safe Chain's temporary file and your settings will not be picked up.
|
||||||
|
|
||||||
## Malware List Base URL
|
## Malware List Base URL
|
||||||
|
|
||||||
Configure Safe Chain to fetch malware databases and new packages lists from a custom mirror URL. This allows you to host your own copy of the Aikido malware database.
|
Configure Safe Chain to fetch malware databases and new packages lists from a custom mirror URL. This allows you to host your own copy of the Aikido malware database.
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@
|
||||||
set -e # Exit on error
|
set -e # Exit on error
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
INSTALL_URL="https://github.com/AikidoSec/safechain-internals/releases/download/v1.2.23/EndpointProtection.pkg"
|
INSTALL_URL="https://github.com/AikidoSec/safechain-internals/releases/download/v1.3.4/EndpointProtection.pkg"
|
||||||
DOWNLOAD_SHA256="9af1e0f72e53516c888ade1753ed03f087c1def89244eb0afb60e1f11e8e87e2"
|
DOWNLOAD_SHA256="f2ea55588d42e4aa17545ad787f46dd36001009e2ddb9655c497b1a36edf3581"
|
||||||
TOKEN_FILE="/tmp/aikido_endpoint_token.txt"
|
TOKEN_FILE="/tmp/aikido_endpoint_token.txt"
|
||||||
|
|
||||||
# Colors for output
|
# Colors for output
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,8 @@ param(
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
$InstallUrl = "https://github.com/AikidoSec/safechain-internals/releases/download/v1.2.23/EndpointProtection.msi"
|
$InstallUrl = "https://github.com/AikidoSec/safechain-internals/releases/download/v1.3.4/EndpointProtection.msi"
|
||||||
$DownloadSha256 = "3327d35db6654d12dbd7c5ccec0645edb0277f71dcd993ba9733e266bbd235f8"
|
$DownloadSha256 = "0699379716a9a8b1531befa538befb237252af9f7fd780b33f4dce73588c6f83"
|
||||||
|
|
||||||
# Ensure TLS 1.2 is enabled for downloads
|
# Ensure TLS 1.2 is enabled for downloads
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,20 @@ $SafeChainBase = $installDirValidation.Normalized
|
||||||
$InstallDir = Join-Path $SafeChainBase "bin"
|
$InstallDir = Join-Path $SafeChainBase "bin"
|
||||||
$RepoUrl = "https://github.com/AikidoSec/safe-chain"
|
$RepoUrl = "https://github.com/AikidoSec/safe-chain"
|
||||||
|
|
||||||
|
# SHA256 checksums for release binaries.
|
||||||
|
# Empty in source; populated by the release pipeline.
|
||||||
|
# When empty (running from main), checksum verification is skipped.
|
||||||
|
# Non-Windows hashes are unused today (PS script is Windows-only) but baked in
|
||||||
|
# for future cross-platform support.
|
||||||
|
$SHA256_MACOS_X64 = ""
|
||||||
|
$SHA256_MACOS_ARM64 = ""
|
||||||
|
$SHA256_LINUX_X64 = ""
|
||||||
|
$SHA256_LINUX_ARM64 = ""
|
||||||
|
$SHA256_LINUXSTATIC_X64 = ""
|
||||||
|
$SHA256_LINUXSTATIC_ARM64 = ""
|
||||||
|
$SHA256_WIN_X64 = ""
|
||||||
|
$SHA256_WIN_ARM64 = ""
|
||||||
|
|
||||||
# Ensure TLS 1.2 is enabled for downloads
|
# Ensure TLS 1.2 is enabled for downloads
|
||||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
|
||||||
|
|
@ -166,6 +180,38 @@ function Get-BinaryName {
|
||||||
return "safe-chain-win-$Architecture.exe"
|
return "safe-chain-win-$Architecture.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Returns the expected SHA256 for the given OS+arch, or empty if not baked in.
|
||||||
|
function Get-ExpectedSha256 {
|
||||||
|
param([string]$Os, [string]$Architecture)
|
||||||
|
switch ("$Os-$Architecture") {
|
||||||
|
"macos-x64" { return $SHA256_MACOS_X64 }
|
||||||
|
"macos-arm64" { return $SHA256_MACOS_ARM64 }
|
||||||
|
"linux-x64" { return $SHA256_LINUX_X64 }
|
||||||
|
"linux-arm64" { return $SHA256_LINUX_ARM64 }
|
||||||
|
"linuxstatic-x64" { return $SHA256_LINUXSTATIC_X64 }
|
||||||
|
"linuxstatic-arm64" { return $SHA256_LINUXSTATIC_ARM64 }
|
||||||
|
"win-x64" { return $SHA256_WIN_X64 }
|
||||||
|
"win-arm64" { return $SHA256_WIN_ARM64 }
|
||||||
|
default { return "" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Test-Checksum {
|
||||||
|
param([string]$File, [string]$Expected)
|
||||||
|
|
||||||
|
if ([string]::IsNullOrWhiteSpace($Expected)) { return }
|
||||||
|
|
||||||
|
$actual = (Get-FileHash -Path $File -Algorithm SHA256).Hash.ToLowerInvariant()
|
||||||
|
$expectedLower = $Expected.ToLowerInvariant()
|
||||||
|
|
||||||
|
if ($actual -ne $expectedLower) {
|
||||||
|
Remove-Item -Path $File -Force -ErrorAction SilentlyContinue
|
||||||
|
Write-Error-Custom "Checksum verification failed. Expected: $expectedLower, Got: $actual"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Info "Checksum verified."
|
||||||
|
}
|
||||||
|
|
||||||
# Runs safe-chain setup or setup-ci after the binary is installed.
|
# Runs safe-chain setup or setup-ci after the binary is installed.
|
||||||
# Temporarily appends the install directory to PATH and downgrades setup failures to warnings.
|
# Temporarily appends the install directory to PATH and downgrades setup failures to warnings.
|
||||||
function Invoke-SafeChainSetup {
|
function Invoke-SafeChainSetup {
|
||||||
|
|
@ -305,6 +351,9 @@ function Install-SafeChain {
|
||||||
Write-Error-Custom "Failed to download from $downloadUrl : $_"
|
Write-Error-Custom "Failed to download from $downloadUrl : $_"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$expectedSha = Get-ExpectedSha256 -Os "win" -Architecture $arch
|
||||||
|
Test-Checksum -File $tempFile -Expected $expectedSha
|
||||||
|
|
||||||
# Rename to final location
|
# Rename to final location
|
||||||
$finalFile = Join-Path $InstallDir "safe-chain.exe"
|
$finalFile = Join-Path $InstallDir "safe-chain.exe"
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,18 @@ SAFE_CHAIN_BASE="${HOME}/.safe-chain"
|
||||||
INSTALL_DIR="${SAFE_CHAIN_BASE}/bin"
|
INSTALL_DIR="${SAFE_CHAIN_BASE}/bin"
|
||||||
REPO_URL="https://github.com/AikidoSec/safe-chain"
|
REPO_URL="https://github.com/AikidoSec/safe-chain"
|
||||||
|
|
||||||
|
# SHA256 checksums for release binaries.
|
||||||
|
# Empty in source; populated by the release pipeline via sed.
|
||||||
|
# When empty (running from main), checksum verification is skipped.
|
||||||
|
SHA256_MACOS_X64=""
|
||||||
|
SHA256_MACOS_ARM64=""
|
||||||
|
SHA256_LINUX_X64=""
|
||||||
|
SHA256_LINUX_ARM64=""
|
||||||
|
SHA256_LINUXSTATIC_X64=""
|
||||||
|
SHA256_LINUXSTATIC_ARM64=""
|
||||||
|
SHA256_WIN_X64=""
|
||||||
|
SHA256_WIN_ARM64=""
|
||||||
|
|
||||||
# Colors for output
|
# Colors for output
|
||||||
RED='\033[0;31m'
|
RED='\033[0;31m'
|
||||||
GREEN='\033[0;32m'
|
GREEN='\033[0;32m'
|
||||||
|
|
@ -156,6 +168,57 @@ fetch_latest_version() {
|
||||||
echo "$latest_version"
|
echo "$latest_version"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Returns the expected SHA256 for the detected platform, or empty if the
|
||||||
|
# release pipeline has not baked one in (i.e. running the source from main).
|
||||||
|
get_expected_sha256() {
|
||||||
|
os="$1"; arch="$2"
|
||||||
|
case "${os}-${arch}" in
|
||||||
|
macos-x64) echo "$SHA256_MACOS_X64" ;;
|
||||||
|
macos-arm64) echo "$SHA256_MACOS_ARM64" ;;
|
||||||
|
linux-x64) echo "$SHA256_LINUX_X64" ;;
|
||||||
|
linux-arm64) echo "$SHA256_LINUX_ARM64" ;;
|
||||||
|
linuxstatic-x64) echo "$SHA256_LINUXSTATIC_X64" ;;
|
||||||
|
linuxstatic-arm64) echo "$SHA256_LINUXSTATIC_ARM64" ;;
|
||||||
|
win-x64) echo "$SHA256_WIN_X64" ;;
|
||||||
|
win-arm64) echo "$SHA256_WIN_ARM64" ;;
|
||||||
|
*) echo "" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
compute_sha256() {
|
||||||
|
file="$1"
|
||||||
|
if command_exists sha256sum; then
|
||||||
|
sha256sum "$file" | awk '{print $1}'
|
||||||
|
elif command_exists shasum; then
|
||||||
|
shasum -a 256 "$file" | awk '{print $1}'
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Verifies the downloaded binary against the expected hash baked in by the release pipeline.
|
||||||
|
# No-op when no expected hash is set (running the script from main).
|
||||||
|
verify_checksum() {
|
||||||
|
file="$1"; expected="$2"
|
||||||
|
|
||||||
|
if [ -z "$expected" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
actual=$(compute_sha256 "$file")
|
||||||
|
if [ -z "$actual" ]; then
|
||||||
|
rm -f "$file"
|
||||||
|
error "Cannot verify checksum: neither sha256sum nor shasum is available. Install one and re-run."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$actual" != "$expected" ]; then
|
||||||
|
rm -f "$file"
|
||||||
|
error "Checksum verification failed. Expected: $expected, Got: $actual"
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Checksum verified."
|
||||||
|
}
|
||||||
|
|
||||||
# Download file
|
# Download file
|
||||||
download() {
|
download() {
|
||||||
url="$1"
|
url="$1"
|
||||||
|
|
@ -432,6 +495,9 @@ main() {
|
||||||
info "Downloading from: $DOWNLOAD_URL"
|
info "Downloading from: $DOWNLOAD_URL"
|
||||||
download "$DOWNLOAD_URL" "$TEMP_FILE"
|
download "$DOWNLOAD_URL" "$TEMP_FILE"
|
||||||
|
|
||||||
|
EXPECTED_SHA256=$(get_expected_sha256 "$OS" "$ARCH")
|
||||||
|
verify_checksum "$TEMP_FILE" "$EXPECTED_SHA256"
|
||||||
|
|
||||||
# Rename and make executable
|
# Rename and make executable
|
||||||
FINAL_FILE=$(get_final_binary_path "$OS")
|
FINAL_FILE=$(get_final_binary_path "$OS")
|
||||||
mv "$TEMP_FILE" "$FINAL_FILE" || error "Failed to move binary to $FINAL_FILE"
|
mv "$TEMP_FILE" "$FINAL_FILE" || error "Failed to move binary to $FINAL_FILE"
|
||||||
|
|
|
||||||
|
|
@ -48,8 +48,11 @@ export function createBuiltInProxyServer() {
|
||||||
*/
|
*/
|
||||||
function startServer(server) {
|
function startServer(server) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// Passing port 0 makes the OS assign an available port
|
// Bind to loopback only. Without an explicit host, Node listens on every
|
||||||
server.listen(0, () => {
|
// interface, turning the proxy into an unauthenticated forward proxy that
|
||||||
|
// anyone reachable on the network can use to hit the victim's localhost,
|
||||||
|
// intranet, or cloud metadata endpoints. Port 0 lets the OS pick a port.
|
||||||
|
server.listen(0, "127.0.0.1", () => {
|
||||||
const address = server.address();
|
const address = server.address();
|
||||||
if (address && typeof address === "object") {
|
if (address && typeof address === "object") {
|
||||||
state.port = address.port;
|
state.port = address.port;
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ export function getProxySettings() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const proxyUrl = `http://localhost:${server.getServerPort()}`;
|
const proxyUrl = `http://127.0.0.1:${server.getServerPort()}`;
|
||||||
const caCert = server.getCaCert();
|
const caCert = server.getCaCert();
|
||||||
const caCertBundlePath = getCombinedCaBundlePath(caCert);
|
const caCertBundlePath = getCombinedCaBundlePath(caCert);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,67 @@
|
||||||
|
import { before, after, describe, it } from "node:test";
|
||||||
|
import assert from "node:assert";
|
||||||
|
import net from "node:net";
|
||||||
|
import os from "node:os";
|
||||||
|
import {
|
||||||
|
createSafeChainProxy,
|
||||||
|
mergeSafeChainProxyEnvironmentVariables,
|
||||||
|
} from "./registryProxy.js";
|
||||||
|
|
||||||
|
describe("registryProxy loopback binding", () => {
|
||||||
|
let proxy, proxyPort;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
proxy = createSafeChainProxy();
|
||||||
|
await proxy.startServer();
|
||||||
|
const envVars = mergeSafeChainProxyEnvironmentVariables([]);
|
||||||
|
proxyPort = parseInt(new URL(envVars.HTTPS_PROXY).port, 10);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async () => {
|
||||||
|
await proxy.stopServer();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("advertises a loopback HTTPS_PROXY URL", () => {
|
||||||
|
const envVars = mergeSafeChainProxyEnvironmentVariables([]);
|
||||||
|
const hostname = new URL(envVars.HTTPS_PROXY).hostname;
|
||||||
|
assert.ok(
|
||||||
|
hostname === "127.0.0.1" || hostname === "::1" || hostname === "localhost",
|
||||||
|
`expected loopback hostname, got ${hostname}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("refuses connections on non-loopback interfaces", async () => {
|
||||||
|
const externalAddrs = Object.values(os.networkInterfaces())
|
||||||
|
.flat()
|
||||||
|
.filter((iface) => iface && iface.family === "IPv4" && !iface.internal)
|
||||||
|
.map((iface) => iface.address);
|
||||||
|
|
||||||
|
if (externalAddrs.length === 0) {
|
||||||
|
// No non-loopback interface available (e.g. locked-down CI) - skip.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const addr of externalAddrs) {
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
const sock = net.createConnection({ host: addr, port: proxyPort });
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
sock.destroy();
|
||||||
|
resolve(); // Filtered / dropped is also fine - we just don't want success.
|
||||||
|
}, 500);
|
||||||
|
sock.once("connect", () => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
sock.destroy();
|
||||||
|
reject(
|
||||||
|
new Error(
|
||||||
|
`proxy accepted a connection on non-loopback ${addr}:${proxyPort}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
sock.once("error", () => {
|
||||||
|
clearTimeout(timer);
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue