Hua-Au-Yeung 3 rokov pred
rodič
commit
eec9a44bc6
9 zmenil súbory, kde vykonal 979 pridanie a 0 odobranie
  1. 7 0
      .gitignore
  2. 26 0
      README.md
  3. 454 0
      package-lock.json
  4. 22 0
      package.json
  5. 115 0
      src/lib/command.ts
  6. 41 0
      src/lib/constants.ts
  7. 201 0
      src/lib/server.ts
  8. 7 0
      src/server_test.ts
  9. 106 0
      tsconfig.json

+ 7 - 0
.gitignore

@@ -0,0 +1,7 @@
+.DS_Store
+Thumbs.db
+.idea/
+
+*.js
+node_modules/
+wz/

+ 26 - 0
README.md

@@ -0,0 +1,26 @@
+# tssocks5
+SOCKS v5 protocol implement by Typescript
+
+### Build
+```
+$ npm build
+```
+
+# Features
+- [x] Socks5 server
+- [x] Support IPv6
+- [x] Support Connect command
+- [x] Support DNS query cache
+- [ ] Support Username/Password authentication
+- [ ] Support Bind command
+- [ ] Support Udp Associate
+- [ ] Socks5 client
+
+
+
+## reference:
+* [Understand the working process of socks5 protocol and protocol details](https://wiyi.org/socks5-protocol-in-deep.html)
+* [Typescript in 5 minutes](https://www.tslang.cn/docs/handbook/typescript-in-5-minutes.html)
+
+## License
+Licensed under The MIT License

+ 454 - 0
package-lock.json

@@ -0,0 +1,454 @@
+{
+  "name": "Typescript socks5",
+  "version": "1.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "Typescript socks5",
+      "version": "1.0.0",
+      "license": "MIT",
+      "dependencies": {
+        "dns-sync": "^0.2.1",
+        "ipaddr.js": "^2.0.1",
+        "mem-cache": "^0.0.5"
+      },
+      "devDependencies": {
+        "@types/node": "^18.11.9",
+        "typescript": "^4.9.3"
+      }
+    },
+    "node_modules/@types/node": {
+      "version": "18.11.9",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz",
+      "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
+      "dev": true
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+    },
+    "node_modules/debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/dns-sync": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/dns-sync/-/dns-sync-0.2.1.tgz",
+      "integrity": "sha512-VB1pDSVs82kFsZuoHQ5/Ysx62WiIfDGn9sx/x55EoVyk8pLwdqWGB2XCaDDOusBllb+1y3XRijscFPJJfpbFiw==",
+      "dependencies": {
+        "debug": "^4",
+        "shelljs": "~0.8"
+      }
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+    },
+    "node_modules/glob": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dependencies": {
+        "function-bind": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "node_modules/interpret": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
+      "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/ipaddr.js": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
+      "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==",
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.11.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+      "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+      "dependencies": {
+        "has": "^1.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/mem-cache": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/mem-cache/-/mem-cache-0.0.5.tgz",
+      "integrity": "sha512-ihkqWSDYdFpaGa5Y3G2QUTvA69I/IqDWT+XRRoMCSYwWZk6n0ecJQZLSoGqEDRaDpPurz2+d9FPqzDZ0xKn7iQ=="
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+    },
+    "node_modules/rechoir": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+      "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
+      "dependencies": {
+        "resolve": "^1.1.6"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.22.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+      "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+      "dependencies": {
+        "is-core-module": "^2.9.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/shelljs": {
+      "version": "0.8.5",
+      "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
+      "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
+      "dependencies": {
+        "glob": "^7.0.0",
+        "interpret": "^1.0.0",
+        "rechoir": "^0.6.2"
+      },
+      "bin": {
+        "shjs": "bin/shjs"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "4.9.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
+      "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
+      "dev": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=4.2.0"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+    }
+  },
+  "dependencies": {
+    "@types/node": {
+      "version": "18.11.9",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz",
+      "integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
+      "dev": true
+    },
+    "balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+    },
+    "debug": {
+      "version": "4.3.4",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+      "requires": {
+        "ms": "2.1.2"
+      }
+    },
+    "dns-sync": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/dns-sync/-/dns-sync-0.2.1.tgz",
+      "integrity": "sha512-VB1pDSVs82kFsZuoHQ5/Ysx62WiIfDGn9sx/x55EoVyk8pLwdqWGB2XCaDDOusBllb+1y3XRijscFPJJfpbFiw==",
+      "requires": {
+        "debug": "^4",
+        "shelljs": "~0.8"
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
+    },
+    "function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+    },
+    "glob": {
+      "version": "7.2.3",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.1.1",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "requires": {
+        "function-bind": "^1.1.1"
+      }
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+    },
+    "interpret": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
+      "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA=="
+    },
+    "ipaddr.js": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz",
+      "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng=="
+    },
+    "is-core-module": {
+      "version": "2.11.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
+      "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
+      "requires": {
+        "has": "^1.0.3"
+      }
+    },
+    "mem-cache": {
+      "version": "0.0.5",
+      "resolved": "https://registry.npmjs.org/mem-cache/-/mem-cache-0.0.5.tgz",
+      "integrity": "sha512-ihkqWSDYdFpaGa5Y3G2QUTvA69I/IqDWT+XRRoMCSYwWZk6n0ecJQZLSoGqEDRaDpPurz2+d9FPqzDZ0xKn7iQ=="
+    },
+    "minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "ms": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="
+    },
+    "path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+    },
+    "rechoir": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
+      "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
+      "requires": {
+        "resolve": "^1.1.6"
+      }
+    },
+    "resolve": {
+      "version": "1.22.1",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
+      "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
+      "requires": {
+        "is-core-module": "^2.9.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      }
+    },
+    "shelljs": {
+      "version": "0.8.5",
+      "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
+      "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
+      "requires": {
+        "glob": "^7.0.0",
+        "interpret": "^1.0.0",
+        "rechoir": "^0.6.2"
+      }
+    },
+    "supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
+    },
+    "typescript": {
+      "version": "4.9.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
+      "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
+      "dev": true
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+    }
+  }
+}

