fanqiang 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/lib/core/TerraformTunnelProxyOperations.d.ts.map +1 -1
- package/lib/core/TerraformTunnelProxyOperations.js +24 -0
- package/lib/core/TerraformTunnelProxyOperations.js.map +1 -1
- package/lib/core/TerraformTunnelProxyOperations.ts +23 -0
- package/lib/core/terraform.d.ts.map +1 -1
- package/lib/core/terraform.js +15 -4
- package/lib/core/terraform.js.map +1 -1
- package/lib/core/terraform.ts +15 -4
- package/lib/domain/Clash.d.ts.map +1 -1
- package/lib/domain/Clash.js +12 -2
- package/lib/domain/Clash.js.map +1 -1
- package/lib/domain/Clash.ts +12 -2
- package/package.json +5 -14
- package/terraform/cloud-init/proxy-init.sh +9 -0
- package/terraform/cloud-init/tunnel-init.sh +38 -0
- package/terraform/main.tf +25 -0
- package/terraform/outputs.tf +6 -0
- package/terraform/proxy.tf +34 -0
- package/terraform/tunnel.tf +106 -0
- package/terraform/variables.tf +18 -0
package/README.md
CHANGED
|
@@ -33,6 +33,8 @@ Options:
|
|
|
33
33
|
[string] [default: "us-east-1"]
|
|
34
34
|
--tunnel-region Aliyun region for tunnel deployment
|
|
35
35
|
[string] [default: "cn-shanghai"]
|
|
36
|
+
--bucket AWS S3 bucket name, used to store clash client configuration file
|
|
37
|
+
[string] [default: "fanqiang-$USER"]
|
|
36
38
|
--help Show help [boolean]
|
|
37
39
|
--version Show version number [boolean]
|
|
38
40
|
```
|
|
@@ -43,7 +45,7 @@ You need to configure an AWS IAM user on the local machine before running any co
|
|
|
43
45
|
supports reading AWS credentials from <code>Shared Credentials File</code>:
|
|
44
46
|
|
|
45
47
|
- The shared credentials file on Linux, Unix, and macOS: ~/.aws/credentials
|
|
46
|
-
- The shared credentials file on Windows: C:\Users\USER_NAME
|
|
48
|
+
- The shared credentials file on Windows: C:\Users\USER_NAME\\.aws\credentials
|
|
47
49
|
|
|
48
50
|
An example of credentials file:
|
|
49
51
|
|
|
@@ -63,7 +65,7 @@ You need to configure an Aliyun RAM user on a local machine if you want to use -
|
|
|
63
65
|
supports reading credentials from <code>$HOME/.alibabacloud/credentials</code>:
|
|
64
66
|
|
|
65
67
|
- The credentials file on Linux, Unix, and macOS: ~/.alibabacloud/credentials
|
|
66
|
-
- The credentials file on Windows: C:\Users\USER_NAME
|
|
68
|
+
- The credentials file on Windows: C:\Users\USER_NAME\\.alibabacloud\credentials
|
|
67
69
|
|
|
68
70
|
An example of credentials file:
|
|
69
71
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerraformTunnelProxyOperations.d.ts","sourceRoot":"","sources":["TerraformTunnelProxyOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"TerraformTunnelProxyOperations.d.ts","sourceRoot":"","sources":["TerraformTunnelProxyOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,qBAAqB,EACtB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAMhD,qBAAa,8BAA+B,YAAW,qBAAqB;IAC9D,OAAO,CAAC,QAAQ,CAAC,aAAa;gBAAb,aAAa,EAAE,aAAa;IAEnD,MAAM,CAAC,OAAO,EAAE,0BAA0B,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAoB/E,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAI/B"}
|
|
@@ -5,12 +5,23 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const terraform = tslib_1.__importStar(require("./terraform"));
|
|
6
6
|
const AwsS3CloudStorage_1 = require("./AwsS3CloudStorage");
|
|
7
7
|
const fs = tslib_1.__importStar(require("fs-extra"));
|
|
8
|
+
const net = tslib_1.__importStar(require("net"));
|
|
9
|
+
const promise_retry_1 = tslib_1.__importDefault(require("promise-retry"));
|
|
8
10
|
class TerraformTunnelProxyOperations {
|
|
9
11
|
constructor(configuration) {
|
|
10
12
|
this.configuration = configuration;
|
|
11
13
|
}
|
|
12
14
|
async create(request) {
|
|
13
15
|
const applyResult = await terraform.apply(request, this.configuration.terraformWorkspace, this.configuration.aliyun.credentials);
|
|
16
|
+
await promise_retry_1.default(async (retry) => {
|
|
17
|
+
try {
|
|
18
|
+
await checkServiceAvailable(request.port, applyResult.address, 2000);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
console.log("Service is not ready, waiting...");
|
|
22
|
+
retry(error);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
14
25
|
return {
|
|
15
26
|
address: applyResult.address,
|
|
16
27
|
cloudStorage: new AwsS3CloudStorage_1.AwsS3CloudStorage(request.proxyRegion, request.bucket, applyResult.bucketDomain),
|
|
@@ -22,4 +33,17 @@ class TerraformTunnelProxyOperations {
|
|
|
22
33
|
}
|
|
23
34
|
}
|
|
24
35
|
exports.TerraformTunnelProxyOperations = TerraformTunnelProxyOperations;
|
|
36
|
+
async function checkServiceAvailable(port, host, timeout) {
|
|
37
|
+
const socket = net.connect({ port, host, family: 4, timeout });
|
|
38
|
+
try {
|
|
39
|
+
await new Promise((resolve, reject) => {
|
|
40
|
+
socket.once("connect", resolve);
|
|
41
|
+
socket.once("timeout", () => reject("timeout"));
|
|
42
|
+
socket.once("error", (err) => reject(err));
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
socket.destroy();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
25
49
|
//# sourceMappingURL=TerraformTunnelProxyOperations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TerraformTunnelProxyOperations.js","sourceRoot":"","sources":["TerraformTunnelProxyOperations.ts"],"names":[],"mappings":";;;;AAKA,+DAAyC;AAEzC,2DAAwD;AACxD,qDAA+B;
|
|
1
|
+
{"version":3,"file":"TerraformTunnelProxyOperations.js","sourceRoot":"","sources":["TerraformTunnelProxyOperations.ts"],"names":[],"mappings":";;;;AAKA,+DAAyC;AAEzC,2DAAwD;AACxD,qDAA+B;AAC/B,iDAA2B;AAC3B,0EAAyC;AAEzC,MAAa,8BAA8B;IACzC,YAA6B,aAA4B;QAA5B,kBAAa,GAAb,aAAa,CAAe;IAAG,CAAC;IAE7D,KAAK,CAAC,MAAM,CAAC,OAAmC;QAC9C,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,KAAK,CACvC,OAAO,EACP,IAAI,CAAC,aAAa,CAAC,kBAAkB,EACrC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CACtC,CAAC;QACF,MAAM,uBAAY,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;YACjC,IAAI;gBACF,MAAM,qBAAqB,CAAC,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;aACtE;YAAC,OAAO,KAAK,EAAE;gBACd,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;gBAChD,KAAK,CAAC,KAAK,CAAC,CAAC;aACd;QACH,CAAC,CAAC,CAAC;QACH,OAAO;YACL,OAAO,EAAE,WAAW,CAAC,OAAO;YAC5B,YAAY,EAAE,IAAI,qCAAiB,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,CAAC,YAAY,CAAC;SACnG,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,kBAAkB,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACtG,MAAM,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,kBAAkB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvF,CAAC;CACF;AA3BD,wEA2BC;AAED,KAAK,UAAU,qBAAqB,CAAC,IAAY,EAAE,IAAY,EAAE,OAAe;IAC9E,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAC/D,IAAI;QACF,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACpC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;YAChD,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;KACJ;YAAS;QACR,MAAM,CAAC,OAAO,EAAE,CAAC;KAClB;AACH,CAAC"}
|
|
@@ -7,6 +7,8 @@ import * as terraform from "./terraform";
|
|
|
7
7
|
import { Configuration } from "./Configuration";
|
|
8
8
|
import { AwsS3CloudStorage } from "./AwsS3CloudStorage";
|
|
9
9
|
import * as fs from "fs-extra";
|
|
10
|
+
import * as net from "net";
|
|
11
|
+
import promiseRetry from "promise-retry";
|
|
10
12
|
|
|
11
13
|
export class TerraformTunnelProxyOperations implements TunnelProxyOperations {
|
|
12
14
|
constructor(private readonly configuration: Configuration) {}
|
|
@@ -17,6 +19,14 @@ export class TerraformTunnelProxyOperations implements TunnelProxyOperations {
|
|
|
17
19
|
this.configuration.terraformWorkspace,
|
|
18
20
|
this.configuration.aliyun.credentials
|
|
19
21
|
);
|
|
22
|
+
await promiseRetry(async (retry) => {
|
|
23
|
+
try {
|
|
24
|
+
await checkServiceAvailable(request.port, applyResult.address, 2000);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.log("Service is not ready, waiting...");
|
|
27
|
+
retry(error);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
20
30
|
return {
|
|
21
31
|
address: applyResult.address,
|
|
22
32
|
cloudStorage: new AwsS3CloudStorage(request.proxyRegion, request.bucket, applyResult.bucketDomain),
|
|
@@ -28,3 +38,16 @@ export class TerraformTunnelProxyOperations implements TunnelProxyOperations {
|
|
|
28
38
|
await fs.rm(this.configuration.terraformWorkspace, { force: true, recursive: true });
|
|
29
39
|
}
|
|
30
40
|
}
|
|
41
|
+
|
|
42
|
+
async function checkServiceAvailable(port: number, host: string, timeout: number): Promise<void> {
|
|
43
|
+
const socket = net.connect({ port, host, family: 4, timeout });
|
|
44
|
+
try {
|
|
45
|
+
await new Promise((resolve, reject) => {
|
|
46
|
+
socket.once("connect", resolve);
|
|
47
|
+
socket.once("timeout", () => reject("timeout"));
|
|
48
|
+
socket.once("error", (err) => reject(err));
|
|
49
|
+
});
|
|
50
|
+
} finally {
|
|
51
|
+
socket.destroy();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terraform.d.ts","sourceRoot":"","sources":["terraform.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAmC,MAAM,qBAAqB,CAAC;AAEzF,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"terraform.d.ts","sourceRoot":"","sources":["terraform.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAmC,MAAM,qBAAqB,CAAC;AAEzF,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAM7E,wBAAsB,KAAK,CACzB,OAAO,EAAE,0BAA0B,EACnC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,iBAAiB,GAC7B,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,CAAC,CAOpD;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAM5F"}
|
package/lib/core/terraform.js
CHANGED
|
@@ -8,9 +8,10 @@ const util = tslib_1.__importStar(require("util"));
|
|
|
8
8
|
const process = tslib_1.__importStar(require("process"));
|
|
9
9
|
const fs = tslib_1.__importStar(require("fs-extra"));
|
|
10
10
|
const path = tslib_1.__importStar(require("path"));
|
|
11
|
+
const promise_retry_1 = tslib_1.__importDefault(require("promise-retry"));
|
|
11
12
|
async function apply(request, workdir, credentials) {
|
|
12
13
|
await init(request, workdir);
|
|
13
|
-
await
|
|
14
|
+
await provisioningRetry(["apply", "-auto-approve"], workdir, aliyunCredentials_1.asTerraformEnvironmentVariables(credentials));
|
|
14
15
|
return {
|
|
15
16
|
address: await inspecting(["output", "-raw", "address"], workdir),
|
|
16
17
|
bucketDomain: await inspecting(["output", "-raw", "bucket_domain_name"], workdir),
|
|
@@ -22,7 +23,7 @@ async function destroy(workdir, credentials) {
|
|
|
22
23
|
console.log("Tunnel proxy never created, nothing to destroy");
|
|
23
24
|
return;
|
|
24
25
|
}
|
|
25
|
-
await
|
|
26
|
+
await provisioningRetry(["destroy", "-auto-approve"], workdir, aliyunCredentials_1.asTerraformEnvironmentVariables(credentials));
|
|
26
27
|
}
|
|
27
28
|
exports.destroy = destroy;
|
|
28
29
|
async function init(request, workdir) {
|
|
@@ -37,10 +38,20 @@ async function init(request, workdir) {
|
|
|
37
38
|
});
|
|
38
39
|
if (!(await fs.pathExists(path.join(workdir, ".terraform")))) {
|
|
39
40
|
await fs.copy(path.resolve(__dirname, "..", "..", "terraform"), workdir, { overwrite: true, recursive: true });
|
|
40
|
-
await
|
|
41
|
+
await provisioningRetry(["init"], workdir);
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
|
-
async function
|
|
44
|
+
async function provisioningRetry(args, cwd, customEnv = {}) {
|
|
45
|
+
await promise_retry_1.default(async (retry) => {
|
|
46
|
+
try {
|
|
47
|
+
await provisioning(args, cwd, customEnv);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
retry(error);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
async function provisioning(args, cwd, customEnv) {
|
|
44
55
|
return new Promise((resolve, reject) => {
|
|
45
56
|
const p = child_process.spawn("terraform", args, { cwd, stdio: "inherit", env: Object.assign(Object.assign({}, process.env), customEnv) });
|
|
46
57
|
p.on("close", (code) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terraform.js","sourceRoot":"","sources":["terraform.ts"],"names":[],"mappings":";;;;AAAA,qEAA+C;AAC/C,2DAAyF;AACzF,mDAA6B;AAE7B,yDAAmC;AACnC,qDAA+B;AAC/B,mDAA6B;
|
|
1
|
+
{"version":3,"file":"terraform.js","sourceRoot":"","sources":["terraform.ts"],"names":[],"mappings":"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"}
|
package/lib/core/terraform.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { TunnelProxyCreatingRequest } from "../domain/TunnelProxyOperations";
|
|
|
5
5
|
import * as process from "process";
|
|
6
6
|
import * as fs from "fs-extra";
|
|
7
7
|
import * as path from "path";
|
|
8
|
+
import promiseRetry from "promise-retry";
|
|
8
9
|
|
|
9
10
|
export async function apply(
|
|
10
11
|
request: TunnelProxyCreatingRequest,
|
|
@@ -12,7 +13,7 @@ export async function apply(
|
|
|
12
13
|
credentials: AliyunCredentials
|
|
13
14
|
): Promise<{ address: string; bucketDomain: string }> {
|
|
14
15
|
await init(request, workdir);
|
|
15
|
-
await
|
|
16
|
+
await provisioningRetry(["apply", "-auto-approve"], workdir, asTerraformEnvironmentVariables(credentials));
|
|
16
17
|
return {
|
|
17
18
|
address: await inspecting(["output", "-raw", "address"], workdir),
|
|
18
19
|
bucketDomain: await inspecting(["output", "-raw", "bucket_domain_name"], workdir),
|
|
@@ -24,7 +25,7 @@ export async function destroy(workdir: string, credentials: AliyunCredentials):
|
|
|
24
25
|
console.log("Tunnel proxy never created, nothing to destroy");
|
|
25
26
|
return;
|
|
26
27
|
}
|
|
27
|
-
await
|
|
28
|
+
await provisioningRetry(["destroy", "-auto-approve"], workdir, asTerraformEnvironmentVariables(credentials));
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
async function init(request: TunnelProxyCreatingRequest, workdir: string): Promise<void> {
|
|
@@ -39,11 +40,21 @@ async function init(request: TunnelProxyCreatingRequest, workdir: string): Promi
|
|
|
39
40
|
});
|
|
40
41
|
if (!(await fs.pathExists(path.join(workdir, ".terraform")))) {
|
|
41
42
|
await fs.copy(path.resolve(__dirname, "..", "..", "terraform"), workdir, { overwrite: true, recursive: true });
|
|
42
|
-
await
|
|
43
|
+
await provisioningRetry(["init"], workdir);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
async function
|
|
47
|
+
async function provisioningRetry(args: string[], cwd: string, customEnv: Record<string, string> = {}): Promise<void> {
|
|
48
|
+
await promiseRetry(async (retry) => {
|
|
49
|
+
try {
|
|
50
|
+
await provisioning(args, cwd, customEnv);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
retry(error);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function provisioning(args: string[], cwd: string, customEnv: Record<string, string>): Promise<void> {
|
|
47
58
|
return new Promise<void>((resolve, reject) => {
|
|
48
59
|
const p = child_process.spawn("terraform", args, { cwd, stdio: "inherit", env: { ...process.env, ...customEnv } });
|
|
49
60
|
p.on("close", (code) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Clash.d.ts","sourceRoot":"","sources":["Clash.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,oBAAY,yBAAyB,GAAG,YAAY,GAAG;IACrD,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,yBAAyB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"Clash.d.ts","sourceRoot":"","sources":["Clash.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD,oBAAY,yBAAyB,GAAG,YAAY,GAAG;IACrD,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,yBAAyB,GAAG,MAAM,CA0B/E"}
|
package/lib/domain/Clash.js
CHANGED
|
@@ -7,10 +7,19 @@ function generateConfigFrom(endpoints) {
|
|
|
7
7
|
return yaml_1.default.stringify({
|
|
8
8
|
port: 7890,
|
|
9
9
|
"socks-port": 7891,
|
|
10
|
-
|
|
10
|
+
"redir-port": 7892,
|
|
11
|
+
"tproxy-port": 7893,
|
|
12
|
+
"mixed-port": 7890,
|
|
13
|
+
mode: "rule",
|
|
14
|
+
dns: {
|
|
15
|
+
enable: true,
|
|
16
|
+
listen: "0.0.0.0:53",
|
|
17
|
+
"enhanced-mode": "redir-host",
|
|
18
|
+
nameserver: ["223.5.5.5", "119.29.29.29", "114.114.114.114", "tls://dns.rubyfish.cn:853"],
|
|
19
|
+
},
|
|
11
20
|
proxies: [
|
|
12
21
|
{
|
|
13
|
-
name: "
|
|
22
|
+
name: "auto",
|
|
14
23
|
type: "ss",
|
|
15
24
|
server: endpoints.address,
|
|
16
25
|
port: endpoints.port,
|
|
@@ -18,6 +27,7 @@ function generateConfigFrom(endpoints) {
|
|
|
18
27
|
password: endpoints.password,
|
|
19
28
|
},
|
|
20
29
|
],
|
|
30
|
+
rules: ["DOMAIN-SUFFIX,google.com,auto", "DOMAIN,ad.com,REJECT", "GEOIP,CN,DIRECT", "MATCH,auto"],
|
|
21
31
|
});
|
|
22
32
|
}
|
|
23
33
|
exports.generateConfigFrom = generateConfigFrom;
|
package/lib/domain/Clash.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Clash.js","sourceRoot":"","sources":["Clash.ts"],"names":[],"mappings":";;;;AAAA,wDAAwB;AAOxB,SAAgB,kBAAkB,CAAC,SAAoC;IACrE,OAAO,cAAI,CAAC,SAAS,CAAC;QACpB,IAAI,EAAE,IAAI;QACV,YAAY,EAAE,IAAI;QAClB,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"Clash.js","sourceRoot":"","sources":["Clash.ts"],"names":[],"mappings":";;;;AAAA,wDAAwB;AAOxB,SAAgB,kBAAkB,CAAC,SAAoC;IACrE,OAAO,cAAI,CAAC,SAAS,CAAC;QACpB,IAAI,EAAE,IAAI;QACV,YAAY,EAAE,IAAI;QAClB,YAAY,EAAE,IAAI;QAClB,aAAa,EAAE,IAAI;QACnB,YAAY,EAAE,IAAI;QAClB,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE;YACH,MAAM,EAAE,IAAI;YACZ,MAAM,EAAE,YAAY;YACpB,eAAe,EAAE,YAAY;YAC7B,UAAU,EAAE,CAAC,WAAW,EAAE,cAAc,EAAE,iBAAiB,EAAE,2BAA2B,CAAC;SAC1F;QACD,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI;gBACV,MAAM,EAAE,SAAS,CAAC,OAAO;gBACzB,IAAI,EAAE,SAAS,CAAC,IAAI;gBACpB,MAAM,EAAE,SAAS,CAAC,mBAAmB;gBACrC,QAAQ,EAAE,SAAS,CAAC,QAAQ;aAC7B;SACF;QACD,KAAK,EAAE,CAAC,+BAA+B,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,YAAY,CAAC;KAClG,CAAC,CAAC;AACL,CAAC;AA1BD,gDA0BC"}
|
package/lib/domain/Clash.ts
CHANGED
|
@@ -9,10 +9,19 @@ export function generateConfigFrom(endpoints: TunnelProxyConnectionInfo): string
|
|
|
9
9
|
return yaml.stringify({
|
|
10
10
|
port: 7890,
|
|
11
11
|
"socks-port": 7891,
|
|
12
|
-
|
|
12
|
+
"redir-port": 7892,
|
|
13
|
+
"tproxy-port": 7893,
|
|
14
|
+
"mixed-port": 7890,
|
|
15
|
+
mode: "rule",
|
|
16
|
+
dns: {
|
|
17
|
+
enable: true,
|
|
18
|
+
listen: "0.0.0.0:53",
|
|
19
|
+
"enhanced-mode": "redir-host",
|
|
20
|
+
nameserver: ["223.5.5.5", "119.29.29.29", "114.114.114.114", "tls://dns.rubyfish.cn:853"],
|
|
21
|
+
},
|
|
13
22
|
proxies: [
|
|
14
23
|
{
|
|
15
|
-
name: "
|
|
24
|
+
name: "auto",
|
|
16
25
|
type: "ss",
|
|
17
26
|
server: endpoints.address,
|
|
18
27
|
port: endpoints.port,
|
|
@@ -20,5 +29,6 @@ export function generateConfigFrom(endpoints: TunnelProxyConnectionInfo): string
|
|
|
20
29
|
password: endpoints.password,
|
|
21
30
|
},
|
|
22
31
|
],
|
|
32
|
+
rules: ["DOMAIN-SUFFIX,google.com,auto", "DOMAIN,ad.com,REJECT", "GEOIP,CN,DIRECT", "MATCH,auto"],
|
|
23
33
|
});
|
|
24
34
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fanqiang",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Tunnel Proxy Auto Deployment",
|
|
5
5
|
"bin": "./bin/fanqiang.js",
|
|
6
6
|
"scripts": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"files": [
|
|
24
24
|
"/bin",
|
|
25
25
|
"/lib",
|
|
26
|
-
"/
|
|
26
|
+
"/terraform",
|
|
27
27
|
"index.*"
|
|
28
28
|
],
|
|
29
29
|
"homepage": "https://github.com/zhifanz/fanqiang#readme",
|
|
@@ -32,14 +32,11 @@
|
|
|
32
32
|
"@commitlint/config-conventional": "^12.1.4",
|
|
33
33
|
"@semantic-release/changelog": "^5.0.1",
|
|
34
34
|
"@semantic-release/git": "^9.0.0",
|
|
35
|
-
"@types/ali-oss": "^6.0.10",
|
|
36
35
|
"@types/fs-extra": "^9.0.12",
|
|
37
36
|
"@types/lodash": "^4.14.171",
|
|
38
37
|
"@types/mocha": "^8.2.3",
|
|
39
|
-
"@types/netmask": "^1.0.30",
|
|
40
38
|
"@types/node": "^14.14.31",
|
|
41
|
-
"@types/
|
|
42
|
-
"@types/tmp": "^0.2.1",
|
|
39
|
+
"@types/promise-retry": "^1.1.3",
|
|
43
40
|
"@types/yargs": "^17.0.2",
|
|
44
41
|
"@typescript-eslint/eslint-plugin": "^4.28.2",
|
|
45
42
|
"@typescript-eslint/parser": "^4.28.2",
|
|
@@ -62,18 +59,12 @@
|
|
|
62
59
|
},
|
|
63
60
|
"dependencies": {
|
|
64
61
|
"@alicloud/credentials": "^2.1.1",
|
|
65
|
-
"@alicloud/openapi-client": "^0.3.3",
|
|
66
|
-
"@alicloud/tea-typescript": "^1.7.1",
|
|
67
|
-
"@aws-sdk/client-iam": "^3.27.0",
|
|
68
|
-
"@aws-sdk/client-lightsail": "^3.21.0",
|
|
69
62
|
"@aws-sdk/client-s3": "^3.27.0",
|
|
70
|
-
"
|
|
63
|
+
"@aws-sdk/node-config-provider": "^3.29.0",
|
|
71
64
|
"dotenv": "^10.0.0",
|
|
72
65
|
"fs-extra": "^10.0.0",
|
|
73
66
|
"lodash": "^4.17.21",
|
|
74
|
-
"
|
|
75
|
-
"qs": "^6.10.1",
|
|
76
|
-
"tmp": "^0.2.1",
|
|
67
|
+
"promise-retry": "^2.0.1",
|
|
77
68
|
"tslib": "^2.3.0",
|
|
78
69
|
"yaml": "^1.10.2",
|
|
79
70
|
"yargs": "^17.0.1"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
PORT=${port}
|
|
3
|
+
ENCRYPTION_ALGORITHM=${encryption_algorithm}
|
|
4
|
+
PASSWORD=${password}
|
|
5
|
+
|
|
6
|
+
curl --location -o /tmp/shadowsocks.tar.xz https://github.com/shadowsocks/shadowsocks-rust/releases/download/v1.11.1/shadowsocks-v1.11.1.x86_64-unknown-linux-gnu.tar.xz
|
|
7
|
+
mkdir /var/lib/shadowsocks
|
|
8
|
+
tar -x -f /tmp/shadowsocks.tar.xz -C /var/lib/shadowsocks
|
|
9
|
+
/var/lib/shadowsocks/ssserver -s "[::]:$PORT" -m "$ENCRYPTION_ALGORITHM" -k "$PASSWORD" -d
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
PROXY_ADDRESS=${proxy_address}
|
|
4
|
+
PROXY_PORT=${proxy_port}
|
|
5
|
+
ELASTIC_IP_ALLOCATION_ID=${elastic_ip_allocation_id}
|
|
6
|
+
REGION=${region}
|
|
7
|
+
RAM_ROLE_NAME=${ram_role_name}
|
|
8
|
+
|
|
9
|
+
aliyun configure set --region $REGION --mode EcsRamRole --ram-role-name $RAM_ROLE_NAME
|
|
10
|
+
aliyun --endpoint "vpc-vpc.$REGION.aliyuncs.com" vpc UnassociateEipAddress --AllocationId $ELASTIC_IP_ALLOCATION_ID || true
|
|
11
|
+
aliyun --endpoint "vpc-vpc.$REGION.aliyuncs.com" vpc AssociateEipAddress --AllocationId $ELASTIC_IP_ALLOCATION_ID --InstanceId "i-$${HOSTNAME: 2: 20}"
|
|
12
|
+
sleep 5
|
|
13
|
+
|
|
14
|
+
yum install nginx -y &>> ~/cloud-init.log
|
|
15
|
+
sleep 5
|
|
16
|
+
yum install nginx-all-modules -y &>> ~/cloud-init.log
|
|
17
|
+
|
|
18
|
+
cat > /etc/nginx/nginx.conf <<EOF
|
|
19
|
+
user nginx;
|
|
20
|
+
worker_processes auto;
|
|
21
|
+
error_log /var/log/nginx/error.log;
|
|
22
|
+
pid /run/nginx.pid;
|
|
23
|
+
|
|
24
|
+
include /usr/share/nginx/modules/*.conf;
|
|
25
|
+
|
|
26
|
+
events {
|
|
27
|
+
worker_connections 1024;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
stream {
|
|
31
|
+
server {
|
|
32
|
+
listen $PROXY_PORT;
|
|
33
|
+
proxy_pass $PROXY_ADDRESS:$PROXY_PORT;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
EOF
|
|
37
|
+
|
|
38
|
+
systemctl start nginx
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
terraform {
|
|
2
|
+
required_providers {
|
|
3
|
+
aws = {
|
|
4
|
+
source = "hashicorp/aws"
|
|
5
|
+
version = "~> 3.0"
|
|
6
|
+
}
|
|
7
|
+
alicloud = {
|
|
8
|
+
source = "aliyun/alicloud"
|
|
9
|
+
version = "1.134.0"
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
provider "aws" {
|
|
14
|
+
region = var.proxy_region
|
|
15
|
+
}
|
|
16
|
+
provider "alicloud" {
|
|
17
|
+
region = var.tunnel_region
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
locals {
|
|
21
|
+
instance_type = "ecs.t5-lc2m1.nano"
|
|
22
|
+
image_id = "aliyun_2_1903_x64_20G_alibase_20210726.vhd"
|
|
23
|
+
internet_max_bandwidth_out = 100
|
|
24
|
+
max_price_per_hour = "0.05"
|
|
25
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
resource "aws_lightsail_instance" "default" {
|
|
2
|
+
availability_zone = data.aws_availability_zones.default.names[0]
|
|
3
|
+
blueprint_id = "centos_8"
|
|
4
|
+
bundle_id = "nano_2_0"
|
|
5
|
+
name = "fanqiang"
|
|
6
|
+
user_data = templatefile("${path.root}/cloud-init/proxy-init.sh", {
|
|
7
|
+
port = var.port,
|
|
8
|
+
encryption_algorithm = var.encryption_algorithm,
|
|
9
|
+
password = var.password
|
|
10
|
+
})
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
resource "aws_lightsail_instance_public_ports" "default" {
|
|
14
|
+
instance_name = aws_lightsail_instance.default.name
|
|
15
|
+
|
|
16
|
+
dynamic "port_info" {
|
|
17
|
+
for_each = [var.port, 22]
|
|
18
|
+
content {
|
|
19
|
+
protocol = "tcp"
|
|
20
|
+
from_port = port_info.value
|
|
21
|
+
to_port = port_info.value
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
resource "aws_s3_bucket" "default" {
|
|
27
|
+
bucket = var.bucket
|
|
28
|
+
acl = "public-read"
|
|
29
|
+
force_destroy = true
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
data "aws_availability_zones" "default" {
|
|
33
|
+
state = "available"
|
|
34
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
resource "alicloud_vpc" "default" {
|
|
2
|
+
cidr_block = "192.168.0.0/16"
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
resource "alicloud_vswitch" "default" {
|
|
6
|
+
count = length(data.alicloud_zones.default.ids)
|
|
7
|
+
zone_id = data.alicloud_zones.default.ids[count.index]
|
|
8
|
+
cidr_block = "192.168.${count.index}.0/24"
|
|
9
|
+
vpc_id = alicloud_vpc.default.id
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
resource "alicloud_security_group" "default" {
|
|
13
|
+
vpc_id = alicloud_vpc.default.id
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
resource "alicloud_security_group_rule" "default" {
|
|
17
|
+
for_each = toset([tostring(var.port), "22"])
|
|
18
|
+
security_group_id = alicloud_security_group.default.id
|
|
19
|
+
ip_protocol = "tcp"
|
|
20
|
+
type = "ingress"
|
|
21
|
+
cidr_ip = "0.0.0.0/0"
|
|
22
|
+
port_range = "${each.key}/${each.key}"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
resource "alicloud_auto_provisioning_group" "default" {
|
|
26
|
+
launch_template_id = alicloud_ecs_launch_template.default.id
|
|
27
|
+
total_target_capacity = "1"
|
|
28
|
+
pay_as_you_go_target_capacity = "0"
|
|
29
|
+
spot_target_capacity = "1"
|
|
30
|
+
auto_provisioning_group_type = "maintain"
|
|
31
|
+
spot_allocation_strategy = "lowest-price"
|
|
32
|
+
spot_instance_interruption_behavior = "terminate"
|
|
33
|
+
excess_capacity_termination_policy = "termination"
|
|
34
|
+
terminate_instances = true
|
|
35
|
+
dynamic "launch_template_config" {
|
|
36
|
+
for_each = alicloud_vswitch.default.*.id
|
|
37
|
+
content {
|
|
38
|
+
instance_type = local.instance_type
|
|
39
|
+
max_price = local.max_price_per_hour
|
|
40
|
+
vswitch_id = launch_template_config.value
|
|
41
|
+
weighted_capacity = "1"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
resource "alicloud_ecs_launch_template" "default" {
|
|
47
|
+
launch_template_name = "fanqiang"
|
|
48
|
+
image_id = local.image_id
|
|
49
|
+
instance_charge_type = "PostPaid"
|
|
50
|
+
instance_type = local.instance_type
|
|
51
|
+
security_group_id = alicloud_security_group.default.id
|
|
52
|
+
key_pair_name = length(data.alicloud_ecs_key_pairs.default) > 0 ? data.alicloud_ecs_key_pairs.default.names[0] : null
|
|
53
|
+
spot_duration = 0
|
|
54
|
+
spot_strategy = "SpotAsPriceGo"
|
|
55
|
+
ram_role_name = alicloud_ram_role.default.id
|
|
56
|
+
user_data = base64encode(templatefile("${path.root}/cloud-init/tunnel-init.sh", {
|
|
57
|
+
proxy_port = var.port,
|
|
58
|
+
proxy_address = aws_lightsail_instance.default.public_ip_address,
|
|
59
|
+
elastic_ip_allocation_id = alicloud_eip_address.default.id,
|
|
60
|
+
region = var.tunnel_region
|
|
61
|
+
ram_role_name = alicloud_ram_role.default.id
|
|
62
|
+
}))
|
|
63
|
+
system_disk {
|
|
64
|
+
category = "cloud_efficiency"
|
|
65
|
+
delete_with_instance = true
|
|
66
|
+
size = 40
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
data "alicloud_ecs_key_pairs" "default" {}
|
|
71
|
+
|
|
72
|
+
resource "alicloud_ram_role" "default" {
|
|
73
|
+
name = "FangqiangEcsEipAccessRole"
|
|
74
|
+
document = <<EOF
|
|
75
|
+
{
|
|
76
|
+
"Statement": [
|
|
77
|
+
{
|
|
78
|
+
"Action": "sts:AssumeRole",
|
|
79
|
+
"Effect": "Allow",
|
|
80
|
+
"Principal": {
|
|
81
|
+
"Service": [
|
|
82
|
+
"ecs.aliyuncs.com"
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
"Version": "1"
|
|
88
|
+
}
|
|
89
|
+
EOF
|
|
90
|
+
force = true
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
resource "alicloud_ram_role_policy_attachment" "default" {
|
|
94
|
+
policy_name = "AliyunEIPFullAccess"
|
|
95
|
+
policy_type = "System"
|
|
96
|
+
role_name = alicloud_ram_role.default.id
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
resource "alicloud_eip_address" "default" {
|
|
100
|
+
bandwidth = local.internet_max_bandwidth_out
|
|
101
|
+
internet_charge_type = "PayByTraffic"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
data "alicloud_zones" "default" {}
|
|
105
|
+
|
|
106
|
+
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
variable "proxy_region" {
|
|
2
|
+
type = string
|
|
3
|
+
}
|
|
4
|
+
variable "tunnel_region" {
|
|
5
|
+
type = string
|
|
6
|
+
}
|
|
7
|
+
variable "port" {
|
|
8
|
+
type = number
|
|
9
|
+
}
|
|
10
|
+
variable "password" {
|
|
11
|
+
type = string
|
|
12
|
+
}
|
|
13
|
+
variable "encryption_algorithm" {
|
|
14
|
+
type = string
|
|
15
|
+
}
|
|
16
|
+
variable "bucket" {
|
|
17
|
+
type = string
|
|
18
|
+
}
|