diff --git a/.changeset/slimy-mayflies-fetch.md b/.changeset/slimy-mayflies-fetch.md new file mode 100644 index 0000000..35a06ca --- /dev/null +++ b/.changeset/slimy-mayflies-fetch.md @@ -0,0 +1,5 @@ +--- +"nsite-ts": minor +--- + +Add support for ALL_PROXY env variable diff --git a/.vscode/launch.json b/.vscode/launch.json index a9b8b50..9bb2bc8 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,6 +14,21 @@ "env": { "DEBUG": "nsite,nsite:*" } + }, + { + "name": "dev-proxy", + "type": "node", + "request": "launch", + "args": ["./src/index.ts"], + "runtimeArgs": ["--loader", "@swc-node/register/esm"], + "cwd": "${workspaceRoot}", + "protocol": "inspector", + "internalConsoleOptions": "openOnSessionStart", + "outputCapture": "std", + "env": { + "DEBUG": "nsite,nsite:*", + "ALL_PROXY": "pac+file://proxy.pac" + } } ] } diff --git a/Dockerfile b/Dockerfile index 1b30cdc..fb3208e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -36,6 +36,7 @@ COPY --from=prod-deps /app/node_modules /app/node_modules COPY --from=build ./app/build ./build COPY ./public ./public +COPY ./proxy.pac . VOLUME [ "/var/cache/nginx" ] diff --git a/README.md b/README.md index 35b534d..b364d0a 100644 --- a/README.md +++ b/README.md @@ -13,3 +13,34 @@ docker compose up Once the service is running you can access the cached version at `http://localhost:8080` If you need to test, you can directly access the ts server at `http://localhost:3000` + +## Connecting to Tor and I2P relays + +nsite-ts supports `ALL_PROXY` and other proxy env variables [here](https://www.npmjs.com/package/proxy-from-env#environment-variables) + +Install Tor ([Documentation](https://community.torproject.org/onion-services/setup/install/)) and I2Pd ([Documentation](https://i2pd.readthedocs.io/en/latest/user-guide/install/)) + +Create a proxy.pac file + +```txt +// SPDX-License-Identifier: CC0-1.0 + +function FindProxyForURL(url, host) +{ + if (shExpMatch(host, "*.i2p")) + { + return "PROXY 127.0.0.1:4444; SOCKS5 127.0.0.1:4447"; + } + if (shExpMatch(host, "*.onion")) + { + return "SOCKS5 127.0.0.1:9050"; + } + return "DIRECT"; +} +``` + +Start server with `PROXY` variable + +```sh +PROXY=pac+file://proxy.pac +``` diff --git a/package.json b/package.json index 414ca06..fd4e4c0 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,8 @@ "koa-static": "^5.0.0", "mime": "^4.0.4", "nostr-tools": "^2.7.2", + "proxy-agent": "^6.4.0", + "proxy-from-env": "^1.1.0", "websocket-polyfill": "^1.0.0", "ws": "^8.18.0", "xbytes": "^1.9.1" @@ -46,6 +48,7 @@ "@types/koa__cors": "^5.0.0", "@types/koa__router": "^12.0.4", "@types/node": "^20.11.19", + "@types/proxy-from-env": "^1.0.4", "@types/ws": "^8.5.10", "nodemon": "^3.0.3", "prettier": "^3.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 948cc13..5af7ce5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -47,6 +47,12 @@ importers: nostr-tools: specifier: ^2.7.2 version: 2.7.2(typescript@5.6.2) + proxy-agent: + specifier: ^6.4.0 + version: 6.4.0 + proxy-from-env: + specifier: ^1.1.0 + version: 1.1.0 websocket-polyfill: specifier: 1.0.0 version: 1.0.0 @@ -90,6 +96,9 @@ importers: '@types/node': specifier: ^20.11.19 version: 20.16.5 + '@types/proxy-from-env': + specifier: ^1.0.4 + version: 1.0.4 '@types/ws': specifier: ^8.5.10 version: 8.5.12 @@ -403,6 +412,9 @@ packages: resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} engines: {node: '>= 6'} + '@tootallnate/quickjs-emscripten@0.23.0': + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} @@ -475,6 +487,9 @@ packages: '@types/node@20.16.5': resolution: {integrity: sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==} + '@types/proxy-from-env@1.0.4': + resolution: {integrity: sha512-TPR9/bCZAr3V1eHN4G3LD3OLicdJjqX1QRXWuNcCYgE66f/K8jO2ZRtHxI2D9MbnuUP6+qiKSS8eUHp6TFHGCw==} + '@types/qs@6.9.16': resolution: {integrity: sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==} @@ -504,6 +519,10 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} + agent-base@7.1.1: + resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} + engines: {node: '>= 14'} + agentkeepalive@4.5.0: resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} engines: {node: '>= 8.0.0'} @@ -539,6 +558,10 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} + ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -549,6 +572,10 @@ packages: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} + basic-ftp@5.0.5: + resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} + engines: {node: '>=10.0.0'} + better-path-resolve@1.0.0: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} @@ -649,6 +676,10 @@ packages: cross-spawn@5.1.0: resolution: {integrity: sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==} + data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -685,6 +716,10 @@ packages: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} + degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} @@ -750,11 +785,24 @@ packages: escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} hasBin: true + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} @@ -800,6 +848,10 @@ packages: fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -825,6 +877,10 @@ packages: engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} deprecated: This package is no longer supported. + get-uri@6.0.3: + resolution: {integrity: sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==} + engines: {node: '>= 14'} + github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} @@ -877,10 +933,18 @@ packages: resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} engines: {node: '>= 6'} + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} + https-proxy-agent@7.0.5: + resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} + engines: {node: '>= 14'} + human-id@1.0.2: resolution: {integrity: sha512-UNopramDEhHJD+VR+ehk8rOslwSfByxPIZyJRfV739NDhN5LF1fa1MqnzKm2lGTQRjNrjK19Q5fhkgIfjlVUKw==} @@ -988,6 +1052,9 @@ packages: jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + keygrip@1.1.0: resolution: {integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==} engines: {node: '>= 0.6'} @@ -1037,6 +1104,10 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + make-fetch-happen@9.1.0: resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==} engines: {node: '>= 10'} @@ -1137,6 +1208,10 @@ packages: resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} engines: {node: '>= 0.6'} + netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + node-abi@3.67.0: resolution: {integrity: sha512-bLn/fU/ALVBE9wj+p4Y21ZJWYFjUXLXPi/IewyLZkx3ApxKDNBWCKdReeKOtD8dWpOdDCeMyLh6ZewzcLsG2Nw==} engines: {node: '>=10'} @@ -1231,6 +1306,14 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + pac-proxy-agent@7.0.2: + resolution: {integrity: sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==} + engines: {node: '>= 14'} + + pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + package-manager-detector@0.2.0: resolution: {integrity: sha512-E385OSk9qDcXhcM9LNSe4sdhx8a9mAPrZ4sMLW+tmxl5ZuGtPUcdFu+MPP2jbgiWAZ6Pfe5soGFMd+0Db5Vrog==} @@ -1292,6 +1375,13 @@ packages: resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} engines: {node: '>=10'} + proxy-agent@6.4.0: + resolution: {integrity: sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==} + engines: {node: '>= 14'} + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pseudomap@1.0.2: resolution: {integrity: sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==} @@ -1411,6 +1501,10 @@ packages: resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==} engines: {node: '>= 10'} + socks-proxy-agent@8.0.4: + resolution: {integrity: sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==} + engines: {node: '>= 14'} + socks@2.8.3: resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} @@ -1537,6 +1631,10 @@ packages: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -1971,6 +2069,8 @@ snapshots: '@tootallnate/once@1.1.2': optional: true + '@tootallnate/quickjs-emscripten@0.23.0': {} + '@tybys/wasm-util@0.9.0': dependencies: tslib: 2.7.0 @@ -2075,6 +2175,10 @@ snapshots: dependencies: undici-types: 6.19.8 + '@types/proxy-from-env@1.0.4': + dependencies: + '@types/node': 20.16.5 + '@types/qs@6.9.16': {} '@types/range-parser@1.2.7': {} @@ -2111,6 +2215,12 @@ snapshots: - supports-color optional: true + agent-base@7.1.1: + dependencies: + debug: 4.3.7(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + agentkeepalive@4.5.0: dependencies: humanize-ms: 1.2.1 @@ -2146,6 +2256,10 @@ snapshots: array-union@2.1.0: {} + ast-types@0.13.4: + dependencies: + tslib: 2.7.0 + balanced-match@1.0.2: {} base64-js@1.5.1: {} @@ -2154,6 +2268,8 @@ snapshots: dependencies: safe-buffer: 5.1.2 + basic-ftp@5.0.5: {} + better-path-resolve@1.0.0: dependencies: is-windows: 1.0.2 @@ -2278,6 +2394,8 @@ snapshots: shebang-command: 1.2.0 which: 1.3.1 + data-uri-to-buffer@6.0.2: {} + debug@2.6.9: dependencies: ms: 2.0.0 @@ -2300,6 +2418,12 @@ snapshots: deep-extend@0.6.0: {} + degenerator@5.0.1: + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + delegates@1.0.0: {} denque@2.1.0: {} @@ -2349,8 +2473,20 @@ snapshots: escape-html@1.0.3: {} + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + esprima@4.0.1: {} + estraverse@5.3.0: {} + + esutils@2.0.3: {} + expand-template@2.0.3: {} extendable-error@0.1.7: {} @@ -2390,6 +2526,12 @@ snapshots: fs-constants@1.0.0: {} + fs-extra@11.2.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.11 @@ -2424,6 +2566,15 @@ snapshots: wide-align: 1.1.5 optional: true + get-uri@6.0.3: + dependencies: + basic-ftp: 5.0.5 + data-uri-to-buffer: 6.0.2 + debug: 4.3.7(supports-color@5.5.0) + fs-extra: 11.2.0 + transitivePeerDependencies: + - supports-color + github-from-package@0.0.0: {} glob-parent@5.1.2: @@ -2494,6 +2645,13 @@ snapshots: - supports-color optional: true + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.1 + debug: 4.3.7(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 @@ -2502,6 +2660,13 @@ snapshots: - supports-color optional: true + https-proxy-agent@7.0.5: + dependencies: + agent-base: 7.1.1 + debug: 4.3.7(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + human-id@1.0.2: {} humanize-ms@1.2.1: @@ -2565,7 +2730,6 @@ snapshots: dependencies: jsbn: 1.1.0 sprintf-js: 1.1.3 - optional: true is-binary-path@2.1.0: dependencies: @@ -2602,13 +2766,18 @@ snapshots: argparse: 1.0.10 esprima: 4.0.1 - jsbn@1.1.0: - optional: true + jsbn@1.1.0: {} jsonfile@4.0.0: optionalDependencies: graceful-fs: 4.2.11 + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + keygrip@1.1.0: dependencies: tsscmp: 1.0.6 @@ -2693,6 +2862,8 @@ snapshots: yallist: 4.0.0 optional: true + lru-cache@7.18.3: {} + make-fetch-happen@9.1.0: dependencies: agentkeepalive: 4.5.0 @@ -2805,6 +2976,8 @@ snapshots: negotiator@0.6.3: {} + netmask@2.0.2: {} + node-abi@3.67.0: dependencies: semver: 7.6.3 @@ -2926,6 +3099,24 @@ snapshots: p-try@2.2.0: {} + pac-proxy-agent@7.0.2: + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.1 + debug: 4.3.7(supports-color@5.5.0) + get-uri: 6.0.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.5 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.4 + transitivePeerDependencies: + - supports-color + + pac-resolver@7.0.1: + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + package-manager-detector@0.2.0: {} parseurl@1.3.3: {} @@ -2972,6 +3163,21 @@ snapshots: retry: 0.12.0 optional: true + proxy-agent@6.4.0: + dependencies: + agent-base: 7.1.1 + debug: 4.3.7(supports-color@5.5.0) + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.5 + lru-cache: 7.18.3 + pac-proxy-agent: 7.0.2 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.4 + transitivePeerDependencies: + - supports-color + + proxy-from-env@1.1.0: {} + pseudomap@1.0.2: {} pstree.remy@1.1.8: {} @@ -3073,8 +3279,7 @@ snapshots: slash@3.0.0: {} - smart-buffer@4.2.0: - optional: true + smart-buffer@4.2.0: {} socks-proxy-agent@6.2.1: dependencies: @@ -3085,11 +3290,18 @@ snapshots: - supports-color optional: true + socks-proxy-agent@8.0.4: + dependencies: + agent-base: 7.1.1 + debug: 4.3.7(supports-color@5.5.0) + socks: 2.8.3 + transitivePeerDependencies: + - supports-color + socks@2.8.3: dependencies: ip-address: 9.0.5 smart-buffer: 4.2.0 - optional: true source-map-support@0.5.21: dependencies: @@ -3105,8 +3317,7 @@ snapshots: sprintf-js@1.0.3: {} - sprintf-js@1.1.3: - optional: true + sprintf-js@1.1.3: {} sqlite3@5.1.7: dependencies: @@ -3223,6 +3434,8 @@ snapshots: universalify@0.1.2: {} + universalify@2.0.1: {} + util-deprecate@1.0.2: {} vary@1.1.2: {} diff --git a/src/helpers/http.ts b/src/helpers/http.ts index 568b618..46facd8 100644 --- a/src/helpers/http.ts +++ b/src/helpers/http.ts @@ -2,6 +2,8 @@ import { IncomingMessage } from "http"; import followRedirects from "follow-redirects"; const { http, https } = followRedirects; +import agent from "../proxy.js"; + export function makeRequestWithAbort(url: URL) { return new Promise<{ response: IncomingMessage; controller: AbortController }>((res, rej) => { const cancelController = new AbortController(); @@ -9,6 +11,7 @@ export function makeRequestWithAbort(url: URL) { url, { signal: cancelController.signal, + agent, }, (response) => { res({ response, controller: cancelController }); diff --git a/src/polyfill.ts b/src/polyfill.ts index ef5c8cd..435e6d8 100644 --- a/src/polyfill.ts +++ b/src/polyfill.ts @@ -1,3 +1,13 @@ -import { WebSocket } from "ws"; +import { ClientOptions, WebSocket } from "ws"; +import { ClientRequestArgs } from "http"; -global.WebSocket = global.WebSocket || WebSocket; +import agent from "./proxy.js"; + +class ProxyWebSocket extends WebSocket { + constructor(address: string | URL, options?: ClientOptions | ClientRequestArgs) { + super(address, { agent, ...options }); + } +} + +// @ts-expect-error +global.WebSocket = agent ? ProxyWebSocket : WebSocket; diff --git a/src/proxy.ts b/src/proxy.ts new file mode 100644 index 0000000..34fc05d --- /dev/null +++ b/src/proxy.ts @@ -0,0 +1,13 @@ +import { ProxyAgent } from "proxy-agent"; +import { getProxyForUrl } from "proxy-from-env"; + +const agent = new ProxyAgent({ keepAlive: true }); + +if (getProxyForUrl("http://example.onion")) { + console.log("Tor connections enabled"); +} +if (getProxyForUrl("http://example.i2p")) { + console.log("I2P connections enabled"); +} + +export default agent; diff --git a/tor-and-i2p.pac b/tor-and-i2p.pac new file mode 100644 index 0000000..29b2801 --- /dev/null +++ b/tor-and-i2p.pac @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: CC0-1.0 + +function FindProxyForURL(url, host) { + if (shExpMatch(host, "*.i2p")) { + return "PROXY 127.0.0.1:4444; SOCKS5 127.0.0.1:4447"; + } + if (shExpMatch(host, "*.onion")) { + return "SOCKS5 127.0.0.1:9050"; + } + return "DIRECT"; +}