+ 22 - 0
package.json

@@ -0,0 +1,22 @@
+{
+  "name": "Typescript socks5",
+  "version": "1.0.0",
+  "description": "Typescript implement socks5 server and client",
+  "type": "module",
+  "module": "es6",
+  "scripts": {
+    "build": "npm install && npx tsc -p tsconfig.json"
+  },
+  "keywords": ["socks5", "typescript"],
+  "author": "Huazai",
+  "license": "MIT",
+  "dependencies": {
+    "dns-sync": "^0.2.1",
+    "ipaddr.js": "^2.0.1",
+    "mem-cache": "^0.0.5"
+  },
+  "devDependencies": {
+    "@types/node": "^18.11.9",
+    "typescript": "^4.9.3"
+  }
+}

+ 115 - 0
src/lib/command.ts

@@ -0,0 +1,115 @@
+import {AddressType, CommandReplyType, CommandType} from "./constants.js";
+import ipaddr from 'ipaddr.js';
+
+export class Command {
+    public version: number;
+    public commandType: CommandType;
+    public addressType: AddressType;
+    public host: string;
+    public port: number;
+
+    constructor(chunk: Buffer) {
+        // console.log(inspect(chunk));
+        this.version = chunk.readUint8(0);
+        this.commandType = chunk.readUint8(1) as CommandType;
+        this.addressType = chunk.readUint8(3) as AddressType;
+
+        [this.host, this.port] = this.parseAddress(chunk);
+    }
+
+    private parseAddress(chunk: Buffer):[string, number] {
+        let address = [], port;
+        switch (this.addressType) {
+            case AddressType.IPv4:
+                address.push(chunk.readUint8(4).toString());
+                address.push(chunk.readUint8(5).toString());
+                address.push(chunk.readUint8(6).toString());
+                address.push(chunk.readUint8(7).toString());
+                port = chunk.readUInt16BE(8);
+                return [address.join('.'), port];
+            case AddressType.Domain:
+                const domainLength: number = chunk.readUint8(4);
+                let i:number;
+                for(i = 5; i < 5 + domainLength; i++) {
+                    address.push(String.fromCharCode(chunk.readUint8(i)));
+                }
+                port = chunk.readUInt16BE(i);
+                return [address.join(''), port];
+            case AddressType.IPv6:
+                let byteArray: number[] = [];
+                for(let i = 4; i < 20; i++) {
+                    byteArray.push(chunk.readUint8(i));
+                }
+                const ipv6Addr = ipaddr.fromByteArray(byteArray);
+                port = chunk.readUInt16BE(20);
+                return [ipv6Addr.toString(), port];
+            default:
+                break;
+        }
+
+        return ['', 0];
+    }
+}
+
+export class CommandReply {
+    private bufferLength:number = -1;
+    constructor(
+        private commandReplyType: CommandReplyType,
+        private addressType: AddressType,
+        private host: string,
+        private port: number
+    ) {
+        switch (this.addressType) {
+            case AddressType.IPv4:
+                this.bufferLength = 10;
+                break;
+            case AddressType.Domain:
+                this.bufferLength = 7 + this.host.length;
+                break;
+            case AddressType.IPv6:
+                this.bufferLength = 22;
+                break;
+        }
+    }
+
+    public generateBuffer(): Buffer {
+        const chunk = Buffer.alloc(this.bufferLength);
+        chunk.writeUint8(5, 0);
+        chunk.writeUint8(this.commandReplyType.valueOf(), 1);
+        chunk.writeUint8(0, 2);
+        chunk.writeUint8(this.addressType.valueOf(), 3);
+        const nextOffset: number = this.Host2Buffer(chunk, 4);
+        chunk.writeUInt16BE(this.port, nextOffset);
+
+        return chunk;
+    }
+
+    private Host2Buffer(chunk: Buffer, offset: number): number {
+        let nextOffset: number = -1;
+        switch (this.addressType) {
+            case AddressType.IPv4:
+                this.host.split('.').forEach((seg: string) => {
+                    chunk.writeUint8(Number.parseInt(seg), offset++);
+                });
+                nextOffset = 8;
+                break;
+            case AddressType.Domain:
+                chunk.writeUint8(this.host.length, 4);
+                offset += 1;
+                [...this.host].forEach((c, i) => {
+                   chunk.writeUint8(this.host.charCodeAt(i), offset++);
+                });
+                nextOffset = 4 + 1 + this.host.length;
+                break;
+            case AddressType.IPv6:
+                const bytes = ipaddr.parse(this.host).toByteArray();
+                bytes.map((byte) => {
+                    chunk.writeUint8(byte, offset++);
+                });
+                nextOffset = 20;
+                break;
+        }
+
+        return nextOffset;
+    }
+}

+ 41 - 0
src/lib/constants.ts

@@ -0,0 +1,41 @@
+export enum CommandType {
+    Connect = 0x01,
+    Bind = 0x02,
+    UdpAssociate = 0x03
+}
+
+export enum AddressType {
+    IPv4 = 0x01,
+    Domain = 0x03,
+    IPv6 = 0x04
+}
+
+export enum ClientSocketState {
+    connected = 0x00,
+    Handshaking = 0x01,
+    Authenticate = 0x02,
+    CmdProcessing = 0x03,
+    DataTransmission = 0x04
+}
+
+export enum AuthMethodType {
+    NoAuth = 0x00,
+    GSSAPI = 0x01,
+    Basic = 0x02, // username/password
+    // 0x03 - 0x7F IANA assigned
+    // 0x80 - 0xFE private methods
+    Invalid = 0xFF
+}
+
+export enum CommandReplyType {
+    Succeeded = 0x00,
+    GeneralFailure = 0x01,
+    ConnectionDisallowedByRuleset = 0x02,
+    NetworkUnreachable = 0x03,
+    HostUnreachable = 0x04,
+    ConnectionRefused = 0x05,
+    TTLExpired = 0x06,
+    CommandNotSupported = 0x07,
+    AddressTypeNotSupported = 0x08
+    // 0x09 - 0xFF not assigned
+}

+ 201 - 0
src/lib/server.ts

@@ -0,0 +1,201 @@
+import {AddressType, AuthMethodType, ClientSocketState, CommandReplyType, CommandType} from "./constants.js";
+import {Command, CommandReply} from './command.js'
+import {EventEmitter} from 'events';
+import * as net from 'net';
+import {inspect} from "util";
+// @ts-ignore
+import dnsSync from 'dns-sync';
+// @ts-ignore
+import Memcache from 'mem-cache';
+
+export class Socks5Server extends EventEmitter{
+    private tcpServer: net.Server;
+    private acceptAuthMethod: AuthMethodType;
+    private mcache: Memcache;
+
+    constructor(port: number, hostname: string) {
+        super();
+        this.acceptAuthMethod = AuthMethodType.NoAuth; // only NoAuth
+        this.mcache = new Memcache();
+
+        this.tcpServer = net.createServer((clientSocket:net.Socket) => {
+            let clientStats = ClientSocketState.connected;
+            console.log(`Connect from ${clientSocket.remoteAddress}:${clientSocket.remotePort}`);
+
+            clientSocket.on('data', (data) => {
+                console.log(`client on data: ${inspect(data)}`);
+                switch (clientStats) {
+                    case ClientSocketState.connected:
+                        clientStats = ClientSocketState.Handshaking;
+                        if (!this.handshake(clientSocket, data)) {
+                            clientSocket.end();
+                        } else {
+                            if (this.acceptAuthMethod == AuthMethodType.NoAuth) {
+                                clientStats = ClientSocketState.CmdProcessing;
+                            } else {
+                                // TODO other AuthMethodType
+                            }
+                        }
+                        break;
+                    case ClientSocketState.CmdProcessing:
+                        if (!this.processCmd(clientSocket, data)) {
+                            clientSocket.end();
+                        } else {
+                            clientStats = ClientSocketState.DataTransmission;
+                        }
+                        break;
+                    case ClientSocketState.DataTransmission:
+                        console.log(`Data transfer begins`);
+                        break;
+                    default:
+                        console.log(`UnHandle data: ${inspect(data)}`);
+                        break;
+                }
+            });
+
+            clientSocket.on('close', () => {
+                console.log(`client ${clientSocket.remoteAddress}:${clientSocket.remotePort} closed`);
+            });
+
+            clientSocket.on('error', (error:Error) => {
+                switch (error.message) {
+                    case 'read ECONNRESET':
+                        break;
+                    default:
+                        console.error(error.message);
+                        break;
+                }
+            });
+        });
+
+        this.tcpServer.listen(port, hostname);
+
+        this.tcpServer.on('listening', () => {
+            console.log('Socks5 server started...');
+        });
+    }
+
+    private handshake(socket: net.Socket, chunk: Buffer): boolean {
+        const version: number = chunk.readUint8(0);
+        const numOfMethods = chunk.readUint8(1);
+        const methods = [];
+
+        for(let i = 0; i < numOfMethods; i++) {
+            methods.push(chunk.readUint8(i + 2));
+        }
+
+        // console.log(`client version ${version} number of methods ${numOfMethods}`);
+        // console.log(`client accept methods: ${inspect(methods)}`);
+
+        const buffer = Buffer.alloc(2);
+        buffer.writeUint8(5, 0);
+        if(methods.indexOf(this.acceptAuthMethod) !== -1) {
+            buffer.writeUint8(this.acceptAuthMethod, 1);
+            socket.write(buffer);
+            return true;
+        } else {
+            buffer.writeUint8(0xFF, 1);
+            socket.write(buffer);
+            return false;
+        }
+    }
+
+    private processCmd(socket: net.Socket, chunk: Buffer): Boolean {
+        const cmd = new Command(chunk);
+        let readyToConnectRemoteHost:string = cmd.host,
+            readyToConnectRemotePort:number = cmd.port;
+        let commandReply: CommandReply;
+        let isCommandSucceeded: boolean = true;
+
+        // error command type
+        if (!Object.values(CommandType).includes(cmd.commandType)) {
+            console.error(`Error command type [${cmd.commandType}] from ${socket.remoteAddress}:${socket.remotePort}`);
+            socket.end();
+        }
+
+        switch (cmd.addressType) {
+            case AddressType.Domain:
+                const dnsResolveRecord = this.dnsQuery(cmd.host);
+                // resole domain name & no record found
+                if (!dnsResolveRecord) {
+                    commandReply = new CommandReply(
+                        CommandReplyType.HostUnreachable,
+                        AddressType.Domain, cmd.host, cmd.port
+                    );
+                    isCommandSucceeded = false;
+                } else {
+                    readyToConnectRemoteHost = dnsResolveRecord;
+                }
+                break;
+            case AddressType.IPv4:
+                break;
+            case AddressType.IPv6:
+                break;
+            default:
+                commandReply = new CommandReply(
+                    CommandReplyType.AddressTypeNotSupported,
+                    cmd.addressType, cmd.host, cmd.port
+                );
+                isCommandSucceeded = false;
+        }
+
+        if (isCommandSucceeded) {
+            switch (cmd.commandType) {
+                case CommandType.Connect:
+                    // remove data event listeners
+                    socket.removeAllListeners('data');
+                    const remoteSocket: net.Socket = new net.Socket();
+                    remoteSocket.connect(readyToConnectRemotePort, readyToConnectRemoteHost, () => {
+                        const commandReply2: CommandReply = new CommandReply(
+                            CommandReplyType.Succeeded,
+                            cmd.addressType, readyToConnectRemoteHost, readyToConnectRemotePort
+                        );
+                        const replyBuffer: Buffer = commandReply2.generateBuffer();
+                        socket.write(replyBuffer);
+                        socket.pipe(remoteSocket);
+                        remoteSocket.pipe(socket);
+                    });
+                    remoteSocket.on('error', (error: Error) => {
+                        console.error(`RemoteSocket Error:${inspect(error)}`);
+                    });
+
+                    break;
+                case CommandType.Bind:
+                // TODO
+                case CommandType.UdpAssociate:
+                // TODO
+                default:
+                    commandReply = new CommandReply(
+                        CommandReplyType.CommandNotSupported,
+                        cmd.addressType, cmd.host, cmd.port
+                    );
+                    isCommandSucceeded = false;
+            }
+        }
+
+        // @ts-ignore
+        if (commandReply != undefined) {
+            const replyBuffer: Buffer = commandReply.generateBuffer();
+            console.log(inspect(replyBuffer));
+            socket.write(replyBuffer);
+        }
+        return isCommandSucceeded;
+    }
+
+    // query and cache dns lookup record for 60 * 10 seconds
+    private dnsQuery(domain: string): string {
+        const key = `D:${domain}`;
+        let value = this.mcache.get(key);
+        if (!value) {
+            value = dnsSync.resolve(domain);
+        }
+
+        if (value == null) {
+            return '';
+        } else {
+            this.mcache.set(key, value, 60 * 10);
+            return value;
+        }
+    }
+}
+

+ 7 - 0
src/server_test.ts

@@ -0,0 +1,7 @@
+import {Socks5Server} from "./lib/server.js";
+
+process.on('uncaughtException', function (err) {
+    console.error(err);
+});
+
+const server = new Socks5Server(2211, 'localhost');

+ 106 - 0
tsconfig.json

@@ -0,0 +1,106 @@
+{
+  "compilerOptions": {
+    /* Visit https://aka.ms/tsconfig to read more about this file */
+
+    /* Projects */
+    // "incremental": true,                              /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
+    // "composite": true,                                /* Enable constraints that allow a TypeScript project to be used with project references. */
+    // "tsBuildInfoFile": "./.tsbuildinfo",              /* Specify the path to .tsbuildinfo incremental compilation file. */
+    // "disableSourceOfProjectReferenceRedirect": true,  /* Disable preferring source files instead of declaration files when referencing composite projects. */
+    // "disableSolutionSearching": true,                 /* Opt a project out of multi-project reference checking when editing. */
+    // "disableReferencedProjectLoad": true,             /* Reduce the number of projects loaded automatically by TypeScript. */
+
+    /* Language and Environment */
+    "target": "es2016",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
+    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
+    // "jsx": "preserve",                                /* Specify what JSX code is generated. */
+    // "experimentalDecorators": true,                   /* Enable experimental support for TC39 stage 2 draft decorators. */
+    // "emitDecoratorMetadata": true,                    /* Emit design-type metadata for decorated declarations in source files. */
+    // "jsxFactory": "",                                 /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
+    // "jsxFragmentFactory": "",                         /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
+    // "jsxImportSource": "",                            /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
+    // "reactNamespace": "",                             /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
+    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
+    // "useDefineForClassFields": true,                  /* Emit ECMAScript-standard-compliant class fields. */
+    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */
+
+    /* Modules */
+    "module": "es6",                                /* Specify what module code is generated. */
+    // "rootDir": "./",                                  /* Specify the root folder within your source files. */
+    "moduleResolution": "node",                       /* Specify how TypeScript looks up a file from a given module specifier. */
+    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
+    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
+    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
+    // "typeRoots": [],                                  /* Specify multiple folders that act like './node_modules/@types'. */
+    // "types": [],                                      /* Specify type package names to be included without being referenced in a source file. */
+    // "allowUmdGlobalAccess": true,                     /* Allow accessing UMD globals from modules. */
+    // "moduleSuffixes": [],                             /* List of file name suffixes to search when resolving a module. */
+    // "resolveJsonModule": true,                        /* Enable importing .json files. */
+    // "noResolve": true,                                /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
+
+    /* JavaScript Support */
+    // "allowJs": true,                                  /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
+    // "checkJs": true,                                  /* Enable error reporting in type-checked JavaScript files. */
+    // "maxNodeModuleJsDepth": 1,                        /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
+
+    /* Emit */
+    // "declaration": true,                              /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
+    // "declarationMap": true,                           /* Create sourcemaps for d.ts files. */
+    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
+    // "sourceMap": true,                                /* Create source map files for emitted JavaScript files. */
+    // "outFile": "./",                                  /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
+    "outDir": "",                                   /* Specify an output folder for all emitted files. */
+    // "removeComments": true,                           /* Disable emitting comments. */
+    // "noEmit": true,                                   /* Disable emitting files from a compilation. */
+    // "importHelpers": true,                            /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
+    // "importsNotUsedAsValues": "remove",               /* Specify emit/checking behavior for imports that are only used for types. */
+    // "downlevelIteration": true,                       /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
+    // "sourceRoot": "",                                 /* Specify the root path for debuggers to find the reference source code. */
+    // "mapRoot": "",                                    /* Specify the location where debugger should locate map files instead of generated locations. */
+    // "inlineSourceMap": true,                          /* Include sourcemap files inside the emitted JavaScript. */
+    // "inlineSources": true,                            /* Include source code in the sourcemaps inside the emitted JavaScript. */
+    // "emitBOM": true,                                  /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
+    // "newLine": "crlf",                                /* Set the newline character for emitting files. */
+    // "stripInternal": true,                            /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
+    // "noEmitHelpers": true,                            /* Disable generating custom helper functions like '__extends' in compiled output. */
+    // "noEmitOnError": true,                            /* Disable emitting files if any type checking errors are reported. */
+    // "preserveConstEnums": true,                       /* Disable erasing 'const enum' declarations in generated code. */
+    // "declarationDir": "./",                           /* Specify the output directory for generated declaration files. */
+    // "preserveValueImports": true,                     /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
+
+    /* Interop Constraints */
+    // "isolatedModules": true,                          /* Ensure that each file can be safely transpiled without relying on other imports. */
+    // "allowSyntheticDefaultImports": true,             /* Allow 'import x from y' when a module doesn't have a default export. */
+    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
+    // "preserveSymlinks": true,                         /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
+    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */
+
+    /* Type Checking */
+    "strict": true,                                      /* Enable all strict type-checking options. */
+    // "noImplicitAny": true,                            /* Enable error reporting for expressions and declarations with an implied 'any' type. */
+    // "strictNullChecks": true,                         /* When type checking, take into account 'null' and 'undefined'. */
+    // "strictFunctionTypes": true,                      /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
+    // "strictBindCallApply": true,                      /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
+    // "strictPropertyInitialization": true,             /* Check for class properties that are declared but not set in the constructor. */
+    // "noImplicitThis": true,                           /* Enable error reporting when 'this' is given the type 'any'. */
+    // "useUnknownInCatchVariables": true,               /* Default catch clause variables as 'unknown' instead of 'any'. */
+    // "alwaysStrict": true,                             /* Ensure 'use strict' is always emitted. */
+    // "noUnusedLocals": true,                           /* Enable error reporting when local variables aren't read. */
+    // "noUnusedParameters": true,                       /* Raise an error when a function parameter isn't read. */
+    // "exactOptionalPropertyTypes": true,               /* Interpret optional property types as written, rather than adding 'undefined'. */
+    // "noImplicitReturns": true,                        /* Enable error reporting for codepaths that do not explicitly return in a function. */
+    // "noFallthroughCasesInSwitch": true,               /* Enable error reporting for fallthrough cases in switch statements. */
+    // "noUncheckedIndexedAccess": true,                 /* Add 'undefined' to a type when accessed using an index. */
+    // "noImplicitOverride": true,                       /* Ensure overriding members in derived classes are marked with an override modifier. */
+    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */
+    // "allowUnusedLabels": true,                        /* Disable error reporting for unused labels. */
+    // "allowUnreachableCode": true,                     /* Disable error reporting for unreachable code. */
+
+    /* Completeness */
+    // "skipDefaultLibCheck": true,                      /* Skip type checking .d.ts files that are included with TypeScript. */
+    "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
+  },
+  "include": [
+    "./src/"
+  ]
+}