diff --git a/.github/update.log b/.github/update.log index 44b98de2ce..166030a93f 100644 --- a/.github/update.log +++ b/.github/update.log @@ -829,3 +829,4 @@ Update On Fri Nov 15 19:36:45 CET 2024 Update On Sat Nov 16 19:33:37 CET 2024 Update On Sun Nov 17 19:33:17 CET 2024 Update On Mon Nov 18 19:38:02 CET 2024 +Update On Tue Nov 19 19:38:38 CET 2024 diff --git a/clash-nyanpasu/frontend/nyanpasu/package.json b/clash-nyanpasu/frontend/nyanpasu/package.json index 392499c68d..411db8727b 100644 --- a/clash-nyanpasu/frontend/nyanpasu/package.json +++ b/clash-nyanpasu/frontend/nyanpasu/package.json @@ -81,7 +81,7 @@ "sass": "1.81.0", "shiki": "1.23.1", "tailwindcss-textshadow": "2.1.3", - "unplugin-auto-import": "0.18.4", + "unplugin-auto-import": "0.18.5", "unplugin-icons": "0.20.1", "validator": "13.12.0", "vite": "5.4.11", diff --git a/clash-nyanpasu/manifest/version.json b/clash-nyanpasu/manifest/version.json index 1038f96dc6..34a8b3d52d 100644 --- a/clash-nyanpasu/manifest/version.json +++ b/clash-nyanpasu/manifest/version.json @@ -2,7 +2,7 @@ "manifest_version": 1, "latest": { "mihomo": "v1.18.10", - "mihomo_alpha": "alpha-25b3c86", + "mihomo_alpha": "alpha-671d901", "clash_rs": "v0.7.1", "clash_premium": "2023-09-05-gdcc8d87", "clash_rs_alpha": "0.7.1-alpha+sha.5f2306a" @@ -69,5 +69,5 @@ "linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf" } }, - "updated_at": "2024-11-17T22:20:55.383Z" + "updated_at": "2024-11-18T22:20:52.531Z" } diff --git a/clash-nyanpasu/package.json b/clash-nyanpasu/package.json index 8b31100600..e1911cd5ef 100644 --- a/clash-nyanpasu/package.json +++ b/clash-nyanpasu/package.json @@ -53,7 +53,7 @@ "prepare:preview": "tsx scripts/prepare-preview.ts" }, "dependencies": { - "husky": "9.1.6", + "husky": "9.1.7", "lodash-es": "4.17.21" }, "devDependencies": { @@ -64,8 +64,8 @@ "@types/fs-extra": "11.0.4", "@types/lodash-es": "4.17.12", "@types/node": "22.9.0", - "@typescript-eslint/eslint-plugin": "8.14.0", - "@typescript-eslint/parser": "8.14.0", + "@typescript-eslint/eslint-plugin": "8.15.0", + "@typescript-eslint/parser": "8.15.0", "autoprefixer": "10.4.20", "conventional-changelog-conventionalcommits": "8.0.0", "cross-env": "7.0.3", diff --git a/clash-nyanpasu/pnpm-lock.yaml b/clash-nyanpasu/pnpm-lock.yaml index b54448c3b0..488f504cc5 100644 --- a/clash-nyanpasu/pnpm-lock.yaml +++ b/clash-nyanpasu/pnpm-lock.yaml @@ -14,8 +14,8 @@ importers: .: dependencies: husky: - specifier: 9.1.6 - version: 9.1.6 + specifier: 9.1.7 + version: 9.1.7 lodash-es: specifier: 4.17.21 version: 4.17.21 @@ -42,11 +42,11 @@ importers: specifier: 22.9.0 version: 22.9.0 '@typescript-eslint/eslint-plugin': - specifier: 8.14.0 - version: 8.14.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3) + specifier: 8.15.0 + version: 8.15.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3) '@typescript-eslint/parser': - specifier: 8.14.0 - version: 8.14.0(eslint@8.57.1)(typescript@5.6.3) + specifier: 8.15.0 + version: 8.15.0(eslint@8.57.1)(typescript@5.6.3) autoprefixer: specifier: 10.4.20 version: 10.4.20(postcss@8.4.49) @@ -67,16 +67,16 @@ importers: version: 9.1.0(eslint@8.57.1) eslint-config-standard: specifier: 17.1.0 - version: 17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint-plugin-n@17.13.2(eslint@8.57.1))(eslint-plugin-promise@7.1.0(eslint@8.57.1))(eslint@8.57.1) + version: 17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint-plugin-n@17.13.2(eslint@8.57.1))(eslint-plugin-promise@7.1.0(eslint@8.57.1))(eslint@8.57.1) eslint-import-resolver-alias: specifier: 1.1.2 - version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)) + version: 1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)) eslint-plugin-html: specifier: 8.1.2 version: 8.1.2 eslint-plugin-import: specifier: 2.31.0 - version: 2.31.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1) + version: 2.31.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1) eslint-plugin-n: specifier: 17.13.2 version: 17.13.2(eslint@8.57.1) @@ -392,8 +392,8 @@ importers: specifier: 2.1.3 version: 2.1.3 unplugin-auto-import: - specifier: 0.18.4 - version: 0.18.4(rollup@4.21.0) + specifier: 0.18.5 + version: 0.18.5(rollup@4.21.0) unplugin-icons: specifier: 0.20.1 version: 0.20.1(@svgr/core@8.1.0(typescript@5.6.3))(webpack-sources@3.2.3) @@ -556,8 +556,8 @@ importers: specifier: 7.4.3 version: 7.4.3 telegram: - specifier: 2.26.6 - version: 2.26.6 + specifier: 2.26.8 + version: 2.26.8 undici: specifier: 6.21.0 version: 6.21.0 @@ -3106,8 +3106,8 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.14.0': - resolution: {integrity: sha512-tqp8H7UWFaZj0yNO6bycd5YjMwxa6wIHOLZvWPkidwbgLCsBMetQoGj7DPuAlWa2yGO3H48xmPwjhsSPPCGU5w==} + '@typescript-eslint/eslint-plugin@8.15.0': + resolution: {integrity: sha512-+zkm9AR1Ds9uLWN3fkoeXgFppaQ+uEVtfOV62dDmsy9QCNqlRHWNEck4yarvRNrvRcHQLGfqBNui3cimoz8XAg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 @@ -3117,8 +3117,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@8.14.0': - resolution: {integrity: sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==} + '@typescript-eslint/parser@8.15.0': + resolution: {integrity: sha512-7n59qFpghG4uazrF9qtGKBZXn7Oz4sOMm8dwNWDQY96Xlm2oX67eipqcblDj+oY1lLCbf1oltMZFpUso66Kl1A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3127,40 +3127,45 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@8.14.0': - resolution: {integrity: sha512-aBbBrnW9ARIDn92Zbo7rguLnqQ/pOrUguVpbUwzOhkFg2npFDwTgPGqFqE0H5feXcOoJOfX3SxlJaKEVtq54dw==} + '@typescript-eslint/scope-manager@8.15.0': + resolution: {integrity: sha512-QRGy8ADi4J7ii95xz4UoiymmmMd/zuy9azCaamnZ3FM8T5fZcex8UfJcjkiEZjJSztKfEBe3dZ5T/5RHAmw2mA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@8.14.0': - resolution: {integrity: sha512-Xcz9qOtZuGusVOH5Uk07NGs39wrKkf3AxlkK79RBK6aJC1l03CobXjJbwBPSidetAOV+5rEVuiT1VSBUOAsanQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/types@8.14.0': - resolution: {integrity: sha512-yjeB9fnO/opvLJFAsPNYlKPnEM8+z4og09Pk504dkqonT02AyL5Z9SSqlE0XqezS93v6CXn49VHvB2G7XSsl0g==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@typescript-eslint/typescript-estree@8.14.0': - resolution: {integrity: sha512-OPXPLYKGZi9XS/49rdaCbR5j/S14HazviBlUQFvSKz3npr3NikF+mrgK7CFVur6XEt95DZp/cmke9d5i3vtVnQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/utils@8.14.0': - resolution: {integrity: sha512-OGqj6uB8THhrHj0Fk27DcHPojW7zKwKkPmHXHvQ58pLYp4hy8CSUdTKykKeh+5vFqTTVmjz0zCOOPKRovdsgHA==} + '@typescript-eslint/type-utils@8.15.0': + resolution: {integrity: sha512-UU6uwXDoI3JGSXmcdnP5d8Fffa2KayOhUUqr/AiBnG1Gl7+7ut/oyagVeSkh7bxQ0zSXV9ptRh/4N15nkCqnpw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true - '@typescript-eslint/visitor-keys@8.14.0': - resolution: {integrity: sha512-vG0XZo8AdTH9OE6VFRwAZldNc7qtJ/6NLGWak+BtENuEUXGZgFpihILPiBvKXvJ2nFu27XNGC6rKiwuaoMbYzQ==} + '@typescript-eslint/types@8.15.0': + resolution: {integrity: sha512-n3Gt8Y/KyJNe0S3yDCD2RVKrHBC4gTUcLTebVBXacPy091E6tNspFLKRXlk3hwT4G55nfr1n2AdFqi/XMxzmPQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.15.0': + resolution: {integrity: sha512-1eMp2JgNec/niZsR7ioFBlsh/Fk0oJbhaqO0jRyQBMgkz7RrFfkqF9lYYmBoGBaSiLnu8TAPQTwoTUiSTUW9dg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@8.15.0': + resolution: {integrity: sha512-k82RI9yGhr0QM3Dnq+egEpz9qB6Un+WLYhmoNcvl8ltMEededhh7otBVVIDDsEEttauwdY/hQoSsOv13lxrFzQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/visitor-keys@8.15.0': + resolution: {integrity: sha512-h8vYOulWec9LhpwfAdZf2bjr8xIp0KNKnpgqSz0qqYYKAW/QZKw3ktRndbiAtUz4acH4QLQavwZBYCc0wulA/Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@ungap/structured-clone@1.2.0': @@ -3712,9 +3717,6 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - confbox@0.1.7: - resolution: {integrity: sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==} - confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} @@ -4435,6 +4437,10 @@ packages: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint@8.57.1: resolution: {integrity: sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4871,8 +4877,8 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} - husky@9.1.6: - resolution: {integrity: sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==} + husky@9.1.7: + resolution: {integrity: sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==} engines: {node: '>=18'} hasBin: true @@ -5493,6 +5499,9 @@ packages: magic-string@0.30.12: resolution: {integrity: sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==} + magic-string@0.30.13: + resolution: {integrity: sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g==} + make-dir@1.3.0: resolution: {integrity: sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==} engines: {node: '>=4'} @@ -6084,9 +6093,6 @@ packages: resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} engines: {node: '>= 6'} - pkg-types@1.2.0: - resolution: {integrity: sha512-+ifYuSSqOQ8CqP4MbZA5hDpb97n3E8SVWdJe+Wms9kj745lmd3b7EZJiqvmLwAlmRfjrI7Hi5z3kdBJ93lFNPA==} - pkg-types@1.2.1: resolution: {integrity: sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==} @@ -7194,8 +7200,8 @@ packages: resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} engines: {node: '>=18'} - telegram@2.26.6: - resolution: {integrity: sha512-2nZGL3ADRnEoWV0NMH4E+rhPFSD03HQ1ugTHJqpZR2l0iPz5m8TfD+fWoicfe8sltpCcj7nLmNsiEf5ExX/eGA==} + telegram@2.26.8: + resolution: {integrity: sha512-5sIb43Fd7HxjXQZqKWMhNTmdMOlG3QkuhR2xPleUA5B8BxOZl9IwrDwFdiC7aezGVTcD6oJ1d4cloUySjmCX/A==} term-size@1.2.0: resolution: {integrity: sha512-7dPUZQGy/+m3/wjVz3ZW5dobSoD/02NxJpoXUX0WIyjfVS3l0c+b/+9phIDFA7FHzkYtwtMFgeGZ/Y8jVTeqQQ==} @@ -7443,8 +7449,8 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - unplugin-auto-import@0.18.4: - resolution: {integrity: sha512-I+QAZPQn5lfH3HYa6HTgpcz30XGY0H1g6QenEB+sgBjgfvgJ33UI907dlNkgOSm/CFHZyNmTKVHf+O2qTnfNKw==} + unplugin-auto-import@0.18.5: + resolution: {integrity: sha512-ZUnayBRlOwNuN9hrM1PymSZK5qDEI8heDD0E3U8Tq4FS6bUxd9VMfJ8tCwWTG5ir6g1yThe/4SVHbFUZQwplOw==} engines: {node: '>=14'} peerDependencies: '@nuxt/kit': ^3.2.2 @@ -10535,14 +10541,14 @@ snapshots: '@types/node': 22.9.0 optional: true - '@typescript-eslint/eslint-plugin@8.14.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)': + '@typescript-eslint/eslint-plugin@8.15.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.14.0(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/scope-manager': 8.14.0 - '@typescript-eslint/type-utils': 8.14.0(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/utils': 8.14.0(eslint@8.57.1)(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 8.14.0 + '@typescript-eslint/parser': 8.15.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/type-utils': 8.15.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/utils': 8.15.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.15.0 eslint: 8.57.1 graphemer: 1.4.0 ignore: 5.3.2 @@ -10553,12 +10559,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3)': + '@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: - '@typescript-eslint/scope-manager': 8.14.0 - '@typescript-eslint/types': 8.14.0 - '@typescript-eslint/typescript-estree': 8.14.0(typescript@5.6.3) - '@typescript-eslint/visitor-keys': 8.14.0 + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3) + '@typescript-eslint/visitor-keys': 8.15.0 debug: 4.3.7 eslint: 8.57.1 optionalDependencies: @@ -10566,29 +10572,29 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.14.0': + '@typescript-eslint/scope-manager@8.15.0': dependencies: - '@typescript-eslint/types': 8.14.0 - '@typescript-eslint/visitor-keys': 8.14.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/visitor-keys': 8.15.0 - '@typescript-eslint/type-utils@8.14.0(eslint@8.57.1)(typescript@5.6.3)': + '@typescript-eslint/type-utils@8.15.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: - '@typescript-eslint/typescript-estree': 8.14.0(typescript@5.6.3) - '@typescript-eslint/utils': 8.14.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3) + '@typescript-eslint/utils': 8.15.0(eslint@8.57.1)(typescript@5.6.3) debug: 4.3.7 + eslint: 8.57.1 ts-api-utils: 1.3.0(typescript@5.6.3) optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: - - eslint - supports-color - '@typescript-eslint/types@8.14.0': {} + '@typescript-eslint/types@8.15.0': {} - '@typescript-eslint/typescript-estree@8.14.0(typescript@5.6.3)': + '@typescript-eslint/typescript-estree@8.15.0(typescript@5.6.3)': dependencies: - '@typescript-eslint/types': 8.14.0 - '@typescript-eslint/visitor-keys': 8.14.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/visitor-keys': 8.15.0 debug: 4.3.7 fast-glob: 3.3.2 is-glob: 4.0.3 @@ -10600,21 +10606,22 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.14.0(eslint@8.57.1)(typescript@5.6.3)': + '@typescript-eslint/utils@8.15.0(eslint@8.57.1)(typescript@5.6.3)': dependencies: '@eslint-community/eslint-utils': 4.4.1(eslint@8.57.1) - '@typescript-eslint/scope-manager': 8.14.0 - '@typescript-eslint/types': 8.14.0 - '@typescript-eslint/typescript-estree': 8.14.0(typescript@5.6.3) + '@typescript-eslint/scope-manager': 8.15.0 + '@typescript-eslint/types': 8.15.0 + '@typescript-eslint/typescript-estree': 8.15.0(typescript@5.6.3) eslint: 8.57.1 + optionalDependencies: + typescript: 5.6.3 transitivePeerDependencies: - supports-color - - typescript - '@typescript-eslint/visitor-keys@8.14.0': + '@typescript-eslint/visitor-keys@8.15.0': dependencies: - '@typescript-eslint/types': 8.14.0 - eslint-visitor-keys: 3.4.3 + '@typescript-eslint/types': 8.15.0 + eslint-visitor-keys: 4.2.0 '@ungap/structured-clone@1.2.0': {} @@ -11231,8 +11238,6 @@ snapshots: concat-map@0.0.1: {} - confbox@0.1.7: {} - confbox@0.1.8: {} configstore@3.1.5: @@ -11952,16 +11957,16 @@ snapshots: dependencies: eslint: 8.57.1 - eslint-config-standard@17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint-plugin-n@17.13.2(eslint@8.57.1))(eslint-plugin-promise@7.1.0(eslint@8.57.1))(eslint@8.57.1): + eslint-config-standard@17.1.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1))(eslint-plugin-n@17.13.2(eslint@8.57.1))(eslint-plugin-promise@7.1.0(eslint@8.57.1))(eslint@8.57.1): dependencies: eslint: 8.57.1 - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1) eslint-plugin-n: 17.13.2(eslint@8.57.1) eslint-plugin-promise: 7.1.0(eslint@8.57.1) - eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)): + eslint-import-resolver-alias@1.1.2(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1)): dependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1) eslint-import-resolver-node@0.3.9: dependencies: @@ -11971,11 +11976,11 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 8.14.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/parser': 8.15.0(eslint@8.57.1)(typescript@5.6.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: @@ -11992,7 +11997,7 @@ snapshots: dependencies: htmlparser2: 9.1.0 - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -12003,7 +12008,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.14.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -12015,7 +12020,7 @@ snapshots: string.prototype.trimend: 1.0.8 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.14.0(eslint@8.57.1)(typescript@5.6.3) + '@typescript-eslint/parser': 8.15.0(eslint@8.57.1)(typescript@5.6.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack @@ -12091,6 +12096,8 @@ snapshots: eslint-visitor-keys@3.4.3: {} + eslint-visitor-keys@4.2.0: {} + eslint@8.57.1: dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.1) @@ -12649,7 +12656,7 @@ snapshots: human-signals@5.0.0: {} - husky@9.1.6: {} + husky@9.1.7: {} hyphenate-style-name@1.1.0: {} @@ -13104,8 +13111,8 @@ snapshots: local-pkg@0.5.0: dependencies: - mlly: 1.7.1 - pkg-types: 1.2.0 + mlly: 1.7.3 + pkg-types: 1.2.1 locate-path@6.0.0: dependencies: @@ -13192,6 +13199,10 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + magic-string@0.30.13: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + make-dir@1.3.0: dependencies: pify: 3.0.0 @@ -13512,7 +13523,7 @@ snapshots: dependencies: acorn: 8.14.0 pathe: 1.1.2 - pkg-types: 1.2.0 + pkg-types: 1.2.1 ufo: 1.5.4 mlly@1.7.3: @@ -13897,12 +13908,6 @@ snapshots: pirates@4.0.6: {} - pkg-types@1.2.0: - dependencies: - confbox: 0.1.7 - mlly: 1.7.1 - pathe: 1.1.2 - pkg-types@1.2.1: dependencies: confbox: 0.1.8 @@ -15075,7 +15080,7 @@ snapshots: mkdirp: 3.0.1 yallist: 5.0.0 - telegram@2.26.6: + telegram@2.26.8: dependencies: '@cryptography/aes': 0.1.1 async-mutex: 0.3.2 @@ -15314,7 +15319,7 @@ snapshots: estree-walker: 3.0.3 fast-glob: 3.3.2 local-pkg: 0.5.0 - magic-string: 0.30.12 + magic-string: 0.30.13 mlly: 1.7.3 pathe: 1.1.2 pkg-types: 1.2.1 @@ -15366,13 +15371,13 @@ snapshots: universalify@2.0.1: {} - unplugin-auto-import@0.18.4(rollup@4.21.0): + unplugin-auto-import@0.18.5(rollup@4.21.0): dependencies: '@antfu/utils': 0.7.10 '@rollup/pluginutils': 5.1.3(rollup@4.21.0) fast-glob: 3.3.2 local-pkg: 0.5.0 - magic-string: 0.30.12 + magic-string: 0.30.13 minimatch: 9.0.5 unimport: 3.13.2(rollup@4.21.0) unplugin: 1.16.0 diff --git a/clash-nyanpasu/scripts/package.json b/clash-nyanpasu/scripts/package.json index 029a60f494..edea0869b8 100644 --- a/clash-nyanpasu/scripts/package.json +++ b/clash-nyanpasu/scripts/package.json @@ -21,7 +21,7 @@ "octokit": "4.0.2", "picocolors": "1.1.1", "tar": "7.4.3", - "telegram": "2.26.6", + "telegram": "2.26.8", "undici": "6.21.0" } } diff --git a/lede/package/boot/uboot-rockchip/Makefile b/lede/package/boot/uboot-rockchip/Makefile index ad25649706..e3d859079a 100644 --- a/lede/package/boot/uboot-rockchip/Makefile +++ b/lede/package/boot/uboot-rockchip/Makefile @@ -1,3 +1,4 @@ + # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. @@ -38,6 +39,13 @@ define U-Boot/nanopi-r2c-rk3328 friendlyarm_nanopi-r2c endef +define U-Boot/nanopi-r2c-plus-rk3328 + $(U-Boot/rk3328/Default) + NAME:=NanoPi R2C Plus + BUILD_DEVICES:= \ + friendlyarm_nanopi-r2c-plus +endef + define U-Boot/nanopi-r2s-rk3328 $(U-Boot/rk3328/Default) NAME:=NanoPi R2S @@ -406,6 +414,7 @@ UBOOT_TARGETS := \ guangmiao-g4c-rk3399 \ xiaobao-nas-v1-rk3399 \ nanopi-r2c-rk3328 \ + nanopi-r2c-plus-rk3328 \ nanopi-r2s-rk3328 \ nanopi-r2s-plus-rk3328 \ orangepi-r1-plus-rk3328 \ diff --git a/lede/target/linux/ramips/dts/mt7621_huasifei_mt7621dtu.dts b/lede/target/linux/ramips/dts/mt7621_huasifei_mt7621dtu.dts index 9d58b0a749..b80f43c0d8 100644 --- a/lede/target/linux/ramips/dts/mt7621_huasifei_mt7621dtu.dts +++ b/lede/target/linux/ramips/dts/mt7621_huasifei_mt7621dtu.dts @@ -49,7 +49,7 @@ led-cellular-l2 { label = "green:4g"; - gpios = <&gpio 5 GPIO_ACTIVE_LOW>; + gpios = <&gpio 10 GPIO_ACTIVE_LOW>; }; led-cellular-l3 { diff --git a/lede/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds b/lede/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds index a288f0c72c..3428509c52 100644 --- a/lede/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds +++ b/lede/target/linux/ramips/mt7621/base-files/etc/board.d/01_leds @@ -58,6 +58,10 @@ gnubee,gb-pc2) ucidef_set_led_netdev "ethblack_act" "ethblack act" "green:ethblack_act" "ethblack" "tx rx" ucidef_set_led_netdev "ethblue_act" "ethblue act" "green:ethblue_act" "ethblue" "tx rx" ;; +huasifei,mt7621dtu) + ucidef_set_led_switch "lan3" "lan3" "amber:4g" "switch0" "0x08" + ucidef_set_led_switch "lan4" "lan3" "amber:5g" "switch0" "0x10" + ;; huasifei,ws1208v2) ucidef_set_led_netdev "wwan0" "wwan0" "green:cellular" "wwan0" "link tx rx" ;; diff --git a/lede/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds b/lede/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds index 7db3d26457..f53a72ae98 100755 --- a/lede/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds +++ b/lede/target/linux/rockchip/armv8/base-files/etc/board.d/01_leds @@ -10,6 +10,7 @@ board_config_update case $board in friendlyarm,nanopi-r2c|\ +friendlyarm,nanopi-r2c-plus|\ friendlyarm,nanopi-r2s|\ friendlyarm,nanopi-r2s-plus|\ friendlyarm,nanopi-r4s|\ diff --git a/lede/target/linux/rockchip/armv8/base-files/etc/board.d/02_network b/lede/target/linux/rockchip/armv8/base-files/etc/board.d/02_network index c982b66e50..aebbb372f3 100755 --- a/lede/target/linux/rockchip/armv8/base-files/etc/board.d/02_network +++ b/lede/target/linux/rockchip/armv8/base-files/etc/board.d/02_network @@ -14,6 +14,7 @@ rockchip_setup_interfaces() ezpro,mrkaio-m68s|\ ezpro,mrkaio-m68s-plus|\ friendlyarm,nanopi-r2c|\ + friendlyarm,nanopi-r2c-plus|\ friendlyarm,nanopi-r2s|\ friendlyarm,nanopi-r2s-plus|\ friendlyarm,nanopi-r4s|\ @@ -107,6 +108,7 @@ rockchip_setup_macs() firefly,rk3568-roc-pc|\ friendlyarm,nanopc-t6|\ friendlyarm,nanopi-r2c|\ + friendlyarm,nanopi-r2c-plus|\ friendlyarm,nanopi-r2s|\ friendlyarm,nanopi-r2s-plus|\ hinlink,opc-h28k|\ diff --git a/lede/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity b/lede/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity index 7e867fa36c..cc30c5751a 100644 --- a/lede/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity +++ b/lede/target/linux/rockchip/armv8/base-files/etc/hotplug.d/net/40-net-smp-affinity @@ -47,7 +47,9 @@ xunlong,orangepi-5-plus) set_interface_core 4 "eth1" ;; friendlyarm,nanopi-r2c|\ +friendlyarm,nanopi-r2c-plus|\ friendlyarm,nanopi-r2s|\ +friendlyarm,nanopi-r2s-plus|\ xunlong,orangepi-r1-plus|\ xunlong,orangepi-r1-plus-lts) set_interface_core 2 "eth0" diff --git a/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts new file mode 100644 index 0000000000..16a1958e45 --- /dev/null +++ b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2c-plus.dts @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright (c) 2021 FriendlyElec Computer Tech. Co., Ltd. + * (http://www.friendlyarm.com) + * + * Copyright (c) 2023 Tianling Shen + */ + +/dts-v1/; +#include "rk3328-nanopi-r2c.dts" + +/ { + model = "FriendlyElec NanoPi R2C Plus"; + compatible = "friendlyarm,nanopi-r2c-plus", "rockchip,rk3328"; + + aliases { + mmc1 = &emmc; + }; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + max-frequency = <150000000>; + mmc-ddr-1_8v; + mmc-hs200-1_8v; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; + vmmc-supply = <&vcc_io_33>; + vqmmc-supply = <&vcc18_emmc>; + status = "okay"; +}; diff --git a/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts new file mode 100644 index 0000000000..4b9ced6774 --- /dev/null +++ b/lede/target/linux/rockchip/files/arch/arm64/boot/dts/rockchip/rk3328-nanopi-r2s-plus.dts @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * (C) Copyright 2018 FriendlyElec Computer Tech. Co., Ltd. + * (http://www.friendlyarm.com) + * + * (C) Copyright 2016 Rockchip Electronics Co., Ltd + */ + +/dts-v1/; +#include "rk3328-nanopi-r2s.dts" + +/ { + compatible = "friendlyarm,nanopi-r2s-plus", "rockchip,rk3328"; + model = "FriendlyElec NanoPi R2S Plus"; + + aliases { + mmc1 = &emmc; + }; +}; + +&emmc { + bus-width = <8>; + cap-mmc-highspeed; + disable-wp; + mmc-hs200-1_8v; + non-removable; + pinctrl-names = "default"; + pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>; + status = "okay"; +}; diff --git a/lede/target/linux/rockchip/image/armv8.mk b/lede/target/linux/rockchip/image/armv8.mk index 9329eaf32a..2adaae101c 100644 --- a/lede/target/linux/rockchip/image/armv8.mk +++ b/lede/target/linux/rockchip/image/armv8.mk @@ -154,6 +154,16 @@ define Device/friendlyarm_nanopi-r2c endef TARGET_DEVICES += friendlyarm_nanopi-r2c +define Device/friendlyarm_nanopi-r2c-plus + DEVICE_VENDOR := FriendlyARM + DEVICE_MODEL := NanoPi R2C Plus + SOC := rk3328 + UBOOT_DEVICE_NAME := nanopi-r2c-plus-rk3328 + IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-bin | gzip | append-metadata + DEVICE_PACKAGES := kmod-usb-net-rtl8152 +endef +TARGET_DEVICES += friendlyarm_nanopi-r2c-plus + define Device/friendlyarm_nanopi-r2s DEVICE_VENDOR := FriendlyARM DEVICE_MODEL := NanoPi R2S diff --git a/openwrt-passwall/.github/workflows/Auto compile with openwrt sdk.yml b/openwrt-passwall/.github/workflows/Auto compile with openwrt sdk.yml index dce62463d0..7d8dd5e9b4 100644 --- a/openwrt-passwall/.github/workflows/Auto compile with openwrt sdk.yml +++ b/openwrt-passwall/.github/workflows/Auto compile with openwrt sdk.yml @@ -43,7 +43,7 @@ jobs: url_tags: https://api.github.com/repos/${{ env.passwall }}/tags run: | cd luci-app-passwall - latest_version=$(awk -F ':=' '/PKG_VERSION|PKG_RELEASE/ {print $2}' Makefile | sed ':a;N;s/\$(PKG_VERSION)-//;s/\n$//;s/\n/-/;ba') + latest_version=$(awk -F ':=' '/PKG_VERSION|PKG_RELEASE/ {print $2}' Makefile | sed ':a;N;s/\$(PKG_VERSION).//;s/\n$//;s/\n/-/;ba') has_update=$([ -z "$(wget -qO- -t1 -T2 ${{env.url_tags}} | grep \"${latest_version}\")" ] && echo true || echo false) prerelease=$([ "${{ github.ref_name }}" == "main" ] && echo false || echo true) echo "latest_version=${latest_version}" >> $GITHUB_OUTPUT diff --git a/openwrt-passwall/luci-app-passwall/Makefile b/openwrt-passwall/luci-app-passwall/Makefile index eaa3e9bff4..5f06c23ae2 100644 --- a/openwrt-passwall/luci-app-passwall/Makefile +++ b/openwrt-passwall/luci-app-passwall/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=24.11.18 -PKG_RELEASE:=3 +PKG_RELEASE:=4 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ diff --git a/openwrt-passwall/luci-app-passwall/luasrc/passwall/api.lua b/openwrt-passwall/luci-app-passwall/luasrc/passwall/api.lua index 71c4a7d63f..289e06d9d3 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/passwall/api.lua +++ b/openwrt-passwall/luci-app-passwall/luasrc/passwall/api.lua @@ -989,7 +989,7 @@ end function get_version() local version = sys.exec("opkg list-installed luci-app-passwall 2>/dev/null | awk '{print $3}'") if not version or #version == 0 then - version = sys.exec("apk info luci-app-passwall 2>/dev/null | awk '{print $2}'") + version = sys.exec("apk info luci-app-passwall 2>/dev/null | awk 'NR == 1 {print $1}' | cut -d'-' -f4-") end return version or "" end diff --git a/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua b/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua index 90137784b5..91e609fdd7 100644 --- a/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/openwrt-passwall/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -267,7 +267,8 @@ function gen_outbound(flag, node, tag, proxy_table) level = 0, security = (node.protocol == "vmess") and node.security or nil, encryption = node.encryption or "none", - flow = (node.protocol == "vless" and node.tls == "1" and node.transport == "raw" and node.flow and node.flow ~= "") and node.flow or nil + flow = (node.protocol == "vless" and node.tls == "1" and (node.transport == "raw" or node.transport == "tcp") and node.flow and node.flow ~= "") and node.flow or nil + } } } diff --git a/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml b/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml index 73fa288069..85a58254c5 100644 --- a/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml +++ b/openwrt-passwall2/.github/workflows/Auto compile with openwrt sdk.yml @@ -265,7 +265,7 @@ jobs: ./scripts/feeds install luci-app-passwall2 rm -rf feeds/packages/lang/golang - git clone https://github.com/sbwml/packages_lang_golang -b 22.x feeds/packages/lang/golang + git clone https://github.com/sbwml/packages_lang_golang -b 23.x feeds/packages/lang/golang echo "CONFIG_ALL_NONSHARED=n" > .config echo "CONFIG_ALL_KMODS=n" >> .config @@ -303,11 +303,19 @@ jobs: id: compile run: | cd sdk - for package in $(ls feeds/passwall_packages); do - if [ -d "feeds/passwall_packages/$package" ]; then - make package/feeds/passwall_packages/$package/compile -j1 2>/dev/null - fi - done + make package/feeds/passwall_packages/tcping/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/xray-core/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/v2ray-geoip/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/v2ray-geodata/compile -j1 V=s 2>/dev/null + + make package/feeds/passwall_packages/hysteria/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/naiveproxy/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/shadowsocks-rust/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/shadowsocksr-libev/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/simple-obfs/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/sing-box/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/tuic-client/compile -j1 V=s 2>/dev/null + make package/feeds/passwall_packages/v2ray-plugin/compile -j1 V=s 2>/dev/null echo "status=success" >> $GITHUB_OUTPUT diff --git a/openwrt-passwall2/luci-app-passwall2/Makefile b/openwrt-passwall2/luci-app-passwall2/Makefile index ee7af1f0b6..5172ce6bdb 100644 --- a/openwrt-passwall2/luci-app-passwall2/Makefile +++ b/openwrt-passwall2/luci-app-passwall2/Makefile @@ -5,8 +5,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=24.11.18 -PKG_RELEASE:=2 +PKG_VERSION:=24.11.19 +PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/controller/passwall2.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/controller/passwall2.lua index 0f4b003718..5521ece0f1 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/controller/passwall2.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/controller/passwall2.lua @@ -76,6 +76,7 @@ function index() entry({"admin", "services", appname, "update_rules"}, call("update_rules")).leaf = true --[[Components update]] + entry({"admin", "services", appname, "check_passwall2"}, call("app_check")).leaf = true local coms = require "luci.passwall2.com" local com for com, _ in pairs(coms) do @@ -403,6 +404,11 @@ function server_clear_log() luci.sys.call("echo '' > /tmp/log/passwall2_server.log") end +function app_check() + local json = api.to_check_self() + http_write_json(json) +end + function com_check(comname) local json = api.to_check("", comname) http_write_json(json) diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua index 222ff7d13c..e561c2cea1 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua @@ -100,6 +100,14 @@ if #hysteria2_type > 0 then end end +o = s:option(ListValue, "domain_strategy", "Sing-box " .. translate("Domain Strategy"), translate("Set the default domain resolution strategy for the sing-box node.")) +o.default = "" +o:value("", translate("Auto")) +o:value("prefer_ipv4", translate("Prefer IPv4")) +o:value("prefer_ipv6", translate("Prefer IPv6")) +o:value("ipv4_only", translate("IPv4 Only")) +o:value("ipv6_only", translate("IPv6 Only")) + ---- Subscribe Delete All o = s:option(Button, "_stop", translate("Delete All Subscribe Node")) o.inputstyle = "remove" diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua index 9f88ff268e..cd13e9aaae 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua @@ -121,6 +121,15 @@ if #hysteria2_type > 0 then end end +o = s:option(ListValue, "domain_strategy", "Sing-box " .. translate("Domain Strategy"), translate("Set the default domain resolution strategy for the sing-box node.")) +o.default = "global" +o:value("global", translate("Use global config")) +o:value("", translate("Auto")) +o:value("prefer_ipv4", translate("Prefer IPv4")) +o:value("prefer_ipv6", translate("Prefer IPv6")) +o:value("ipv4_only", translate("IPv4 Only")) +o:value("ipv6_only", translate("IPv6 Only")) + ---- Enable auto update subscribe o = s:option(Flag, "auto_update", translate("Enable auto update subscribe")) o.default = 0 @@ -163,11 +172,11 @@ o:depends("week_update", "8") o.rmempty = true o = s:option(Value, "user_agent", translate("User-Agent")) -o.default = "sing-box/9.9.9" -o:value("curl", "Curl Default") +o.default = "v2rayN/9.99" +o:value("curl", "Curl") o:value("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0", "Edge for Linux") o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0", "Edge for Windows") o:value("Passwall2/OpenWrt", "PassWall2") -o:value("sing-box/9.9.9", "Xboard(V2board)") +o:value("v2rayN/9.99", "V2rayN") return m diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua index 63ab75fcec..9aec55d441 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua @@ -321,7 +321,7 @@ o = s:option(ListValue, option_name("flow"), translate("flow")) o.default = "" o:value("", translate("Disable")) o:value("xtls-rprx-vision") -o:depends({ [option_name("protocol")] = "vless" }) +o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true, [option_name("transport")] = "raw" }) o = s:option(Flag, option_name("tls"), translate("TLS")) o.default = 0 diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua index c7e27de052..ce424b751e 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua @@ -666,11 +666,23 @@ o = s:option(Value, option_name("plugin_opts"), translate("opts")) o:depends({ [option_name("plugin_enabled")] = true }) o = s:option(ListValue, option_name("domain_strategy"), translate("Domain Strategy"), translate("If is domain name, The requested domain name will be resolved to IP before connect.")) -o.default = "prefer_ipv6" -o:value("prefer_ipv4") -o:value("prefer_ipv6") -o:value("ipv4_only") -o:value("ipv6_only") +o.default = "" +o:value("", translate("Auto")) +o:value("prefer_ipv4", translate("Prefer IPv4")) +o:value("prefer_ipv6", translate("Prefer IPv6")) +o:value("ipv4_only", translate("IPv4 Only")) +o:value("ipv6_only", translate("IPv6 Only")) +o:depends({ [option_name("protocol")] = "socks" }) +o:depends({ [option_name("protocol")] = "http" }) +o:depends({ [option_name("protocol")] = "shadowsocks" }) +o:depends({ [option_name("protocol")] = "shadowsocksr" }) +o:depends({ [option_name("protocol")] = "vmess" }) +o:depends({ [option_name("protocol")] = "trojan" }) +o:depends({ [option_name("protocol")] = "wireguard" }) +o:depends({ [option_name("protocol")] = "hysteria" }) +o:depends({ [option_name("protocol")] = "vless" }) +o:depends({ [option_name("protocol")] = "tuic" }) +o:depends({ [option_name("protocol")] = "hysteria2" }) o = s:option(ListValue, option_name("to_node"), translate("Landing node"), translate("Only support a layer of proxy.")) o.default = "" diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua index bf11e18ec2..fe75553d53 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua @@ -109,7 +109,7 @@ o = s:option(ListValue, option_name("flow"), translate("flow")) o.default = "" o:value("", translate("Disable")) o:value("xtls-rprx-vision") -o:depends({ [option_name("protocol")] = "vless" }) +o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true, [option_name("transport")] = "raw" }) o = s:option(Flag, option_name("tls"), translate("TLS")) o.default = 0 @@ -197,7 +197,7 @@ o.validate = function(self, value, t) end o = s:option(ListValue, option_name("transport"), translate("Transport")) -o:value("tcp", "TCP") +o:value("raw", "RAW") o:value("mkcp", "mKCP") o:value("ws", "WebSocket") o:value("h2", "HTTP/2") @@ -205,7 +205,7 @@ o:value("ds", "DomainSocket") o:value("quic", "QUIC") o:value("grpc", "gRPC") o:value("httpupgrade", "HttpUpgrade") -o:value("splithttp", "SplitHTTP") +o:value("xhttp", "XHTTP") o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "socks" }) @@ -235,12 +235,20 @@ o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path")) o:depends({ [option_name("transport")] = "h2" }) -- [[ SplitHTTP部分 ]]-- -o = s:option(Value, option_name("splithttp_host"), translate("SplitHTTP Host")) -o:depends({ [option_name("transport")] = "splithttp" }) +o = s:option(Value, option_name("xhttp_host"), translate("XHTTP Host")) +o:depends({ [option_name("transport")] = "xhttp" }) -o = s:option(Value, option_name("splithttp_path"), translate("SplitHTTP Path")) +o = s:option(Value, option_name("xhttp_path"), translate("XHTTP Path")) o.placeholder = "/" -o:depends({ [option_name("transport")] = "splithttp" }) +o:depends({ [option_name("transport")] = "xhttp" }) + +o = s:option(Value, option_name("xhttp_maxuploadsize"), translate("maxUploadSize")) +o.default = "1000000" +o:depends({ [option_name("transport")] = "xhttp" }) + +o = s:option(Value, option_name("xhttp_maxconcurrentuploads"), translate("maxConcurrentUploads")) +o.default = "10" +o:depends({ [option_name("transport")] = "xhttp" }) o = s:option(Value, option_name("splithttp_maxuploadsize"), translate("maxUploadSize")) o.default = "1000000" @@ -256,7 +264,7 @@ o:depends({ [option_name("transport")] = "splithttp" }) o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type")) o:value("none", "none") o:value("http", "http") -o:depends({ [option_name("transport")] = "tcp" }) +o:depends({ [option_name("transport")] = "raw" }) -- HTTP域名 o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host")) @@ -328,8 +336,8 @@ o.default = "0" -- [[ Fallback部分 ]]-- o = s:option(Flag, option_name("fallback"), translate("Fallback")) -o:depends({ [option_name("protocol")] = "vless", [option_name("transport")] = "tcp" }) -o:depends({ [option_name("protocol")] = "trojan", [option_name("transport")] = "tcp" }) +o:depends({ [option_name("protocol")] = "vless", [option_name("transport")] = "raw" }) +o:depends({ [option_name("protocol")] = "trojan", [option_name("transport")] = "raw" }) --[[ o = s:option(Value, option_name("fallback_alpn"), "Fallback alpn") diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua index bd969d4847..16fa181f2c 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/api.lua @@ -964,6 +964,47 @@ function to_move(app_name,file) return {code = 0} end +function get_version() + local version = sys.exec("opkg list-installed luci-app-passwall2 2>/dev/null | awk '{print $3}'") + if not version or #version == 0 then + version = sys.exec("apk info luci-app-passwall2 2>/dev/null | awk 'NR == 1 {print $1}' | cut -d'-' -f4-") + end + return version or "" +end + +function to_check_self() + local url = "https://raw.githubusercontent.com/xiaorouji/openwrt-passwall2/main/luci-app-passwall2/Makefile" + local tmp_file = "/tmp/passwall2_makefile" + local return_code, result = curl_logic(url, tmp_file, curl_args) + result = return_code == 0 + if not result then + exec("/bin/rm", {"-f", tmp_file}) + return { + code = 1, + error = i18n.translatef("Failed") + } + end + local local_version = get_version() + local remote_version = sys.exec("echo -n $(grep 'PKG_VERSION' /tmp/passwall2_makefile|awk -F '=' '{print $2}')") + .. "-" .. sys.exec("echo -n $(grep 'PKG_RELEASE' /tmp/passwall2_makefile|awk -F '=' '{print $2}')") + + local has_update = compare_versions(local_version, "<", remote_version) + if not has_update then + return { + code = 0, + local_version = local_version, + remote_version = remote_version + } + end + return { + code = 1, + has_update = true, + local_version = local_version, + remote_version = remote_version, + error = i18n.translatef("The latest version: %s, currently does not support automatic update, if you need to update, please compile or download the ipk and then manually install.", remote_version) + } +end + function cacheFileCompareToLogic(file, str) local result = nil if file and str then diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 121d4d96a5..1aa130cb74 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -264,7 +264,8 @@ function gen_outbound(flag, node, tag, proxy_table) level = 0, security = (node.protocol == "vmess") and node.security or nil, encryption = node.encryption or "none", - flow = (node.protocol == "vless" and node.tls == '1' and node.flow) and node.flow or nil + flow = (node.protocol == "vless" and node.tls == "1" and (node.transport == "raw" or node.transport == "tcp") and node.flow and node.flow ~= "") and node.flow or nil + } } } @@ -367,7 +368,7 @@ function gen_config_server(node) for i = 1, #node.uuid do clients[i] = { id = node.uuid[i], - flow = ("vless" == node.protocol and "1" == node.tls and node.flow) and node.flow or nil + flow = ("vless" == node.protocol and "1" == node.tls and "raw" == node.transport and node.flow and node.flow ~= "") and node.flow or nil } end settings = { @@ -561,11 +562,11 @@ function gen_config_server(node) path = node.httpupgrade_path or "/", host = node.httpupgrade_host } or nil, - splithttpSettings = (node.transport == "splithttp") and { - path = node.splithttp_path or "/", - host = node.splithttp_host, - maxUploadSize = node.splithttp_maxuploadsize, - maxConcurrentUploads = node.splithttp_maxconcurrentuploads + xhttpSettings = (node.transport == "xhttp") and { + path = node.xhttp_path or "/", + host = node.xhttp_host, + maxUploadSize = node.xhttp_maxuploadsize, + maxConcurrentUploads = node.xhttp_maxconcurrentuploads } or nil, sockopt = { acceptProxyProtocol = (node.acceptProxyProtocol and node.acceptProxyProtocol == "1") and true or false diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/app_update/app_version.htm b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/app_update/app_version.htm index 107c87222c..98e58061c9 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/app_update/app_version.htm +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/app_update/app_version.htm @@ -177,6 +177,18 @@ local version = {} //]]> +
+ +
+
+ 【 <%=api.get_version()%> 】 + + +
+
+
+ <%for k, v in pairs(com) do version[k] = api.get_app_version(k)%>
diff --git a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm index 5071216db4..2922632680 100644 --- a/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm +++ b/openwrt-passwall2/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm @@ -210,7 +210,7 @@ local api = require "luci.passwall2.api" v_transport = "http"; params += opt.query("host", dom_prefix + "h2_host"); params += opt.query("path", dom_prefix + "h2_path"); - } else if (v_transport === "tcp") { + } else if (v_transport === "raw" || v_transport === "tcp") { params += opt.query("headerType", dom_prefix + "tcp_guise"); params += opt.query("host", dom_prefix + "tcp_guise_http_host"); params += opt.query("path", dom_prefix + "tcp_guise_http_path"); @@ -300,7 +300,7 @@ local api = require "luci.passwall2.api" } else if (v_transport === "h2") { info.host = opt.get(dom_prefix + "h2_host").value; info.path = opt.get(dom_prefix + "h2_path").value; - } else if (v_transport === "tcp") { + } else if (v_transport === "raw" || v_transport === "tcp") { info.type = opt.get(dom_prefix + "tcp_guise").value; if (info.type === "http") { info.host = opt.get(dom_prefix + "tcp_guise_http_host").value; @@ -349,7 +349,7 @@ local api = require "luci.passwall2.api" v_transport = "http"; params += opt.query("host", dom_prefix + "h2_host"); params += opt.query("path", dom_prefix + "h2_path"); - } else if (v_transport === "tcp") { + } else if (v_transport === "raw" || v_transport === "tcp") { params += opt.query("headerType", dom_prefix + "tcp_guise"); params += opt.query("host", dom_prefix + "tcp_guise_http_host"); params += opt.query("path", dom_prefix + "tcp_guise_http_path"); @@ -364,12 +364,7 @@ local api = require "luci.passwall2.api" params += opt.query("path", dom_prefix + "grpc_serviceName"); params += opt.query("serviceName", dom_prefix + "grpc_serviceName"); params += opt.query("mode", dom_prefix + "grpc_mode"); - } else if (v_transport === "splithttp") { - v_transport = "splithttp"; - params += opt.query("host", dom_prefix + "splithttp_host"); - params += opt.query("path", dom_prefix + "splithttp_path"); } else if (v_transport === "xhttp") { - v_transport = "xhttp"; params += opt.query("host", dom_prefix + "xhttp_host"); params += opt.query("path", dom_prefix + "xhttp_path"); } @@ -423,7 +418,7 @@ local api = require "luci.passwall2.api" v_transport = "http"; params += opt.query("host", dom_prefix + "h2_host"); params += opt.query("path", dom_prefix + "h2_path"); - } else if (v_transport === "tcp") { + } else if (v_transport === "raw" || v_transport === "tcp") { params += opt.query("headerType", dom_prefix + "tcp_guise"); params += opt.query("host", dom_prefix + "tcp_guise_http_host"); params += opt.query("path", dom_prefix + "tcp_guise_http_path"); @@ -799,8 +794,13 @@ local api = require "luci.passwall2.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); - if (queryParam.type === "tcp") { + if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); if (queryParam.headerType && queryParam.headerType != "none") { opt.set(dom_prefix + 'tcp_guise_http_host', queryParam.host || ""); @@ -838,7 +838,7 @@ local api = require "luci.passwall2.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); } } } else { @@ -908,8 +908,13 @@ local api = require "luci.passwall2.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); - if (queryParam.type === "tcp") { + if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); if (queryParam.headerType && queryParam.headerType != "none") { opt.set(dom_prefix + 'tcp_guise_http_host', queryParam.host || ""); @@ -947,7 +952,7 @@ local api = require "luci.passwall2.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); } opt.set(dom_prefix + 'mux', queryParam.mux === '1'); @@ -988,8 +993,13 @@ local api = require "luci.passwall2.api" ssm.net = ssm.net.toLowerCase(); if (ssm.net === "kcp" || ssm.net === "mkcp") ssm.net = "mkcp" + if (dom_prefix == "singbox_" && ssm.net === "raw") { + ssm.net = "tcp"; + } else if (dom_prefix == "xray_" && ssm.net === "tcp") { + ssm.net = "raw"; + } opt.set(dom_prefix + 'transport', ssm.net); - if (ssm.net === "tcp") { + if (ssm.net === "raw" || ssm.net === "tcp") { opt.set(dom_prefix + 'tcp_guise', (ssm.host && ssm.path) ? "http" : "none"); if (ssm.host && ssm.path) { opt.set(dom_prefix + 'tcp_guise_http_host', ssm.host); @@ -1096,8 +1106,13 @@ local api = require "luci.passwall2.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); - if (queryParam.type === "tcp") { + if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); if (queryParam.headerType && queryParam.headerType != "none") { opt.set(dom_prefix + 'tcp_guise_http_host', queryParam.host || ""); @@ -1135,11 +1150,8 @@ local api = require "luci.passwall2.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); - } else if (queryParam.type === "splithttp") { - opt.set(dom_prefix + 'splithttp_host', queryParam.host || ""); - opt.set(dom_prefix + 'splithttp_path', queryParam.path || ""); - } else if (queryParam.type === "xhttp") { + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); + } else if (queryParam.type === "xhttp" || queryParam.type === "splithttp") { opt.set(dom_prefix + 'xhttp_host', queryParam.host || ""); opt.set(dom_prefix + 'xhttp_path', queryParam.path || ""); } diff --git a/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po b/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po index 2bf6ca5923..f255d4dd0b 100644 --- a/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/openwrt-passwall2/luci-app-passwall2/po/zh-cn/passwall2.po @@ -760,6 +760,9 @@ msgstr "检查更新" msgid "Force update" msgstr "强制更新" +msgid "The latest version: %s, currently does not support automatic update, if you need to update, please compile or download the ipk and then manually install." +msgstr "最新版本:%s,目前暂不支持自动更新,如需更新,请自行编译或下载ipk然后手动安装。" + msgid "Enable custom URL" msgstr "启用自定义规则地址" @@ -1566,3 +1569,18 @@ msgstr "落地节点" msgid "Only support a layer of proxy." msgstr "仅支持一层代理。" + +msgid "Set the default domain resolution strategy for the sing-box node." +msgstr "为 sing-box 节点设置默认的域名解析策略。" + +msgid "Prefer IPv4" +msgstr "IPv4 优先" + +msgid "Prefer IPv6" +msgstr "IPv6 优先" + +msgid "IPv4 Only" +msgstr "仅 IPv4" + +msgid "IPv6 Only" +msgstr "仅 IPv6" diff --git a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index a1a8900b3d..e1db556001 100755 --- a/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -33,6 +33,8 @@ local trojan_type_default = uci:get(appname, "@global_subscribe[0]", "trojan_typ local vmess_type_default = uci:get(appname, "@global_subscribe[0]", "vmess_type") or "xray" local vless_type_default = uci:get(appname, "@global_subscribe[0]", "vless_type") or "xray" local hysteria2_type_default = uci:get(appname, "@global_subscribe[0]", "hysteria2_type") or "hysteria2" +local domain_strategy_default = uci:get(appname, "@global_subscribe[0]", "domain_strategy") or "" +local domain_strategy_node = "" -- 判断是否过滤节点关键字 local filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0" local filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {} @@ -426,10 +428,13 @@ local function processData(szType, content, add_mode, add_from) -- result.mux = 1 -- result.mux_concurrency = 8 - if not info.net then - info.net = "tcp" - end + if not info.net then info.net = "tcp" end info.net = string.lower(info.net) + if result.type == "sing-box" and info.net == "raw" then + info.net = "tcp" + elseif result.type == "Xray" and info.net == "tcp" then + info.net = "raw" + end result.transport = info.net if info.net == 'ws' then result.ws_host = info.host @@ -454,7 +459,7 @@ local function processData(szType, content, add_mode, add_from) result.h2_host = info.host result.h2_path = info.path end - if info.net == 'tcp' then + if info.net == 'raw' or info.net == 'tcp' then if info.type and info.type ~= "http" then info.type = "none" end @@ -480,9 +485,9 @@ local function processData(szType, content, add_mode, add_from) if info.net == 'grpc' then result.grpc_serviceName = info.path end - if info.net == 'splithttp' then - result.splithttp_host = info.host - result.splithttp_path = info.path + if info.net == 'xhttp' or info.net == 'splithttp' then + result.xhttp_host = info.host + result.xhttp_path = info.path end if not info.security then result.security = "auto" end if info.tls == "tls" or info.tls == "1" then @@ -493,7 +498,7 @@ local function processData(szType, content, add_mode, add_from) result.tls = "0" end - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end @@ -580,7 +585,7 @@ local function processData(szType, content, add_mode, add_from) if ss_type_default == "xray" and has_xray then result.type = 'Xray' result.protocol = 'shadowsocks' - result.transport = 'tcp' + result.transport = 'raw' end if ss_type_default == "sing-box" and has_singbox then result.type = 'sing-box' @@ -621,6 +626,11 @@ local function processData(szType, content, add_mode, add_from) if params.type then params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if result.type ~= "SS-Rust" and result.type ~= "SS" then if params.type == 'ws' then @@ -653,7 +663,7 @@ local function processData(szType, content, add_mode, add_from) result.h2_path = params.path end end - if params.type == 'tcp' then + if params.type == 'raw' or params.type == 'tcp' then result.tcp_guise = params.headerType or "none" result.tcp_guise_http_host = params.host result.tcp_guise_http_path = params.path @@ -677,7 +687,7 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end result.tls = "0" if params.security == "tls" or params.security == "reality" then @@ -765,10 +775,13 @@ local function processData(szType, content, add_mode, add_from) result.tls_allowInsecure = allowInsecure_default and "1" or "0" end - if not params.type then - params.type = "tcp" - end + if not params.type then params.type = "tcp" end params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if params.type == 'ws' then result.ws_host = params.host @@ -800,7 +813,7 @@ local function processData(szType, content, add_mode, add_from) result.h2_path = params.path end end - if params.type == 'tcp' then + if params.type == 'raw' or params.type == 'tcp' then result.tcp_guise = params.headerType or "none" result.tcp_guise_http_host = params.host result.tcp_guise_http_path = params.path @@ -824,18 +837,18 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end - if params.type == 'splithttp' then - result.splithttp_host = params.host - result.splithttp_path = params.path + if params.type == 'xhttp' or params.type == 'splithttp' then + result.xhttp_host = params.host + result.xhttp_path = params.path end result.encryption = params.encryption or "none" result.flow = params.flow or nil - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end @@ -897,10 +910,13 @@ local function processData(szType, content, add_mode, add_from) result.address = host_port end - if not params.type then - params.type = "tcp" - end + if not params.type then params.type = "tcp" end params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if params.type == 'ws' then result.ws_host = params.host @@ -932,7 +948,7 @@ local function processData(szType, content, add_mode, add_from) result.h2_path = params.path end end - if params.type == 'tcp' then + if params.type == 'raw' or params.type == 'tcp' then result.tcp_guise = params.headerType or "none" result.tcp_guise_http_host = params.host result.tcp_guise_http_path = params.path @@ -955,11 +971,11 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end - if params.type == 'splithttp' then - result.splithttp_host = params.host - result.splithttp_path = params.path + if params.type == 'xhttp' or params.type == 'splithttp' then + result.xhttp_host = params.host + result.xhttp_path = params.path end result.encryption = params.encryption or "none" @@ -983,7 +999,7 @@ local function processData(szType, content, add_mode, add_from) result.port = port result.tls_allowInsecure = allowInsecure_default and "1" or "0" - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end @@ -1351,6 +1367,10 @@ local function update_node(manual) local cfgid = uci:section(appname, "nodes", api.gen_short_uuid()) for kkk, vvv in pairs(vv) do uci:set(appname, cfgid, kkk, vvv) + -- sing-box 域名解析策略 + if kkk == "type" and vvv == "sing-box" then + uci:set(appname, cfgid, "domain_strategy", domain_strategy_node) + end end end end @@ -1544,6 +1564,12 @@ local execute = function() if hysteria2_type ~= "global" then hysteria2_type_default = hysteria2_type end + local domain_strategy = value.domain_strategy or "global" + if domain_strategy ~= "global" then + domain_strategy_node = domain_strategy + else + domain_strategy_node = domain_strategy_default + end local ua = value.user_agent log('正在订阅:【' .. remark .. '】' .. url) local raw = curl(url, "/tmp/" .. cfgid, ua) diff --git a/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs b/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs index 12e0466039..a2ff2e4592 100644 --- a/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs +++ b/shadowsocks-rust/crates/shadowsocks/src/net/sys/windows/mod.rs @@ -467,7 +467,7 @@ pub async fn create_inbound_udp_socket(addr: &SocketAddr, ipv6_only: bool) -> io /// Create a `UdpSocket` for connecting to `addr` #[inline(always)] pub async fn create_outbound_udp_socket(af: AddrFamily, opts: &ConnectOpts) -> io::Result { - let bind_addr = match (af, config.bind_local_addr) { + let bind_addr = match (af, opts.bind_local_addr) { (AddrFamily::Ipv4, Some(SocketAddr::V4(addr))) => addr.into(), (AddrFamily::Ipv6, Some(SocketAddr::V6(addr))) => addr.into(), (AddrFamily::Ipv4, ..) => SocketAddr::new(Ipv4Addr::UNSPECIFIED.into(), 0), diff --git a/small/luci-app-passwall/Makefile b/small/luci-app-passwall/Makefile index 4a14c500fb..5f06c23ae2 100644 --- a/small/luci-app-passwall/Makefile +++ b/small/luci-app-passwall/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=24.11.18 -PKG_RELEASE:=2 +PKG_RELEASE:=4 PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \ diff --git a/small/luci-app-passwall/luasrc/passwall/api.lua b/small/luci-app-passwall/luasrc/passwall/api.lua index 71c4a7d63f..289e06d9d3 100644 --- a/small/luci-app-passwall/luasrc/passwall/api.lua +++ b/small/luci-app-passwall/luasrc/passwall/api.lua @@ -989,7 +989,7 @@ end function get_version() local version = sys.exec("opkg list-installed luci-app-passwall 2>/dev/null | awk '{print $3}'") if not version or #version == 0 then - version = sys.exec("apk info luci-app-passwall 2>/dev/null | awk '{print $2}'") + version = sys.exec("apk info luci-app-passwall 2>/dev/null | awk 'NR == 1 {print $1}' | cut -d'-' -f4-") end return version or "" end diff --git a/small/luci-app-passwall/luasrc/passwall/util_xray.lua b/small/luci-app-passwall/luasrc/passwall/util_xray.lua index 30d56e1410..91e609fdd7 100644 --- a/small/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/small/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -267,7 +267,8 @@ function gen_outbound(flag, node, tag, proxy_table) level = 0, security = (node.protocol == "vmess") and node.security or nil, encryption = node.encryption or "none", - flow = (node.protocol == "vless" and node.tls == "1" and node.transport == "raw" and node.flow and node.flow ~= "") and node.flow or nil + flow = (node.protocol == "vless" and node.tls == "1" and (node.transport == "raw" or node.transport == "tcp") and node.flow and node.flow ~= "") and node.flow or nil + } } } @@ -783,13 +784,15 @@ function gen_config(var) if #valid_nodes == 0 then return nil end -- fallback node + local fallback_node_tag = nil local fallback_node_id = _node.fallback_node - if fallback_node_id == "" then fallback_node_id = nil end + if fallback_node_id == "" or fallback_node_id == "nil" then fallback_node_id = nil end if fallback_node_id then local is_new_node = true for _, outbound in ipairs(outbounds) do - if outbound.tag == fallback_node_id then + if outbound.tag:find("^" .. fallback_node_id) == 1 then is_new_node = false + fallback_node_tag = outbound.tag break end end @@ -800,12 +803,7 @@ function gen_config(var) if outbound then outbound.tag = outbound.tag .. ":" .. fallback_node.remarks table.insert(outbounds, outbound) - else - fallback_node_id = nil - end - else - if not gen_balancer(fallback_node) then - fallback_node_id = nil + fallback_node_tag = outbound.tag end end end @@ -813,10 +811,10 @@ function gen_config(var) table.insert(balancers, { tag = balancer_tag, selector = valid_nodes, - fallbackTag = fallback_node_id, + fallbackTag = fallback_node_tag, strategy = { type = _node.balancingStrategy or "random" } }) - if _node.balancingStrategy == "leastPing" or fallback_node_id then + if _node.balancingStrategy == "leastPing" or fallback_node_tag then if not observatory then observatory = { subjectSelector = { "blc-" }, @@ -1191,13 +1189,8 @@ function gen_config(var) --[[ local default_dns_flag = "remote" - if node_id and tcp_redir_port then - local node = uci:get_all(appname, node_id) - if node.protocol == "_shunt" then - if node.default_node == "_direct" then - default_dns_flag = "direct" - end - end + if (not COMMON.default_balancer_tag and not COMMON.default_outbound_tag) or COMMON.default_outbound_tag == "direct" then + default_dns_flag = "direct" end if dns.servers and #dns.servers > 0 then diff --git a/small/luci-app-passwall2/Makefile b/small/luci-app-passwall2/Makefile index 52ec5c6685..5172ce6bdb 100644 --- a/small/luci-app-passwall2/Makefile +++ b/small/luci-app-passwall2/Makefile @@ -5,7 +5,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 -PKG_VERSION:=24.11.18 +PKG_VERSION:=24.11.19 PKG_RELEASE:=1 PKG_CONFIG_DEPENDS:= \ diff --git a/small/luci-app-passwall2/luasrc/controller/passwall2.lua b/small/luci-app-passwall2/luasrc/controller/passwall2.lua index 0f4b003718..5521ece0f1 100644 --- a/small/luci-app-passwall2/luasrc/controller/passwall2.lua +++ b/small/luci-app-passwall2/luasrc/controller/passwall2.lua @@ -76,6 +76,7 @@ function index() entry({"admin", "services", appname, "update_rules"}, call("update_rules")).leaf = true --[[Components update]] + entry({"admin", "services", appname, "check_passwall2"}, call("app_check")).leaf = true local coms = require "luci.passwall2.com" local com for com, _ in pairs(coms) do @@ -403,6 +404,11 @@ function server_clear_log() luci.sys.call("echo '' > /tmp/log/passwall2_server.log") end +function app_check() + local json = api.to_check_self() + http_write_json(json) +end + function com_check(comname) local json = api.to_check("", comname) http_write_json(json) diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua index 222ff7d13c..e561c2cea1 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua @@ -100,6 +100,14 @@ if #hysteria2_type > 0 then end end +o = s:option(ListValue, "domain_strategy", "Sing-box " .. translate("Domain Strategy"), translate("Set the default domain resolution strategy for the sing-box node.")) +o.default = "" +o:value("", translate("Auto")) +o:value("prefer_ipv4", translate("Prefer IPv4")) +o:value("prefer_ipv6", translate("Prefer IPv6")) +o:value("ipv4_only", translate("IPv4 Only")) +o:value("ipv6_only", translate("IPv6 Only")) + ---- Subscribe Delete All o = s:option(Button, "_stop", translate("Delete All Subscribe Node")) o.inputstyle = "remove" diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua index 9f88ff268e..cd13e9aaae 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua @@ -121,6 +121,15 @@ if #hysteria2_type > 0 then end end +o = s:option(ListValue, "domain_strategy", "Sing-box " .. translate("Domain Strategy"), translate("Set the default domain resolution strategy for the sing-box node.")) +o.default = "global" +o:value("global", translate("Use global config")) +o:value("", translate("Auto")) +o:value("prefer_ipv4", translate("Prefer IPv4")) +o:value("prefer_ipv6", translate("Prefer IPv6")) +o:value("ipv4_only", translate("IPv4 Only")) +o:value("ipv6_only", translate("IPv6 Only")) + ---- Enable auto update subscribe o = s:option(Flag, "auto_update", translate("Enable auto update subscribe")) o.default = 0 @@ -163,11 +172,11 @@ o:depends("week_update", "8") o.rmempty = true o = s:option(Value, "user_agent", translate("User-Agent")) -o.default = "sing-box/9.9.9" -o:value("curl", "Curl Default") +o.default = "v2rayN/9.99" +o:value("curl", "Curl") o:value("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0", "Edge for Linux") o:value("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0", "Edge for Windows") o:value("Passwall2/OpenWrt", "PassWall2") -o:value("sing-box/9.9.9", "Xboard(V2board)") +o:value("v2rayN/9.99", "V2rayN") return m diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua index 63ab75fcec..9aec55d441 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua @@ -321,7 +321,7 @@ o = s:option(ListValue, option_name("flow"), translate("flow")) o.default = "" o:value("", translate("Disable")) o:value("xtls-rprx-vision") -o:depends({ [option_name("protocol")] = "vless" }) +o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true, [option_name("transport")] = "raw" }) o = s:option(Flag, option_name("tls"), translate("TLS")) o.default = 0 diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua index c7e27de052..ce424b751e 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua @@ -666,11 +666,23 @@ o = s:option(Value, option_name("plugin_opts"), translate("opts")) o:depends({ [option_name("plugin_enabled")] = true }) o = s:option(ListValue, option_name("domain_strategy"), translate("Domain Strategy"), translate("If is domain name, The requested domain name will be resolved to IP before connect.")) -o.default = "prefer_ipv6" -o:value("prefer_ipv4") -o:value("prefer_ipv6") -o:value("ipv4_only") -o:value("ipv6_only") +o.default = "" +o:value("", translate("Auto")) +o:value("prefer_ipv4", translate("Prefer IPv4")) +o:value("prefer_ipv6", translate("Prefer IPv6")) +o:value("ipv4_only", translate("IPv4 Only")) +o:value("ipv6_only", translate("IPv6 Only")) +o:depends({ [option_name("protocol")] = "socks" }) +o:depends({ [option_name("protocol")] = "http" }) +o:depends({ [option_name("protocol")] = "shadowsocks" }) +o:depends({ [option_name("protocol")] = "shadowsocksr" }) +o:depends({ [option_name("protocol")] = "vmess" }) +o:depends({ [option_name("protocol")] = "trojan" }) +o:depends({ [option_name("protocol")] = "wireguard" }) +o:depends({ [option_name("protocol")] = "hysteria" }) +o:depends({ [option_name("protocol")] = "vless" }) +o:depends({ [option_name("protocol")] = "tuic" }) +o:depends({ [option_name("protocol")] = "hysteria2" }) o = s:option(ListValue, option_name("to_node"), translate("Landing node"), translate("Only support a layer of proxy.")) o.default = "" diff --git a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua index bf11e18ec2..fe75553d53 100644 --- a/small/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua +++ b/small/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua @@ -109,7 +109,7 @@ o = s:option(ListValue, option_name("flow"), translate("flow")) o.default = "" o:value("", translate("Disable")) o:value("xtls-rprx-vision") -o:depends({ [option_name("protocol")] = "vless" }) +o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true, [option_name("transport")] = "raw" }) o = s:option(Flag, option_name("tls"), translate("TLS")) o.default = 0 @@ -197,7 +197,7 @@ o.validate = function(self, value, t) end o = s:option(ListValue, option_name("transport"), translate("Transport")) -o:value("tcp", "TCP") +o:value("raw", "RAW") o:value("mkcp", "mKCP") o:value("ws", "WebSocket") o:value("h2", "HTTP/2") @@ -205,7 +205,7 @@ o:value("ds", "DomainSocket") o:value("quic", "QUIC") o:value("grpc", "gRPC") o:value("httpupgrade", "HttpUpgrade") -o:value("splithttp", "SplitHTTP") +o:value("xhttp", "XHTTP") o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "socks" }) @@ -235,12 +235,20 @@ o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path")) o:depends({ [option_name("transport")] = "h2" }) -- [[ SplitHTTP部分 ]]-- -o = s:option(Value, option_name("splithttp_host"), translate("SplitHTTP Host")) -o:depends({ [option_name("transport")] = "splithttp" }) +o = s:option(Value, option_name("xhttp_host"), translate("XHTTP Host")) +o:depends({ [option_name("transport")] = "xhttp" }) -o = s:option(Value, option_name("splithttp_path"), translate("SplitHTTP Path")) +o = s:option(Value, option_name("xhttp_path"), translate("XHTTP Path")) o.placeholder = "/" -o:depends({ [option_name("transport")] = "splithttp" }) +o:depends({ [option_name("transport")] = "xhttp" }) + +o = s:option(Value, option_name("xhttp_maxuploadsize"), translate("maxUploadSize")) +o.default = "1000000" +o:depends({ [option_name("transport")] = "xhttp" }) + +o = s:option(Value, option_name("xhttp_maxconcurrentuploads"), translate("maxConcurrentUploads")) +o.default = "10" +o:depends({ [option_name("transport")] = "xhttp" }) o = s:option(Value, option_name("splithttp_maxuploadsize"), translate("maxUploadSize")) o.default = "1000000" @@ -256,7 +264,7 @@ o:depends({ [option_name("transport")] = "splithttp" }) o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type")) o:value("none", "none") o:value("http", "http") -o:depends({ [option_name("transport")] = "tcp" }) +o:depends({ [option_name("transport")] = "raw" }) -- HTTP域名 o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host")) @@ -328,8 +336,8 @@ o.default = "0" -- [[ Fallback部分 ]]-- o = s:option(Flag, option_name("fallback"), translate("Fallback")) -o:depends({ [option_name("protocol")] = "vless", [option_name("transport")] = "tcp" }) -o:depends({ [option_name("protocol")] = "trojan", [option_name("transport")] = "tcp" }) +o:depends({ [option_name("protocol")] = "vless", [option_name("transport")] = "raw" }) +o:depends({ [option_name("protocol")] = "trojan", [option_name("transport")] = "raw" }) --[[ o = s:option(Value, option_name("fallback_alpn"), "Fallback alpn") diff --git a/small/luci-app-passwall2/luasrc/passwall2/api.lua b/small/luci-app-passwall2/luasrc/passwall2/api.lua index bd969d4847..16fa181f2c 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/api.lua @@ -964,6 +964,47 @@ function to_move(app_name,file) return {code = 0} end +function get_version() + local version = sys.exec("opkg list-installed luci-app-passwall2 2>/dev/null | awk '{print $3}'") + if not version or #version == 0 then + version = sys.exec("apk info luci-app-passwall2 2>/dev/null | awk 'NR == 1 {print $1}' | cut -d'-' -f4-") + end + return version or "" +end + +function to_check_self() + local url = "https://raw.githubusercontent.com/xiaorouji/openwrt-passwall2/main/luci-app-passwall2/Makefile" + local tmp_file = "/tmp/passwall2_makefile" + local return_code, result = curl_logic(url, tmp_file, curl_args) + result = return_code == 0 + if not result then + exec("/bin/rm", {"-f", tmp_file}) + return { + code = 1, + error = i18n.translatef("Failed") + } + end + local local_version = get_version() + local remote_version = sys.exec("echo -n $(grep 'PKG_VERSION' /tmp/passwall2_makefile|awk -F '=' '{print $2}')") + .. "-" .. sys.exec("echo -n $(grep 'PKG_RELEASE' /tmp/passwall2_makefile|awk -F '=' '{print $2}')") + + local has_update = compare_versions(local_version, "<", remote_version) + if not has_update then + return { + code = 0, + local_version = local_version, + remote_version = remote_version + } + end + return { + code = 1, + has_update = true, + local_version = local_version, + remote_version = remote_version, + error = i18n.translatef("The latest version: %s, currently does not support automatic update, if you need to update, please compile or download the ipk and then manually install.", remote_version) + } +end + function cacheFileCompareToLogic(file, str) local result = nil if file and str then diff --git a/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua index b482126ace..1aa130cb74 100644 --- a/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/small/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -264,7 +264,8 @@ function gen_outbound(flag, node, tag, proxy_table) level = 0, security = (node.protocol == "vmess") and node.security or nil, encryption = node.encryption or "none", - flow = (node.protocol == "vless" and node.tls == '1' and node.flow) and node.flow or nil + flow = (node.protocol == "vless" and node.tls == "1" and (node.transport == "raw" or node.transport == "tcp") and node.flow and node.flow ~= "") and node.flow or nil + } } } @@ -367,7 +368,7 @@ function gen_config_server(node) for i = 1, #node.uuid do clients[i] = { id = node.uuid[i], - flow = ("vless" == node.protocol and "1" == node.tls and node.flow) and node.flow or nil + flow = ("vless" == node.protocol and "1" == node.tls and "raw" == node.transport and node.flow and node.flow ~= "") and node.flow or nil } end settings = { @@ -561,11 +562,11 @@ function gen_config_server(node) path = node.httpupgrade_path or "/", host = node.httpupgrade_host } or nil, - splithttpSettings = (node.transport == "splithttp") and { - path = node.splithttp_path or "/", - host = node.splithttp_host, - maxUploadSize = node.splithttp_maxuploadsize, - maxConcurrentUploads = node.splithttp_maxconcurrentuploads + xhttpSettings = (node.transport == "xhttp") and { + path = node.xhttp_path or "/", + host = node.xhttp_host, + maxUploadSize = node.xhttp_maxuploadsize, + maxConcurrentUploads = node.xhttp_maxconcurrentuploads } or nil, sockopt = { acceptProxyProtocol = (node.acceptProxyProtocol and node.acceptProxyProtocol == "1") and true or false @@ -781,13 +782,15 @@ function gen_config(var) if #valid_nodes == 0 then return nil end -- fallback node + local fallback_node_tag = nil local fallback_node_id = _node.fallback_node - if fallback_node_id == "" then fallback_node_id = nil end + if fallback_node_id == "" or fallback_node_id == "nil" then fallback_node_id = nil end if fallback_node_id then local is_new_node = true for _, outbound in ipairs(outbounds) do - if outbound.tag == fallback_node_id then + if outbound.tag:find("^" .. fallback_node_id) == 1 then is_new_node = false + fallback_node_tag = outbound.tag break end end @@ -798,12 +801,7 @@ function gen_config(var) if outbound then outbound.tag = outbound.tag .. ":" .. fallback_node.remarks table.insert(outbounds, outbound) - else - fallback_node_id = nil - end - else - if not gen_balancer(fallback_node) then - fallback_node_id = nil + fallback_node_tag = outbound.tag end end end @@ -811,10 +809,10 @@ function gen_config(var) table.insert(balancers, { tag = balancer_tag, selector = valid_nodes, - fallbackTag = fallback_node_id, + fallbackTag = fallback_node_tag, strategy = { type = _node.balancingStrategy or "random" } }) - if _node.balancingStrategy == "leastPing" or fallback_node_id then + if _node.balancingStrategy == "leastPing" or fallback_node_tag then if not observatory then observatory = { subjectSelector = { "blc-" }, @@ -1366,7 +1364,7 @@ function gen_config(var) end local default_dns_flag = "remote" - if not COMMON.default_outbound_tag or COMMON.default_outbound_tag == "direct" then + if (not COMMON.default_balancer_tag and not COMMON.default_outbound_tag) or COMMON.default_outbound_tag == "direct" then default_dns_flag = "direct" end diff --git a/small/luci-app-passwall2/luasrc/view/passwall2/app_update/app_version.htm b/small/luci-app-passwall2/luasrc/view/passwall2/app_update/app_version.htm index 107c87222c..98e58061c9 100644 --- a/small/luci-app-passwall2/luasrc/view/passwall2/app_update/app_version.htm +++ b/small/luci-app-passwall2/luasrc/view/passwall2/app_update/app_version.htm @@ -177,6 +177,18 @@ local version = {} //]]> +
+ +
+
+ 【 <%=api.get_version()%> 】 + + +
+
+
+ <%for k, v in pairs(com) do version[k] = api.get_app_version(k)%>
diff --git a/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm b/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm index 5071216db4..2922632680 100644 --- a/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm +++ b/small/luci-app-passwall2/luasrc/view/passwall2/node_list/link_share_man.htm @@ -210,7 +210,7 @@ local api = require "luci.passwall2.api" v_transport = "http"; params += opt.query("host", dom_prefix + "h2_host"); params += opt.query("path", dom_prefix + "h2_path"); - } else if (v_transport === "tcp") { + } else if (v_transport === "raw" || v_transport === "tcp") { params += opt.query("headerType", dom_prefix + "tcp_guise"); params += opt.query("host", dom_prefix + "tcp_guise_http_host"); params += opt.query("path", dom_prefix + "tcp_guise_http_path"); @@ -300,7 +300,7 @@ local api = require "luci.passwall2.api" } else if (v_transport === "h2") { info.host = opt.get(dom_prefix + "h2_host").value; info.path = opt.get(dom_prefix + "h2_path").value; - } else if (v_transport === "tcp") { + } else if (v_transport === "raw" || v_transport === "tcp") { info.type = opt.get(dom_prefix + "tcp_guise").value; if (info.type === "http") { info.host = opt.get(dom_prefix + "tcp_guise_http_host").value; @@ -349,7 +349,7 @@ local api = require "luci.passwall2.api" v_transport = "http"; params += opt.query("host", dom_prefix + "h2_host"); params += opt.query("path", dom_prefix + "h2_path"); - } else if (v_transport === "tcp") { + } else if (v_transport === "raw" || v_transport === "tcp") { params += opt.query("headerType", dom_prefix + "tcp_guise"); params += opt.query("host", dom_prefix + "tcp_guise_http_host"); params += opt.query("path", dom_prefix + "tcp_guise_http_path"); @@ -364,12 +364,7 @@ local api = require "luci.passwall2.api" params += opt.query("path", dom_prefix + "grpc_serviceName"); params += opt.query("serviceName", dom_prefix + "grpc_serviceName"); params += opt.query("mode", dom_prefix + "grpc_mode"); - } else if (v_transport === "splithttp") { - v_transport = "splithttp"; - params += opt.query("host", dom_prefix + "splithttp_host"); - params += opt.query("path", dom_prefix + "splithttp_path"); } else if (v_transport === "xhttp") { - v_transport = "xhttp"; params += opt.query("host", dom_prefix + "xhttp_host"); params += opt.query("path", dom_prefix + "xhttp_path"); } @@ -423,7 +418,7 @@ local api = require "luci.passwall2.api" v_transport = "http"; params += opt.query("host", dom_prefix + "h2_host"); params += opt.query("path", dom_prefix + "h2_path"); - } else if (v_transport === "tcp") { + } else if (v_transport === "raw" || v_transport === "tcp") { params += opt.query("headerType", dom_prefix + "tcp_guise"); params += opt.query("host", dom_prefix + "tcp_guise_http_host"); params += opt.query("path", dom_prefix + "tcp_guise_http_path"); @@ -799,8 +794,13 @@ local api = require "luci.passwall2.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); - if (queryParam.type === "tcp") { + if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); if (queryParam.headerType && queryParam.headerType != "none") { opt.set(dom_prefix + 'tcp_guise_http_host', queryParam.host || ""); @@ -838,7 +838,7 @@ local api = require "luci.passwall2.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); } } } else { @@ -908,8 +908,13 @@ local api = require "luci.passwall2.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); - if (queryParam.type === "tcp") { + if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); if (queryParam.headerType && queryParam.headerType != "none") { opt.set(dom_prefix + 'tcp_guise_http_host', queryParam.host || ""); @@ -947,7 +952,7 @@ local api = require "luci.passwall2.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); } opt.set(dom_prefix + 'mux', queryParam.mux === '1'); @@ -988,8 +993,13 @@ local api = require "luci.passwall2.api" ssm.net = ssm.net.toLowerCase(); if (ssm.net === "kcp" || ssm.net === "mkcp") ssm.net = "mkcp" + if (dom_prefix == "singbox_" && ssm.net === "raw") { + ssm.net = "tcp"; + } else if (dom_prefix == "xray_" && ssm.net === "tcp") { + ssm.net = "raw"; + } opt.set(dom_prefix + 'transport', ssm.net); - if (ssm.net === "tcp") { + if (ssm.net === "raw" || ssm.net === "tcp") { opt.set(dom_prefix + 'tcp_guise', (ssm.host && ssm.path) ? "http" : "none"); if (ssm.host && ssm.path) { opt.set(dom_prefix + 'tcp_guise_http_host', ssm.host); @@ -1096,8 +1106,13 @@ local api = require "luci.passwall2.api" queryParam.type = "mkcp" if (queryParam.type === "h2" || queryParam.type === "http") queryParam.type = "h2" + if (dom_prefix == "singbox_" && queryParam.type === "raw") { + queryParam.type = "tcp"; + } else if (dom_prefix == "xray_" && queryParam.type === "tcp") { + queryParam.type = "raw"; + } opt.set(dom_prefix + 'transport', queryParam.type); - if (queryParam.type === "tcp") { + if (queryParam.type === "raw" || queryParam.type === "tcp") { opt.set(dom_prefix + 'tcp_guise', queryParam.headerType || "none"); if (queryParam.headerType && queryParam.headerType != "none") { opt.set(dom_prefix + 'tcp_guise_http_host', queryParam.host || ""); @@ -1135,11 +1150,8 @@ local api = require "luci.passwall2.api" opt.set(dom_prefix + 'mkcp_guise', queryParam.headerType || "none"); } else if (queryParam.type === "grpc") { opt.set(dom_prefix + 'grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); - opt.set(dom_prefix + 'grpc_mode', queryParam.mode); - } else if (queryParam.type === "splithttp") { - opt.set(dom_prefix + 'splithttp_host', queryParam.host || ""); - opt.set(dom_prefix + 'splithttp_path', queryParam.path || ""); - } else if (queryParam.type === "xhttp") { + opt.set(dom_prefix + 'grpc_mode', queryParam.mode || "gun"); + } else if (queryParam.type === "xhttp" || queryParam.type === "splithttp") { opt.set(dom_prefix + 'xhttp_host', queryParam.host || ""); opt.set(dom_prefix + 'xhttp_path', queryParam.path || ""); } diff --git a/small/luci-app-passwall2/po/zh-cn/passwall2.po b/small/luci-app-passwall2/po/zh-cn/passwall2.po index 2bf6ca5923..f255d4dd0b 100644 --- a/small/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/small/luci-app-passwall2/po/zh-cn/passwall2.po @@ -760,6 +760,9 @@ msgstr "检查更新" msgid "Force update" msgstr "强制更新" +msgid "The latest version: %s, currently does not support automatic update, if you need to update, please compile or download the ipk and then manually install." +msgstr "最新版本:%s,目前暂不支持自动更新,如需更新,请自行编译或下载ipk然后手动安装。" + msgid "Enable custom URL" msgstr "启用自定义规则地址" @@ -1566,3 +1569,18 @@ msgstr "落地节点" msgid "Only support a layer of proxy." msgstr "仅支持一层代理。" + +msgid "Set the default domain resolution strategy for the sing-box node." +msgstr "为 sing-box 节点设置默认的域名解析策略。" + +msgid "Prefer IPv4" +msgstr "IPv4 优先" + +msgid "Prefer IPv6" +msgstr "IPv6 优先" + +msgid "IPv4 Only" +msgstr "仅 IPv4" + +msgid "IPv6 Only" +msgstr "仅 IPv6" diff --git a/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index a1a8900b3d..e1db556001 100755 --- a/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/small/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -33,6 +33,8 @@ local trojan_type_default = uci:get(appname, "@global_subscribe[0]", "trojan_typ local vmess_type_default = uci:get(appname, "@global_subscribe[0]", "vmess_type") or "xray" local vless_type_default = uci:get(appname, "@global_subscribe[0]", "vless_type") or "xray" local hysteria2_type_default = uci:get(appname, "@global_subscribe[0]", "hysteria2_type") or "hysteria2" +local domain_strategy_default = uci:get(appname, "@global_subscribe[0]", "domain_strategy") or "" +local domain_strategy_node = "" -- 判断是否过滤节点关键字 local filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0" local filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {} @@ -426,10 +428,13 @@ local function processData(szType, content, add_mode, add_from) -- result.mux = 1 -- result.mux_concurrency = 8 - if not info.net then - info.net = "tcp" - end + if not info.net then info.net = "tcp" end info.net = string.lower(info.net) + if result.type == "sing-box" and info.net == "raw" then + info.net = "tcp" + elseif result.type == "Xray" and info.net == "tcp" then + info.net = "raw" + end result.transport = info.net if info.net == 'ws' then result.ws_host = info.host @@ -454,7 +459,7 @@ local function processData(szType, content, add_mode, add_from) result.h2_host = info.host result.h2_path = info.path end - if info.net == 'tcp' then + if info.net == 'raw' or info.net == 'tcp' then if info.type and info.type ~= "http" then info.type = "none" end @@ -480,9 +485,9 @@ local function processData(szType, content, add_mode, add_from) if info.net == 'grpc' then result.grpc_serviceName = info.path end - if info.net == 'splithttp' then - result.splithttp_host = info.host - result.splithttp_path = info.path + if info.net == 'xhttp' or info.net == 'splithttp' then + result.xhttp_host = info.host + result.xhttp_path = info.path end if not info.security then result.security = "auto" end if info.tls == "tls" or info.tls == "1" then @@ -493,7 +498,7 @@ local function processData(szType, content, add_mode, add_from) result.tls = "0" end - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end @@ -580,7 +585,7 @@ local function processData(szType, content, add_mode, add_from) if ss_type_default == "xray" and has_xray then result.type = 'Xray' result.protocol = 'shadowsocks' - result.transport = 'tcp' + result.transport = 'raw' end if ss_type_default == "sing-box" and has_singbox then result.type = 'sing-box' @@ -621,6 +626,11 @@ local function processData(szType, content, add_mode, add_from) if params.type then params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if result.type ~= "SS-Rust" and result.type ~= "SS" then if params.type == 'ws' then @@ -653,7 +663,7 @@ local function processData(szType, content, add_mode, add_from) result.h2_path = params.path end end - if params.type == 'tcp' then + if params.type == 'raw' or params.type == 'tcp' then result.tcp_guise = params.headerType or "none" result.tcp_guise_http_host = params.host result.tcp_guise_http_path = params.path @@ -677,7 +687,7 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end result.tls = "0" if params.security == "tls" or params.security == "reality" then @@ -765,10 +775,13 @@ local function processData(szType, content, add_mode, add_from) result.tls_allowInsecure = allowInsecure_default and "1" or "0" end - if not params.type then - params.type = "tcp" - end + if not params.type then params.type = "tcp" end params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if params.type == 'ws' then result.ws_host = params.host @@ -800,7 +813,7 @@ local function processData(szType, content, add_mode, add_from) result.h2_path = params.path end end - if params.type == 'tcp' then + if params.type == 'raw' or params.type == 'tcp' then result.tcp_guise = params.headerType or "none" result.tcp_guise_http_host = params.host result.tcp_guise_http_path = params.path @@ -824,18 +837,18 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end - if params.type == 'splithttp' then - result.splithttp_host = params.host - result.splithttp_path = params.path + if params.type == 'xhttp' or params.type == 'splithttp' then + result.xhttp_host = params.host + result.xhttp_path = params.path end result.encryption = params.encryption or "none" result.flow = params.flow or nil - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end @@ -897,10 +910,13 @@ local function processData(szType, content, add_mode, add_from) result.address = host_port end - if not params.type then - params.type = "tcp" - end + if not params.type then params.type = "tcp" end params.type = string.lower(params.type) + if result.type == "sing-box" and params.type == "raw" then + params.type = "tcp" + elseif result.type == "Xray" and params.type == "tcp" then + params.type = "raw" + end result.transport = params.type if params.type == 'ws' then result.ws_host = params.host @@ -932,7 +948,7 @@ local function processData(szType, content, add_mode, add_from) result.h2_path = params.path end end - if params.type == 'tcp' then + if params.type == 'raw' or params.type == 'tcp' then result.tcp_guise = params.headerType or "none" result.tcp_guise_http_host = params.host result.tcp_guise_http_path = params.path @@ -955,11 +971,11 @@ local function processData(szType, content, add_mode, add_from) if params.type == 'grpc' then if params.path then result.grpc_serviceName = params.path end if params.serviceName then result.grpc_serviceName = params.serviceName end - result.grpc_mode = params.mode + result.grpc_mode = params.mode or "gun" end - if params.type == 'splithttp' then - result.splithttp_host = params.host - result.splithttp_path = params.path + if params.type == 'xhttp' or params.type == 'splithttp' then + result.xhttp_host = params.host + result.xhttp_path = params.path end result.encryption = params.encryption or "none" @@ -983,7 +999,7 @@ local function processData(szType, content, add_mode, add_from) result.port = port result.tls_allowInsecure = allowInsecure_default and "1" or "0" - if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "splithttp") then + if result.type == "sing-box" and (result.transport == "mkcp" or result.transport == "xhttp" or result.transport == "splithttp") then log("跳过节点:" .. result.remarks ..",因Sing-Box不支持" .. szType .. "协议的" .. result.transport .. "传输方式,需更换Xray。") return nil end @@ -1351,6 +1367,10 @@ local function update_node(manual) local cfgid = uci:section(appname, "nodes", api.gen_short_uuid()) for kkk, vvv in pairs(vv) do uci:set(appname, cfgid, kkk, vvv) + -- sing-box 域名解析策略 + if kkk == "type" and vvv == "sing-box" then + uci:set(appname, cfgid, "domain_strategy", domain_strategy_node) + end end end end @@ -1544,6 +1564,12 @@ local execute = function() if hysteria2_type ~= "global" then hysteria2_type_default = hysteria2_type end + local domain_strategy = value.domain_strategy or "global" + if domain_strategy ~= "global" then + domain_strategy_node = domain_strategy + else + domain_strategy_node = domain_strategy_default + end local ua = value.user_agent log('正在订阅:【' .. remark .. '】' .. url) local raw = curl(url, "/tmp/" .. cfgid, ua) diff --git a/small/luci-app-ssr-plus/root/usr/share/shadowsocksr/update.lua b/small/luci-app-ssr-plus/root/usr/share/shadowsocksr/update.lua index 33ca9fef6c..d786864b36 100755 --- a/small/luci-app-ssr-plus/root/usr/share/shadowsocksr/update.lua +++ b/small/luci-app-ssr-plus/root/usr/share/shadowsocksr/update.lua @@ -10,15 +10,40 @@ local icount = 0 local args = arg[1] local uci = luci.model.uci.cursor() --- 以下设置更新数据库至 DNSMASQ 路径 --- 获取 DEFAULT_DNSMASQ_CFGID +-- 以下设置更新数据库至 DNSMASQ 配置路径 +-- 获取 DNSMasq 配置 ID local DEFAULT_DNSMASQ_CFGID = uci:get_first("dhcp", "dnsmasq", ".name") + +if not DEFAULT_DNSMASQ_CFGID then + error("未找到默认的 DNSMasq 配置 ID") +end + -- 查找包含 conf-dir 选项的 dnsmasq.conf 文件路径 -local DNSMASQ_CONF_PATH = string.format("grep -l '^conf-dir=' /tmp/etc/dnsmasq.conf.%s*", DEFAULT_DNSMASQ_CFGID):gsub("%s+", "") -- 去除空白字符 --- 获取 DNSMASQ_CONF_DIR -local DNSMASQ_CONF_DIR = string.format("grep '^conf-dir=' %s | cut -d'=' -f2 | head -n 1", DNSMASQ_CONF_PATH):gsub("%s+", "") -- 去除空白字符 --- 设置 TMP_DNSMASQ_PATH 路径 -local TMP_DNSMASQ_PATH = DNSMASQ_CONF_DIR .. "/dnsmasq-ssrplus.d" +local DNSMASQ_CONF_PATH_CMD = string.format("grep -l '^conf-dir=' /tmp/etc/dnsmasq.conf.%s*", DEFAULT_DNSMASQ_CFGID) +local DNSMASQ_CONF_PATH = io.popen(DNSMASQ_CONF_PATH_CMD):read("*l") + +if not DNSMASQ_CONF_PATH or DNSMASQ_CONF_PATH:match("^%s*$") then + error("无法找到包含 conf-dir 选项的 dnsmasq.conf 文件路径") +end + +DNSMASQ_CONF_PATH = DNSMASQ_CONF_PATH:gsub("%s+", "") -- 去除空白字符 + +-- 获取 DNSMASQ 配置路径 +local DNSMASQ_CONF_DIR_CMD = string.format("grep '^conf-dir=' %s | cut -d'=' -f2 | head -n 1", DNSMASQ_CONF_PATH) +local DNSMASQ_CONF_DIR = io.popen(DNSMASQ_CONF_DIR_CMD):read("*l") + +if not DNSMASQ_CONF_DIR or DNSMASQ_CONF_DIR:match("^%s*$") then + error("无法提取 conf-dir 配置,请检查 dnsmasq.conf 文件内容") +end + +DNSMASQ_CONF_DIR = DNSMASQ_CONF_DIR:gsub("%s+", "") -- 去除空白字符 + +-- 设置 dnsmasq-ssrplus.d 目录路径,并去除路径末尾的斜杠 +local TMP_DNSMASQ_PATH = DNSMASQ_CONF_DIR:match("^(.-)/?$") .. "/dnsmasq-ssrplus.d" + +if not TMP_DNSMASQ_PATH or TMP_DNSMASQ_PATH:match("^%s*$") then + error("无法找到包含 dnsmasq 选项的 dnsmasq-ssrplus.d 目录路径") +end local TMP_PATH = "/var/etc/ssrplus" -- match comments/title/whitelist/ip address/excluded_domain diff --git a/v2rayn/v2rayN/AmazTool/Assets/en-US.json b/v2rayn/v2rayN/AmazTool/Assets/en-US.json index f4c0f60014..8b94e7cb5d 100644 --- a/v2rayn/v2rayN/AmazTool/Assets/en-US.json +++ b/v2rayn/v2rayN/AmazTool/Assets/en-US.json @@ -1,14 +1,14 @@ { - "Restart_v2rayN": "Start v2rayN, please wait...", - "Guidelines": "Please run it from the main application.", - "Upgrade_File_Not_Found": "Upgrade failed, file not found.", - "In_Progress": "In progress, please wait...", - "Try_Terminate_Process": "Try to terminate the v2rayN process.", - "Failed_Terminate_Process": "Failed to terminate the v2rayN.Close it manually,or the upgrade may fail.", - "Start_Unzipping": "Start extracting the update package.", - "Success_Unzipping": "Successfully extracted the update package!", - "Failed_Unzipping": "Failed to extract the update package!", - "Failed_Upgrade": "Upgrade failed!", - "Success_Upgrade": "Upgrade success!", - "Information": "Information" + "Restart_v2rayN": "Start v2rayN, please wait...", + "Guidelines": "Please run it from the main application.", + "Upgrade_File_Not_Found": "Upgrade failed, file not found.", + "In_Progress": "In progress, please wait...", + "Try_Terminate_Process": "Try to terminate the v2rayN process.", + "Failed_Terminate_Process": "Failed to terminate the v2rayN.Close it manually,or the upgrade may fail.", + "Start_Unzipping": "Start extracting the update package.", + "Success_Unzipping": "Successfully extracted the update package!", + "Failed_Unzipping": "Failed to extract the update package!", + "Failed_Upgrade": "Upgrade failed!", + "Success_Upgrade": "Upgrade success!", + "Information": "Information" } \ No newline at end of file diff --git a/v2rayn/v2rayN/AmazTool/Assets/zh-CN.json b/v2rayn/v2rayN/AmazTool/Assets/zh-CN.json index a6b6a1b780..dd57bcdfff 100644 --- a/v2rayn/v2rayN/AmazTool/Assets/zh-CN.json +++ b/v2rayn/v2rayN/AmazTool/Assets/zh-CN.json @@ -1,14 +1,14 @@ { - "Restart_v2rayN": "正在重启,请等待...", - "Guidelines": "请从主应用运行!", - "Upgrade_File_Not_Found": "升级失败,文件不存在!", - "In_Progress": "正在进行中,请等待...", - "Try_Terminate_Process": "尝试结束 v2rayN 进程...", - "Failed_Terminate_Process": "请手动关闭正在运行的v2rayN,否则可能升级失败。", - "Start_Unzipping": "开始解压缩更新包...", - "Success_Unzipping": "解压缩更新包成功!", - "Failed_Unzipping": "解压缩更新包失败!", - "Failed_Upgrade": "升级失败!", - "Success_Upgrade": "升级成功!", - "Information": "提示" + "Restart_v2rayN": "正在重启,请等待...", + "Guidelines": "请从主应用运行!", + "Upgrade_File_Not_Found": "升级失败,文件不存在!", + "In_Progress": "正在进行中,请等待...", + "Try_Terminate_Process": "尝试结束 v2rayN 进程...", + "Failed_Terminate_Process": "请手动关闭正在运行的v2rayN,否则可能升级失败。", + "Start_Unzipping": "开始解压缩更新包...", + "Success_Unzipping": "解压缩更新包成功!", + "Failed_Unzipping": "解压缩更新包失败!", + "Failed_Upgrade": "升级失败!", + "Success_Upgrade": "升级成功!", + "Information": "提示" } \ No newline at end of file diff --git a/v2rayn/v2rayN/AmazTool/LocalizationHelper.cs b/v2rayn/v2rayN/AmazTool/LocalizationHelper.cs index 4af352c6ed..f10b8e3371 100644 --- a/v2rayn/v2rayN/AmazTool/LocalizationHelper.cs +++ b/v2rayn/v2rayN/AmazTool/LocalizationHelper.cs @@ -29,7 +29,7 @@ namespace AmazTool using var stream = assembly.GetManifestResourceStream(resourceName); if (stream == null) return; - + using StreamReader reader = new(stream); var json = reader.ReadToEnd(); if (!string.IsNullOrEmpty(json)) @@ -56,4 +56,4 @@ namespace AmazTool return _languageResources.TryGetValue(key, out var translation) ? translation : key; } } -} +} \ No newline at end of file diff --git a/v2rayn/v2rayN/AmazTool/UpgradeApp.cs b/v2rayn/v2rayN/AmazTool/UpgradeApp.cs index 9823996180..e8ab76f25f 100644 --- a/v2rayn/v2rayN/AmazTool/UpgradeApp.cs +++ b/v2rayn/v2rayN/AmazTool/UpgradeApp.cs @@ -9,7 +9,7 @@ namespace AmazTool public static void Upgrade(string fileName) { Console.WriteLine($"{LocalizationHelper.GetLocalizedValue("Start_Unzipping")}\n{fileName}"); - + Thread.Sleep(9000); if (!File.Exists(fileName)) diff --git a/v2rayn/v2rayN/ProtosLib/ProtosLib.csproj b/v2rayn/v2rayN/ProtosLib/ProtosLib.csproj deleted file mode 100644 index 0b22dfb863..0000000000 --- a/v2rayn/v2rayN/ProtosLib/ProtosLib.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - net8.0 - enable - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - diff --git a/v2rayn/v2rayN/ProtosLib/Statistics.proto b/v2rayn/v2rayN/ProtosLib/Statistics.proto deleted file mode 100644 index db96ac026c..0000000000 --- a/v2rayn/v2rayN/ProtosLib/Statistics.proto +++ /dev/null @@ -1,53 +0,0 @@ -syntax = "proto3"; - -package v2ray.core.app.stats.command; -option csharp_namespace = "ProtosLib.Statistics"; - -message GetStatsRequest { - // Name of the stat counter. - string name = 1; - // Whether or not to reset the counter to fetching its value. - bool reset = 2; -} - -message Stat { - string name = 1; - int64 value = 2; -} - -message GetStatsResponse { - Stat stat = 1; -} - -message QueryStatsRequest { - string pattern = 1; - bool reset = 2; -} - -message QueryStatsResponse { - repeated Stat stat = 1; -} - -message SysStatsRequest { -} - -message SysStatsResponse { - uint32 NumGoroutine = 1; - uint32 NumGC = 2; - uint64 Alloc = 3; - uint64 TotalAlloc = 4; - uint64 Sys = 5; - uint64 Mallocs = 6; - uint64 Frees = 7; - uint64 LiveObjects = 8; - uint64 PauseTotalNs = 9; - uint32 Uptime = 10; -} - -service StatsService { - rpc GetStats(GetStatsRequest) returns (GetStatsResponse) {} - rpc QueryStats(QueryStatsRequest) returns (QueryStatsResponse) {} - rpc GetSysStats(SysStatsRequest) returns (SysStatsResponse) {} -} - -message Config {} diff --git a/v2rayn/v2rayN/ProtosLib/Tests.cs b/v2rayn/v2rayN/ProtosLib/Tests.cs deleted file mode 100644 index e1eb85b165..0000000000 --- a/v2rayn/v2rayN/ProtosLib/Tests.cs +++ /dev/null @@ -1,13 +0,0 @@ -using ProtosLib.Statistics; - -namespace ProtosLib -{ - public class Tests - { - private StatsService.StatsServiceClient client_; - - public Tests() - { - } - } -} \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Global.cs b/v2rayn/v2rayN/ServiceLib/Global.cs index d0b037741b..cb2382d463 100644 --- a/v2rayn/v2rayN/ServiceLib/Global.cs +++ b/v2rayn/v2rayN/ServiceLib/Global.cs @@ -20,6 +20,7 @@ public const string JuicityCoreUrl = "https://github.com/juicity/juicity/releases"; public const string CustomRoutingListUrl = @"https://raw.githubusercontent.com/2dust/v2rayCustomRoutingList/master/"; public const string SingboxRulesetUrl = @"https://raw.githubusercontent.com/2dust/sing-box-rules/rule-set-{0}/{1}.srs"; + public const string IPAPIUrl = "https://ipapi.co/json"; public const string PromotionUrl = @"aHR0cHM6Ly85LjIzNDQ1Ni54eXovYWJjLmh0bWw="; public const string ConfigFileName = "guiNConfig.json"; diff --git a/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs b/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs index 377638cbf6..1c307d115a 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/StatisticsHandler.cs @@ -9,7 +9,7 @@ private ServerStatItem? _serverStatItem; private List _lstServerStat; private Action? _updateFunc; - //private StatisticsV2rayService? _statisticsV2Ray; + private StatisticsXrayService? _statisticsXray; private StatisticsSingboxService? _statisticsSingbox; @@ -26,7 +26,6 @@ await InitData(); - //_statisticsV2Ray = new StatisticsV2rayService(config, UpdateServerStatHandler); _statisticsXray = new StatisticsXrayService(config, UpdateServerStatHandler); _statisticsSingbox = new StatisticsSingboxService(config, UpdateServerStatHandler); } @@ -35,7 +34,6 @@ { try { - //_statisticsV2Ray?.Close(); _statisticsXray?.Close(); _statisticsSingbox?.Close(); } diff --git a/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingOSX.cs b/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingOSX.cs index 8ba1e0437b..6f19ffc867 100644 --- a/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingOSX.cs +++ b/v2rayn/v2rayN/ServiceLib/Handler/SysProxy/ProxySettingOSX.cs @@ -5,6 +5,7 @@ /* * 仅测试了,MacOS 13.7.1 x86 版本,其他版本有待确认 */ + /// /// 应用接口类型 /// @@ -21,14 +22,12 @@ await ExecCmd(lstCmd); } - public static async Task UnsetProxy() { var lstCmd = GetUnsetCmds(); await ExecCmd(lstCmd); } - private static async Task ExecCmd(List lstCmd) { foreach (var cmd in lstCmd) diff --git a/v2rayn/v2rayN/ServiceLib/Models/Config.cs b/v2rayn/v2rayN/ServiceLib/Models/Config.cs index 075f5049c4..c0abe5c2db 100644 --- a/v2rayn/v2rayN/ServiceLib/Models/Config.cs +++ b/v2rayn/v2rayN/ServiceLib/Models/Config.cs @@ -20,6 +20,7 @@ case ECoreType.Xray when RunningCoreType is ECoreType.Xray or ECoreType.v2fly or ECoreType.v2fly_v5: case ECoreType.sing_box when RunningCoreType is ECoreType.sing_box or ECoreType.mihomo: return true; + default: return false; } diff --git a/v2rayn/v2rayN/ServiceLib/Models/IPAPIInfo.cs b/v2rayn/v2rayN/ServiceLib/Models/IPAPIInfo.cs new file mode 100644 index 0000000000..07259d9593 --- /dev/null +++ b/v2rayn/v2rayN/ServiceLib/Models/IPAPIInfo.cs @@ -0,0 +1,13 @@ +namespace ServiceLib.Models +{ + internal class IPAPIInfo + { + public string? ip { get; set; } + public string? city { get; set; } + public string? region { get; set; } + public string? region_code { get; set; } + public string? country { get; set; } + public string? country_name { get; set; } + public string? country_code { get; set; } + } +} \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.Designer.cs b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.Designer.cs index a439d7c0f2..ea43a4efbd 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.Designer.cs +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.Designer.cs @@ -3644,7 +3644,7 @@ namespace ServiceLib.Resx { } /// - /// 查找类似 The ping of current service: {0} ms 的本地化字符串。 + /// 查找类似 The delay : {0} ms, {1} 的本地化字符串。 /// public static string TestMeOutput { get { diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx index 937d107fe9..f940823c78 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx @@ -302,7 +302,7 @@ اسکن URL وارد کردن با موفقیت - پینگ سرویس فعلی: {0} ms + پینگ سرویس فعلی: {0} ms, {1} موفقیت عملیات diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.resx index af6a2c9ee6..95a85755d7 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.resx @@ -302,7 +302,7 @@ Scan import the shared link successfully - The ping of current service: {0} ms + The delay : {0} ms, {1} Operation success diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.ru.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.ru.resx index 8758825cd1..4637717e7c 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.ru.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.ru.resx @@ -302,7 +302,7 @@ Сканирование URL-адреса импорта успешна. - Задержка текущего сервера: {0} мс + Задержка текущего сервера: {0} мс, {1} Операция успешна diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx index c281a4adc2..61c72dc50b 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx @@ -302,7 +302,7 @@ 扫描导入分享链接成功 - 当前服务的真连接延迟: {0} ms + 当前延迟: {0} ms,{1} 操作成功 diff --git a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx index 2d18ce2ebd..3d6e9777bc 100644 --- a/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx +++ b/v2rayn/v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx @@ -301,7 +301,7 @@ 掃描匯入分享链接成功 - 目前服務的真連線延遲: {0} ms + 目前延遲: {0} ms,{1} 操作成功 diff --git a/v2rayn/v2rayN/ServiceLib/ServiceLib.csproj b/v2rayn/v2rayN/ServiceLib/ServiceLib.csproj index 52c068dfc0..8a8fb5c689 100644 --- a/v2rayn/v2rayN/ServiceLib/ServiceLib.csproj +++ b/v2rayn/v2rayN/ServiceLib/ServiceLib.csproj @@ -49,7 +49,6 @@ - diff --git a/v2rayn/v2rayN/ServiceLib/Services/Statistics/StatisticsV2rayService.cs b/v2rayn/v2rayN/ServiceLib/Services/Statistics/StatisticsV2rayService.cs deleted file mode 100644 index 6641957624..0000000000 --- a/v2rayn/v2rayN/ServiceLib/Services/Statistics/StatisticsV2rayService.cs +++ /dev/null @@ -1,135 +0,0 @@ -using Grpc.Core; -using Grpc.Net.Client; -using ProtosLib.Statistics; - -namespace ServiceLib.Services.Statistics -{ - public class StatisticsV2rayService - { - private Models.Config _config; - private GrpcChannel? _channel; - private StatsService.StatsServiceClient? _client; - private bool _exitFlag; - private Action? _updateFunc; - - public StatisticsV2rayService(Models.Config config, Action updateFunc) - { - _config = config; - _updateFunc = updateFunc; - _exitFlag = false; - - GrpcInit(); - - Task.Run(Run); - } - - private void GrpcInit() - { - if (_channel is null) - { - try - { - _channel = GrpcChannel.ForAddress($"{Global.HttpProtocol}{Global.Loopback}:{AppHandler.Instance.StatePort}"); - _client = new StatsService.StatsServiceClient(_channel); - } - catch (Exception ex) - { - Logging.SaveLog(ex.Message, ex); - } - } - } - - public void Close() - { - _exitFlag = true; - } - - private async void Run() - { - while (!_exitFlag) - { - await Task.Delay(1000); - try - { - if (!_config.IsRunningCore(ECoreType.Xray)) - { - continue; - } - if (_channel?.State == ConnectivityState.Ready) - { - QueryStatsResponse? res = null; - try - { - if (_client != null) - res = await _client.QueryStatsAsync(new QueryStatsRequest() { Pattern = "", Reset = true }); - } - catch - { - } - - if (res != null) - { - ParseOutput(res.Stat, out ServerSpeedItem server); - _updateFunc?.Invoke(server); - } - } - if (_channel != null) - await _channel.ConnectAsync(); - } - catch - { - } - } - } - - private void ParseOutput(Google.Protobuf.Collections.RepeatedField source, out ServerSpeedItem server) - { - server = new(); - long aggregateProxyUp = 0; - long aggregateProxyDown = 0; - try - { - foreach (Stat stat in source) - { - string name = stat.Name; - long value = stat.Value / 1024; //KByte - string[] nStr = name.Split(">>>".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); - string type = ""; - - name = name.Trim(); - - name = nStr[1]; - type = nStr[3]; - - if (name.StartsWith(Global.ProxyTag)) - { - if (type == "uplink") - { - aggregateProxyUp += value; - } - else if (type == "downlink") - { - aggregateProxyDown += value; - } - } - else if (name == Global.DirectTag) - { - if (type == "uplink") - { - server.DirectUp = value; - } - else if (type == "downlink") - { - server.DirectDown = value; - } - } - } - server.ProxyUp = aggregateProxyUp; - server.ProxyDown = aggregateProxyDown; - } - catch - { - } - } - } -} \ No newline at end of file diff --git a/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs b/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs index 4eafc5c457..6474db7c68 100644 --- a/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs +++ b/v2rayn/v2rayN/ServiceLib/Services/UpdateService.cs @@ -244,8 +244,17 @@ namespace ServiceLib.Services public async Task RunAvailabilityCheck(Action updateFunc) { - var time = await new DownloadService().RunAvailabilityCheck(null); - updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time)); + var downloadHandle = new DownloadService(); + var time = await downloadHandle.RunAvailabilityCheck(null); + var ip = Global.None; + if (time > 0) + { + var result = await downloadHandle.TryDownloadString(Global.IPAPIUrl, true, "ipapi"); + var ipInfo = JsonUtils.Deserialize(result); + ip = $"({ipInfo?.country}) {ipInfo?.ip}"; + } + + updateFunc?.Invoke(false, string.Format(ResUI.TestMeOutput, time, ip)); } #region CheckUpdate private diff --git a/v2rayn/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs b/v2rayn/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs index f44d3926c6..65f79e0e73 100644 --- a/v2rayn/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs +++ b/v2rayn/v2rayN/v2rayN.Desktop/Views/AddServerWindow.axaml.cs @@ -209,7 +209,7 @@ namespace v2rayN.Desktop.Views this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Path, v => v.txtPath.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Extra, v => v.txtExtra.Text).DisposeWith(disposables); - + this.Bind(ViewModel, vm => vm.SelectedSource.StreamSecurity, v => v.cmbStreamSecurity.SelectedValue).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.SelectedValue).DisposeWith(disposables); diff --git a/v2rayn/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs b/v2rayn/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs index a0ac88f89b..eebc93621d 100644 --- a/v2rayn/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs +++ b/v2rayn/v2rayN/v2rayN.Desktop/Views/MainWindow.axaml.cs @@ -382,7 +382,7 @@ namespace v2rayN.Desktop.Views #endregion Event #region UI - + public void ShowHideWindow(bool? blShow) { var bl = blShow ?? !_config.UiItem.ShowInTaskbar; diff --git a/v2rayn/v2rayN/v2rayN.sln b/v2rayn/v2rayN/v2rayN.sln index f898d47e5e..ea0fd98543 100644 --- a/v2rayn/v2rayN/v2rayN.sln +++ b/v2rayn/v2rayN/v2rayN.sln @@ -5,8 +5,6 @@ VisualStudioVersion = 17.3.32811.315 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "v2rayN", "v2rayN\v2rayN.csproj", "{6DE127CA-1763-4236-B297-D2EF9CB2EC9B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProtosLib", "ProtosLib\ProtosLib.csproj", "{C5F24BB0-9CC1-44DD-82FF-D545F081819B}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PacLib", "PacLib\PacLib.csproj", "{EE4E6CD8-8353-446B-8F29-A841A02AE5EC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServiceLib", "ServiceLib\ServiceLib.csproj", "{1B6456C4-FFAA-4298-80F6-7B689A6E9243}" @@ -25,10 +23,6 @@ Global {6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Debug|Any CPU.Build.0 = Debug|Any CPU {6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Release|Any CPU.ActiveCfg = Release|Any CPU {6DE127CA-1763-4236-B297-D2EF9CB2EC9B}.Release|Any CPU.Build.0 = Release|Any CPU - {C5F24BB0-9CC1-44DD-82FF-D545F081819B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C5F24BB0-9CC1-44DD-82FF-D545F081819B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C5F24BB0-9CC1-44DD-82FF-D545F081819B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C5F24BB0-9CC1-44DD-82FF-D545F081819B}.Release|Any CPU.Build.0 = Release|Any CPU {EE4E6CD8-8353-446B-8F29-A841A02AE5EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EE4E6CD8-8353-446B-8F29-A841A02AE5EC}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE4E6CD8-8353-446B-8F29-A841A02AE5EC}.Release|Any CPU.ActiveCfg = Release|Any CPU diff --git a/v2rayn/v2rayN/v2rayN/App.xaml b/v2rayn/v2rayN/v2rayN/App.xaml index b22ea83be5..d78d082ccc 100644 --- a/v2rayn/v2rayN/v2rayN/App.xaml +++ b/v2rayn/v2rayN/v2rayN/App.xaml @@ -1,9 +1,9 @@  diff --git a/v2rayn/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs b/v2rayn/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs index 3d5985a4ed..7dd4651d94 100644 --- a/v2rayn/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs +++ b/v2rayn/v2rayN/v2rayN/Views/AddServerWindow.xaml.cs @@ -203,7 +203,7 @@ namespace v2rayN.Views this.Bind(ViewModel, vm => vm.SelectedSource.RequestHost, v => v.txtRequestHost.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Path, v => v.txtPath.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Extra, v => v.txtExtra.Text).DisposeWith(disposables); - + this.Bind(ViewModel, vm => vm.SelectedSource.StreamSecurity, v => v.cmbStreamSecurity.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.Sni, v => v.txtSNI.Text).DisposeWith(disposables); this.Bind(ViewModel, vm => vm.SelectedSource.AllowInsecure, v => v.cmbAllowInsecure.Text).DisposeWith(disposables); diff --git a/v2rayn/v2rayN/v2rayN/Views/ClashConnectionsView.xaml b/v2rayn/v2rayN/v2rayN/Views/ClashConnectionsView.xaml index e5781abec6..8ea9ca0b4d 100644 --- a/v2rayn/v2rayN/v2rayN/Views/ClashConnectionsView.xaml +++ b/v2rayn/v2rayN/v2rayN/Views/ClashConnectionsView.xaml @@ -1,11 +1,11 @@ { + NetworkType.TCP.type -> { val tcpSetting = TcpSettingsBean() if (headerType == AppConfig.HEADER_TYPE_HTTP) { tcpSetting.header.type = AppConfig.HEADER_TYPE_HTTP @@ -368,7 +376,7 @@ data class V2rayConfig( tcpSettings = tcpSetting } - "kcp" -> { + NetworkType.KCP.type -> { val kcpsetting = KcpSettingsBean() kcpsetting.header.type = headerType ?: "none" if (seed.isNullOrEmpty()) { @@ -379,7 +387,7 @@ data class V2rayConfig( kcpSettings = kcpsetting } - "ws" -> { + NetworkType.WS.type -> { val wssetting = WsSettingsBean() wssetting.headers.Host = host.orEmpty() sni = wssetting.headers.Host @@ -387,7 +395,7 @@ data class V2rayConfig( wsSettings = wssetting } - "httpupgrade" -> { + NetworkType.HTTP_UPGRADE.type -> { val httpupgradeSetting = HttpupgradeSettingsBean() httpupgradeSetting.host = host.orEmpty() sni = httpupgradeSetting.host @@ -395,7 +403,7 @@ data class V2rayConfig( httpupgradeSettings = httpupgradeSetting } - "splithttp","xhttp" -> { + NetworkType.SPLIT_HTTP.type, NetworkType.XHTTP.type -> { val xhttpSetting = XhttpSettingsBean() xhttpSetting.host = host.orEmpty() sni = xhttpSetting.host @@ -403,8 +411,8 @@ data class V2rayConfig( xhttpSettings = xhttpSetting } - "h2", "http" -> { - network = "h2" + NetworkType.H2.type, NetworkType.HTTP.type -> { + network = NetworkType.H2.type val h2Setting = HttpSettingsBean() h2Setting.host = host.orEmpty().split(",").map { it.trim() }.filter { it.isNotEmpty() } sni = h2Setting.host.getOrNull(0) ?: sni @@ -420,7 +428,7 @@ data class V2rayConfig( // quicSettings = quicsetting // } - "grpc" -> { + NetworkType.GRPC.type -> { val grpcSetting = GrpcSettingsBean() grpcSetting.multiMode = mode == "multi" grpcSetting.serviceName = serviceName.orEmpty() @@ -435,8 +443,14 @@ data class V2rayConfig( } fun populateTlsSettings( - streamSecurity: String, allowInsecure: Boolean, sni: String?, fingerprint: String?, alpns: String?, - publicKey: String?, shortId: String?, spiderX: String? + streamSecurity: String, + allowInsecure: Boolean, + sni: String?, + fingerprint: String?, + alpns: String?, + publicKey: String?, + shortId: String?, + spiderX: String? ) { security = streamSecurity val tlsSetting = TlsSettingsBean( @@ -544,7 +558,7 @@ data class V2rayConfig( ) { val transport = streamSettings?.network ?: return null return when (transport) { - "tcp" -> { + NetworkType.TCP.type -> { val tcpSetting = streamSettings?.tcpSettings ?: return null listOf( tcpSetting.header.type, @@ -553,7 +567,7 @@ data class V2rayConfig( ) } - "kcp" -> { + NetworkType.KCP.type -> { val kcpSetting = streamSettings?.kcpSettings ?: return null listOf( kcpSetting.header.type, @@ -562,7 +576,7 @@ data class V2rayConfig( ) } - "ws" -> { + NetworkType.WS.type -> { val wsSetting = streamSettings?.wsSettings ?: return null listOf( "", @@ -571,7 +585,7 @@ data class V2rayConfig( ) } - "httpupgrade" -> { + NetworkType.HTTP_UPGRADE.type -> { val httpupgradeSetting = streamSettings?.httpupgradeSettings ?: return null listOf( "", @@ -580,7 +594,7 @@ data class V2rayConfig( ) } - "splithttp" ,"xhttp"-> { + NetworkType.SPLIT_HTTP.type, NetworkType.XHTTP.type -> { val xhttpSettings = streamSettings?.xhttpSettings ?: return null listOf( "", @@ -589,7 +603,7 @@ data class V2rayConfig( ) } - "h2" -> { + NetworkType.H2.type -> { val h2Setting = streamSettings?.httpSettings ?: return null listOf( "", @@ -607,7 +621,7 @@ data class V2rayConfig( // ) // } - "grpc" -> { + NetworkType.GRPC.type -> { val grpcSetting = streamSettings?.grpcSettings ?: return null listOf( if (grpcSetting.multiMode == true) "multi" else "gun", diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt index d4d76161ef..2abbe639db 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/FmtBase.kt @@ -29,6 +29,38 @@ open class FmtBase { .associate { it.split("=").let { (k, v) -> k to Utils.urlDecode(v) } } } + fun getItemFormQuery(config: ProfileItem, queryParam: Map, allowInsecure: Boolean) { + config.network = queryParam["type"] ?: NetworkType.TCP.type + //TODO + if (config.network == NetworkType.SPLIT_HTTP.type) config.network = NetworkType.XHTTP.type + config.headerType = queryParam["headerType"] + config.host = queryParam["host"] + config.path = queryParam["path"] + + config.seed = queryParam["seed"] + config.quicSecurity = queryParam["quicSecurity"] + config.quicKey = queryParam["key"] + config.mode = queryParam["mode"] + config.serviceName = queryParam["serviceName"] + config.authority = queryParam["authority"] + config.xhttpMode = queryParam["mode"] + config.xhttpExtra = queryParam["extra"] + + config.security = queryParam["security"] + config.insecure = if (queryParam["allowInsecure"].isNullOrEmpty()) { + allowInsecure + } else { + queryParam["allowInsecure"].orEmpty() == "1" + } + config.sni = queryParam["sni"] + config.fingerPrint = queryParam["fp"] + config.alpn = queryParam["alpn"] + config.publicKey = queryParam["pbk"] + config.shortId = queryParam["sid"] + config.spiderX = queryParam["spx"] + config.flow = queryParam["flow"] + } + fun getQueryDic(config: ProfileItem): HashMap { val dicQuery = HashMap() dicQuery["security"] = config.security?.ifEmpty { "none" }.orEmpty() @@ -63,6 +95,7 @@ open class FmtBase { config.host.let { if (it.isNotNullEmpty()) dicQuery["host"] = it.orEmpty() } config.path.let { if (it.isNotNullEmpty()) dicQuery["path"] = it.orEmpty() } config.xhttpMode.let { if (it.isNotNullEmpty()) dicQuery["mode"] = it.orEmpty() } + config.xhttpExtra.let { if (it.isNotNullEmpty()) dicQuery["extra"] = it.orEmpty() } } NetworkType.HTTP, NetworkType.H2 -> { diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/ShadowsocksFmt.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/ShadowsocksFmt.kt index 1b47966a0c..860937a415 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/ShadowsocksFmt.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/ShadowsocksFmt.kt @@ -1,6 +1,7 @@ package com.v2ray.ang.fmt import com.v2ray.ang.dto.EConfigType +import com.v2ray.ang.dto.NetworkType import com.v2ray.ang.dto.ProfileItem import com.v2ray.ang.dto.V2rayConfig.OutboundBean import com.v2ray.ang.extension.idnHost @@ -38,7 +39,7 @@ object ShadowsocksFmt : FmtBase() { val queryParam = getQueryParam(uri) if (queryParam["plugin"] == "obfs-local" && queryParam["obfs"] == "http") { - config.network = "tcp" + config.network = NetworkType.TCP.type config.headerType = "http" config.host = queryParam["obfs-host"] config.path = queryParam["path"] diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/TrojanFmt.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/TrojanFmt.kt index 59c0ddb1f9..a760a7c81d 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/TrojanFmt.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/TrojanFmt.kt @@ -2,6 +2,7 @@ package com.v2ray.ang.fmt import com.v2ray.ang.AppConfig import com.v2ray.ang.dto.EConfigType +import com.v2ray.ang.dto.NetworkType import com.v2ray.ang.dto.ProfileItem import com.v2ray.ang.dto.V2rayConfig.OutboundBean import com.v2ray.ang.extension.idnHost @@ -22,37 +23,14 @@ object TrojanFmt : FmtBase() { config.password = uri.userInfo if (uri.rawQuery.isNullOrEmpty()) { - config.network = "tcp" + config.network = NetworkType.TCP.type config.security = AppConfig.TLS config.insecure = allowInsecure } else { val queryParam = getQueryParam(uri) - config.network = queryParam["type"] ?: "tcp" - config.headerType = queryParam["headerType"] - config.host = queryParam["host"] - config.path = queryParam["path"] - - config.seed = queryParam["seed"] - config.quicSecurity = queryParam["quicSecurity"] - config.quicKey = queryParam["key"] - config.mode = queryParam["mode"] - config.serviceName = queryParam["serviceName"] - config.authority = queryParam["authority"] - + getItemFormQuery(config, queryParam, allowInsecure) config.security = queryParam["security"] ?: AppConfig.TLS - config.insecure = if (queryParam["allowInsecure"].isNullOrEmpty()) { - allowInsecure - } else { - queryParam["allowInsecure"].orEmpty() == "1" - } - config.sni = queryParam["sni"] - config.fingerPrint = queryParam["fp"] - config.alpn = queryParam["alpn"] - config.publicKey = queryParam["pbk"] - config.shortId = queryParam["sid"] - config.spiderX = queryParam["spx"] - config.flow = queryParam["flow"] } return config diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt index b828ffacf9..07e80ed81c 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VlessFmt.kt @@ -6,6 +6,7 @@ import com.v2ray.ang.dto.ProfileItem import com.v2ray.ang.dto.V2rayConfig.OutboundBean import com.v2ray.ang.extension.idnHost import com.v2ray.ang.handler.MmkvManager +import com.v2ray.ang.util.JsonUtil import com.v2ray.ang.util.Utils import java.net.URI @@ -25,32 +26,7 @@ object VlessFmt : FmtBase() { config.password = uri.userInfo config.method = queryParam["encryption"] ?: "none" - config.network = queryParam["type"] ?: "tcp" - config.headerType = queryParam["headerType"] - config.host = queryParam["host"] - config.path = queryParam["path"] - - config.seed = queryParam["seed"] - config.quicSecurity = queryParam["quicSecurity"] - config.quicKey = queryParam["key"] - config.mode = queryParam["mode"] - config.serviceName = queryParam["serviceName"] - config.authority = queryParam["authority"] - config.xhttpMode = queryParam["mode"] - - config.security = queryParam["security"] - config.insecure = if (queryParam["allowInsecure"].isNullOrEmpty()) { - allowInsecure - } else { - queryParam["allowInsecure"].orEmpty() == "1" - } - config.sni = queryParam["sni"] - config.fingerPrint = queryParam["fp"] - config.alpn = queryParam["alpn"] - config.publicKey = queryParam["pbk"] - config.shortId = queryParam["sid"] - config.spiderX = queryParam["spx"] - config.flow = queryParam["flow"] + getItemFormQuery(config, queryParam, allowInsecure) return config } @@ -87,6 +63,7 @@ object VlessFmt : FmtBase() { profileItem.authority, ) outboundBean?.streamSettings?.xhttpSettings?.mode = profileItem.xhttpMode + outboundBean?.streamSettings?.xhttpSettings?.extra = JsonUtil.parseString(profileItem.xhttpExtra) outboundBean?.streamSettings?.populateTlsSettings( profileItem.security.orEmpty(), diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt index 1fc7a66f97..e4c4d2c96b 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/fmt/VmessFmt.kt @@ -48,7 +48,7 @@ object VmessFmt : FmtBase() { config.password = vmessQRCode.id config.method = if (TextUtils.isEmpty(vmessQRCode.scy)) AppConfig.DEFAULT_SECURITY else vmessQRCode.scy - config.network = vmessQRCode.net ?: "tcp" + config.network = vmessQRCode.net ?: NetworkType.TCP.type config.headerType = vmessQRCode.type config.host = vmessQRCode.host config.path = vmessQRCode.path @@ -137,23 +137,7 @@ object VmessFmt : FmtBase() { config.password = uri.userInfo config.method = AppConfig.DEFAULT_SECURITY - config.network = NetworkType.fromString(queryParam["type"]).name - config.headerType = queryParam["headerType"] - config.host = queryParam["host"] - config.path = queryParam["path"] - - config.seed = queryParam["seed"] - config.quicSecurity = queryParam["quicSecurity"] - config.quicKey = queryParam["key"] - config.mode = queryParam["mode"] - config.serviceName = queryParam["serviceName"] - config.authority = queryParam["authority"] - - config.security = queryParam["security"] - config.insecure = if ((queryParam["allowInsecure"].orEmpty()) == "1") true else allowInsecure - config.sni = queryParam["sni"] - config.fingerPrint = queryParam["fp"] - config.alpn = queryParam["alpn"] + getItemFormQuery(config, queryParam, allowInsecure) return config } diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/handler/AngConfigManager.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/handler/AngConfigManager.kt index d3eb675103..49adbcefe1 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/handler/AngConfigManager.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/handler/AngConfigManager.kt @@ -280,7 +280,7 @@ object AngConfigManager { val config = CustomFmt.parse(JsonUtil.toJson(srv)) ?: continue config.subscriptionId = subid val key = MmkvManager.encodeServerConfig("", config) - MmkvManager.encodeServerRaw(key, JsonUtil.toJsonPretty(srv)) + MmkvManager.encodeServerRaw(key, JsonUtil.toJsonPretty(srv)?:"") count += 1 } return count diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MigrateManager.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MigrateManager.kt index e8df77290f..a6b6341217 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MigrateManager.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/handler/MigrateManager.kt @@ -5,6 +5,7 @@ import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig.ANG_PACKAGE import com.v2ray.ang.dto.EConfigType +import com.v2ray.ang.dto.NetworkType import com.v2ray.ang.dto.ProfileItem import com.v2ray.ang.dto.ServerConfig import com.v2ray.ang.handler.MmkvManager.decodeServerConfig @@ -72,7 +73,7 @@ object MigrateManager { config.password = outbound.getPassword() config.flow = outbound?.settings?.vnext?.first()?.users?.first()?.flow ?: outbound?.settings?.servers?.first()?.flow - config.network = outbound?.streamSettings?.network ?: "tcp" + config.network = outbound?.streamSettings?.network ?: NetworkType.TCP.type outbound.getTransportSettingDetails()?.let { transportDetails -> config.headerType = transportDetails[0].orEmpty() config.host = transportDetails[1].orEmpty() diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt index dad69f32e0..f609a49ba8 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/ui/ServerActivity.kt @@ -24,7 +24,9 @@ import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_ADDRESS_V6 import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_MTU import com.v2ray.ang.R import com.v2ray.ang.dto.EConfigType +import com.v2ray.ang.dto.NetworkType import com.v2ray.ang.dto.ProfileItem +import com.v2ray.ang.extension.isNotNullEmpty import com.v2ray.ang.extension.toast import com.v2ray.ang.handler.MmkvManager import com.v2ray.ang.util.JsonUtil @@ -123,6 +125,8 @@ class ServerActivity : BaseActivity() { private val et_port_hop: EditText? by lazy { findViewById(R.id.et_port_hop) } private val et_port_hop_interval: EditText? by lazy { findViewById(R.id.et_port_hop_interval) } private val et_pinsha256: EditText? by lazy { findViewById(R.id.et_pinsha256) } + private val et_extra: EditText? by lazy { findViewById(R.id.et_extra) } + private val layout_extra: LinearLayout? by lazy { findViewById(R.id.layout_extra) } override fun onCreate(savedInstanceState: Bundle?) { @@ -156,16 +160,16 @@ class ServerActivity : BaseActivity() { sp_header_type?.adapter = adapter sp_header_type_title?.text = when (networks[position]) { - "grpc" -> getString(R.string.server_lab_mode_type) - "xhttp" -> getString(R.string.server_lab_xhttp_mode) + NetworkType.GRPC.type -> getString(R.string.server_lab_mode_type) + NetworkType.SPLIT_HTTP.type, NetworkType.XHTTP.type -> getString(R.string.server_lab_xhttp_mode) else -> getString(R.string.server_lab_head_type) }.orEmpty() sp_header_type?.setSelection( Utils.arrayFind( types, when (networks[position]) { - "grpc" -> config?.mode - "xhttp" -> config?.xhttpMode + NetworkType.GRPC.type -> config?.mode + NetworkType.SPLIT_HTTP.type, NetworkType.XHTTP.type -> config?.xhttpMode else -> config?.headerType }.orEmpty() ) @@ -174,15 +178,15 @@ class ServerActivity : BaseActivity() { et_request_host?.text = Utils.getEditable( when (networks[position]) { //"quic" -> config?.quicSecurity - "grpc" -> config?.authority + NetworkType.GRPC.type -> config?.authority else -> config?.host }.orEmpty() ) et_path?.text = Utils.getEditable( when (networks[position]) { - "kcp" -> config?.seed + NetworkType.KCP.type -> config?.seed //"quic" -> config?.quicKey - "grpc" -> config?.serviceName + NetworkType.GRPC.type -> config?.serviceName else -> config?.path }.orEmpty() ) @@ -190,13 +194,13 @@ class ServerActivity : BaseActivity() { tv_request_host?.text = Utils.getEditable( getString( when (networks[position]) { - "tcp" -> R.string.server_lab_request_host_http - "ws" -> R.string.server_lab_request_host_ws - "httpupgrade" -> R.string.server_lab_request_host_httpupgrade - "splithttp", "xhttp" -> R.string.server_lab_request_host_xhttp - "h2" -> R.string.server_lab_request_host_h2 + NetworkType.TCP.type -> R.string.server_lab_request_host_http + NetworkType.WS.type -> R.string.server_lab_request_host_ws + NetworkType.HTTP_UPGRADE.type -> R.string.server_lab_request_host_httpupgrade + NetworkType.SPLIT_HTTP.type, NetworkType.XHTTP.type -> R.string.server_lab_request_host_xhttp + NetworkType.H2.type -> R.string.server_lab_request_host_h2 //"quic" -> R.string.server_lab_request_host_quic - "grpc" -> R.string.server_lab_request_host_grpc + NetworkType.GRPC.type -> R.string.server_lab_request_host_grpc else -> R.string.server_lab_request_host } ) @@ -205,17 +209,29 @@ class ServerActivity : BaseActivity() { tv_path?.text = Utils.getEditable( getString( when (networks[position]) { - "kcp" -> R.string.server_lab_path_kcp - "ws" -> R.string.server_lab_path_ws - "httpupgrade" -> R.string.server_lab_path_httpupgrade - "splithttp", "xhttp" -> R.string.server_lab_path_xhttp - "h2" -> R.string.server_lab_path_h2 + NetworkType.KCP.type -> R.string.server_lab_path_kcp + NetworkType.WS.type -> R.string.server_lab_path_ws + NetworkType.HTTP_UPGRADE.type -> R.string.server_lab_path_httpupgrade + NetworkType.SPLIT_HTTP.type, NetworkType.XHTTP.type -> R.string.server_lab_path_xhttp + NetworkType.H2.type -> R.string.server_lab_path_h2 //"quic" -> R.string.server_lab_path_quic - "grpc" -> R.string.server_lab_path_grpc + NetworkType.GRPC.type -> R.string.server_lab_path_grpc else -> R.string.server_lab_path } ) ) + et_extra?.text = Utils.getEditable( + when (networks[position]) { + NetworkType.SPLIT_HTTP.type, NetworkType.XHTTP.type -> config?.xhttpExtra + else -> null + }.orEmpty() + ) + + layout_extra?.visibility = + when (networks[position]) { + NetworkType.SPLIT_HTTP.type, NetworkType.XHTTP.type -> View.VISIBLE + else -> View.GONE + } } override fun onNothingSelected(parent: AdapterView<*>?) { @@ -453,6 +469,12 @@ class ServerActivity : BaseActivity() { return false } } + if (et_extra?.text?.toString().isNotNullEmpty()) { + if (JsonUtil.parseString(et_extra?.text?.toString()) == null) { + toast(R.string.server_lab_xhttp_extra) + return false + } + } saveCommon(config) saveStreamSettings(config) @@ -461,7 +483,7 @@ class ServerActivity : BaseActivity() { if (config.subscriptionId.isEmpty() && !subscriptionId.isNullOrEmpty()) { config.subscriptionId = subscriptionId.orEmpty() } - Log.d(ANG_PACKAGE, JsonUtil.toJsonPretty(config)) + Log.d(ANG_PACKAGE, JsonUtil.toJsonPretty(config) ?: "") MmkvManager.encodeServerConfig(editGuid, config) toast(R.string.toast_success) finish() @@ -518,6 +540,7 @@ class ServerActivity : BaseActivity() { profileItem.serviceName = path profileItem.authority = requestHost profileItem.xhttpMode = transportTypes(networks[network])[type] + profileItem.xhttpExtra = et_extra?.text?.toString()?.trim() } private fun saveTls(config: ProfileItem) { @@ -549,19 +572,19 @@ class ServerActivity : BaseActivity() { private fun transportTypes(network: String?): Array { return when (network) { - "tcp" -> { + NetworkType.TCP.type -> { tcpTypes } - "kcp" -> { + NetworkType.KCP.type -> { kcpAndQuicTypes } - "grpc" -> { + NetworkType.GRPC.type -> { grpcModes } - "xhttp" -> { + NetworkType.SPLIT_HTTP.type, NetworkType.XHTTP.type -> { xhttpMode } diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/JsonUtil.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/JsonUtil.kt index b89b52ff36..28e7e9566e 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/JsonUtil.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/JsonUtil.kt @@ -2,6 +2,8 @@ package com.v2ray.ang.util import com.google.gson.Gson import com.google.gson.GsonBuilder +import com.google.gson.JsonObject +import com.google.gson.JsonParser import com.google.gson.JsonPrimitive import com.google.gson.JsonSerializationContext import com.google.gson.JsonSerializer @@ -15,11 +17,13 @@ object JsonUtil { return gson.toJson(src) } - fun fromJson(json: String, cls: Class): T { - return gson.fromJson(json, cls) + fun fromJson(src: String, cls: Class): T { + return gson.fromJson(src, cls) } - fun toJsonPretty(src: Any?): String { + fun toJsonPretty(src: Any?): String? { + if (src == null) + return null val gsonPre = GsonBuilder() .setPrettyPrinting() .disableHtmlEscaping() @@ -34,4 +38,15 @@ object JsonUtil { .create() return gsonPre.toJson(src) } + + fun parseString(src: String?): JsonObject? { + if (src == null) + return null + try { + return JsonParser.parseString(src).getAsJsonObject() + } catch (e: Exception) { + e.printStackTrace() + return null + } + } } \ No newline at end of file diff --git a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt index 58b6e05d19..69bdffd933 100644 --- a/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt +++ b/v2rayng/V2rayNG/app/src/main/java/com/v2ray/ang/util/Utils.kt @@ -295,7 +295,7 @@ object Utils { fun urlEncode(url: String): String { return try { - URLEncoder.encode(url, Charsets.UTF_8.toString()) + URLEncoder.encode(url, Charsets.UTF_8.toString()).replace("+", "%20") } catch (e: Exception) { e.printStackTrace() url diff --git a/v2rayng/V2rayNG/app/src/main/res/layout/layout_transport.xml b/v2rayng/V2rayNG/app/src/main/res/layout/layout_transport.xml index 103a36d389..bda1e11c2c 100644 --- a/v2rayng/V2rayNG/app/src/main/res/layout/layout_transport.xml +++ b/v2rayng/V2rayNG/app/src/main/res/layout/layout_transport.xml @@ -92,4 +92,26 @@ android:inputType="text" /> + + + + + + + \ No newline at end of file diff --git a/v2rayng/V2rayNG/app/src/main/res/values-ar/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-ar/strings.xml index 41042e19ac..eebe57a947 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-ar/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-ar/strings.xml @@ -120,6 +120,7 @@ Port Hopping Interval pinSHA256 XHTTP Mode + XHTTP Extra raw JSON, format: { XHTTPObject } جار التحميل diff --git a/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml index 0c09b1ccc6..620796d42f 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-bn/strings.xml @@ -119,6 +119,7 @@ Port Hopping Interval pinSHA256 XHTTP Mode + XHTTP Extra raw JSON, format: { XHTTPObject } লোড হচ্ছে diff --git a/v2rayng/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml index 8309964f15..250e9488fb 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-bqi-rIR/strings.xml @@ -37,7 +37,7 @@ کانفیگ سفارشی کانفیگ سفارشین ز کلیپ بورد و من بیار کانفیگ سفارشین ز مهلی و من بیار - کانفیگ سفارشین ز آدرس اینترنتی و من بیار + کانفیگ سفارشین ز آدرس اینترنتی و من بیار نشۊوی اینترنتی اسکن کانفیگ سفارشین بزݩ پاک بۊ؟ پؽش ز پاک کردن کانفیگ نا موئتبر قوۊل کوݩ! پاک کردن کانفیگن قوۊل اکۊنی؟ @@ -107,6 +107,7 @@ ازاف کردن دارایی ازاف کردن فایل ازاف کردن آدرس اینترنتی + اسکن QRcode آدرس اینترنتی دانلود فایلا آدرس اینترنتی دارایین ازاف کۊنین @@ -117,7 +118,8 @@ پورت گوم (درگا سرورن ز نۊ هؽل اکونه) فاسله پورت گوم (سانیه) pinSHA256 - XHTTP Mode + هالت XHTTP + XHTTP قلوه خام JSON، قالوو: { XHTTPObject } هون بارونی بۊ diff --git a/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml index db7a91f588..a15ba6fbbc 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-fa/strings.xml @@ -112,7 +112,8 @@ پورت پرش (درگاه سرور را بازنویسی می کند) فاصله پورت پرش (ثانیه) pinSHA256 - XHTTP Mode + حالت XHTTP + جیسون خام XHTTP Extra، فرمت: { XHTTPObject } URL را اضافه کنید diff --git a/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml index fd9c59cf9c..6c9084a7b6 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-ru/strings.xml @@ -54,14 +54,14 @@ Узел HTTP Узел WS Узел HTTPUpgrade - Узел SplitHTTP + Узел XHTTP Узел H2 Шифрование QUIC Полномочия gRPC Путь Путь WS Путь HTTPUpgrade - Путь SplitHTTP + Путь XHTTP Путь H2 Ключ QUIC Сид KCP @@ -83,7 +83,7 @@ ShortID SpiderX Закрытый ключ - Reserved (необязательно) + Reserved (необязательно, через запятую) Локальный адрес (необязательно, IPv4/IPv6 через запятую) MTU (необязательно, по умолчанию 1420) Успешно @@ -106,7 +106,7 @@ Добавить ресурс Добавить файлы Добавить URL - Сканирование QR-кода + Сканировать QR-код URL Загрузить файлы Добавить URL ресурса @@ -114,10 +114,11 @@ Название уже существует Это действие запрещено Пароль obfs - Переключение портов - Интервал переключения портов + Смена портов (переопределяет порт) + Интервал смены портов pinSHA256 - XHTTP Mode + Режим XHTTP + Необработанный JSON XHTTP Extra, формат: { XHTTPObject } Загрузка… diff --git a/v2rayng/V2rayNG/app/src/main/res/values-vi/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-vi/strings.xml index 27c78d8a98..1cdcd98cb1 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-vi/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-vi/strings.xml @@ -113,6 +113,7 @@ Port Hopping Interval pinSHA256 XHTTP Mode + XHTTP Extra raw JSON, format: { XHTTPObject } Thêm URL nội dung diff --git a/v2rayng/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml index dd82f33e9d..3254fc9d2b 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-zh-rCN/strings.xml @@ -113,6 +113,7 @@ 端口跳跃间隔(秒) SHA256证书指纹 XHTTP 模式 + XHTTP Extra 原始 JSON,格式: { XHTTPObject } 添加资产网址 diff --git a/v2rayng/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml index 1e64aba0a5..5334ef073a 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values-zh-rTW/strings.xml @@ -113,6 +113,7 @@ 連接埠跳躍間隔(秒) SHA256憑證指紋 XHTTP 模式 + XHTTP Extra 原始 JSON,格式: { XHTTPObject } 新增資產網址 diff --git a/v2rayng/V2rayNG/app/src/main/res/values/strings.xml b/v2rayng/V2rayNG/app/src/main/res/values/strings.xml index 3ac2cb297d..df17f257be 100644 --- a/v2rayng/V2rayNG/app/src/main/res/values/strings.xml +++ b/v2rayng/V2rayNG/app/src/main/res/values/strings.xml @@ -119,6 +119,7 @@ Port Hopping Interval pinSHA256 XHTTP Mode + XHTTP Extra raw JSON, format: { XHTTPObject } Loading diff --git a/v2rayng/V2rayNG/gradle/wrapper/gradle-wrapper.properties b/v2rayng/V2rayNG/gradle/wrapper/gradle-wrapper.properties index 20a15d0263..7e8d8ede1a 100644 --- a/v2rayng/V2rayNG/gradle/wrapper/gradle-wrapper.properties +++ b/v2rayng/V2rayNG/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Thu Nov 14 12:42:51 BDT 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/xray-core/go.mod b/xray-core/go.mod index f81174d744..c93cbb75a7 100644 --- a/xray-core/go.mod +++ b/xray-core/go.mod @@ -14,7 +14,7 @@ require ( github.com/pires/go-proxyproto v0.8.0 github.com/quic-go/quic-go v0.46.0 github.com/refraction-networking/utls v1.6.7 - github.com/sagernet/sing v0.5.0 + github.com/sagernet/sing v0.5.1 github.com/sagernet/sing-shadowsocks v0.2.7 github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 github.com/stretchr/testify v1.9.0 diff --git a/xray-core/go.sum b/xray-core/go.sum index d94428a830..fbad852bf8 100644 --- a/xray-core/go.sum +++ b/xray-core/go.sum @@ -54,8 +54,8 @@ github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= -github.com/sagernet/sing v0.5.0 h1:soo2wVwLcieKWWKIksFNK6CCAojUgAppqQVwyRYGkEM= -github.com/sagernet/sing v0.5.0/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing v0.5.1 h1:mhL/MZVq0TjuvHcpYcFtmSD1BFOxZ/+8ofbNZcg1k1Y= +github.com/sagernet/sing v0.5.1/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= github.com/seiflotfy/cuckoofilter v0.0.0-20240715131351-a2f2c23f1771 h1:emzAzMZ1L9iaKCTxdy3Em8Wv4ChIAGnfiz18Cda70g4= diff --git a/xray-core/infra/conf/common.go b/xray-core/infra/conf/common.go index ccd36d3d51..fd6e732a3c 100644 --- a/xray-core/infra/conf/common.go +++ b/xray-core/infra/conf/common.go @@ -42,6 +42,10 @@ type Address struct { net.Address } +func (v Address) MarshalJSON() ([]byte, error) { + return json.Marshal(v.Address.String()) +} + func (v *Address) UnmarshalJSON(data []byte) error { var rawStr string if err := json.Unmarshal(data, &rawStr); err != nil { diff --git a/yass/.github/workflows/releases-android-binary.yml b/yass/.github/workflows/releases-android-binary.yml index ee357e1b85..d28989746f 100644 --- a/yass/.github/workflows/releases-android-binary.yml +++ b/yass/.github/workflows/releases-android-binary.yml @@ -124,7 +124,7 @@ jobs: with: path: | ${{ env.SYSROOT }} - key: android-sysroot-${{ matrix.arch }}-v1-with-tzdata + key: android-sysroot-${{ matrix.arch }}-${{ hashFiles('scripts/get-android-sys.sh') }}-v1 - uses: actions/setup-go@v5 with: go-version: '>=1.20.0' @@ -196,10 +196,9 @@ jobs: if: ${{ matrix.arch == 'x86' || matrix.arch == 'x64' }} run: | # android sysimg doesn't like resolv.conf - mkdir -p $SYSROOT/sys $SYSROOT/etc/ssl/certs $SYSROOT/dev $SYSROOT/proc $SYSROOT/data/local/tmp + mkdir -p $SYSROOT/sys $SYSROOT/dev $SYSROOT/proc $SYSROOT/data/local/tmp bwrap --die-with-parent --ro-bind $SYSROOT / \ --ro-bind /sys /sys \ - --ro-bind /etc/ssl/certs /etc/ssl/certs \ --proc /proc --dev /dev \ --unshare-all --share-net \ --bind $PWD/build-android${{ matrix.apilevel }}-${{ matrix.arch }} /data/local/tmp \ diff --git a/yass/android/build.gradle b/yass/android/build.gradle index 2093c8e51c..0b519a9803 100644 --- a/yass/android/build.gradle +++ b/yass/android/build.gradle @@ -12,7 +12,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' + classpath 'com.android.tools.build:gradle:8.3.2' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/yass/android/gradle.properties b/yass/android/gradle.properties index 968c5ae4ce..983765fcd3 100644 --- a/yass/android/gradle.properties +++ b/yass/android/gradle.properties @@ -11,6 +11,9 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Sun May 28 17:34:07 CST 2023 +android.defaults.buildfeatures.buildconfig=false android.enableJetifier=false +android.nonFinalResIds=false +android.nonTransitiveRClass=false android.useAndroidX=true org.gradle.jvmargs=-Xmx4096M diff --git a/yass/android/yass/build.gradle b/yass/android/yass/build.gradle index 519b79cb30..86af72f9e6 100644 --- a/yass/android/yass/build.gradle +++ b/yass/android/yass/build.gradle @@ -2,6 +2,7 @@ apply plugin: 'com.android.application' android { compileSdkVersion rootProject.ext.compileSdkVersion + namespace 'it.gui.yass' def Properties properties = new Properties() properties.load(project.rootProject.file("local.properties").newDataInputStream()) @@ -71,6 +72,7 @@ android { } buildFeatures { viewBinding true + dataBinding true } packagingOptions { jniLibs { diff --git a/yass/android/yass/src/main/AndroidManifest.xml b/yass/android/yass/src/main/AndroidManifest.xml index e6cca9d33a..238ae7eaa5 100644 --- a/yass/android/yass/src/main/AndroidManifest.xml +++ b/yass/android/yass/src/main/AndroidManifest.xml @@ -1,6 +1,5 @@ - + diff --git a/yass/scripts/get-android-sys.sh b/yass/scripts/get-android-sys.sh index 4c5f5614be..f0a5817cd5 100755 --- a/yass/scripts/get-android-sys.sh +++ b/yass/scripts/get-android-sys.sh @@ -29,6 +29,7 @@ if [ "$WITH_ANDROID_IMG" -a ! -d out/sysroot-build/android/"$WITH_ANDROID_IMG"/s mkdir -p $SYSROOT/system/bin $SYSROOT/system/etc cp -v $WITH_ANDROID_IMG/mount/bin/linker* $SYSROOT/system/bin cp -v $WITH_ANDROID_IMG/mount/etc/hosts $SYSROOT/system/etc + cp -rv $WITH_ANDROID_IMG/mount/etc/security $SYSROOT/system/etc cp -rv $WITH_ANDROID_IMG/mount/lib* $SYSROOT/system mkdir -p $SYSROOT/system/usr/share cp -rv $WITH_ANDROID_IMG/mount/usr/share/zoneinfo $SYSROOT/system/usr/share/ diff --git a/yass/src/net/asio_ssl.cpp b/yass/src/net/asio_ssl.cpp index c4b8149705..64d8e105cb 100644 --- a/yass/src/net/asio_ssl.cpp +++ b/yass/src/net/asio_ssl.cpp @@ -20,7 +20,7 @@ #include "core/utils.hpp" #include "net/x509_util.hpp" -#ifdef _WIN32 +#if BUILDFLAG(IS_WIN) #include #undef X509_NAME #elif BUILDFLAG(IS_MAC) @@ -32,9 +32,9 @@ #include "third_party/boringssl/src/pki/parse_name.h" #include "third_party/boringssl/src/pki/parsed_certificate.h" #include "third_party/boringssl/src/pki/trust_store.h" -#endif +#endif // BUILDFLAG(IS_MAC) -#if defined(_WIN32) +#if BUILDFLAG(IS_WIN) #define DIR_HASH_SEPARATOR ';' #else #define DIR_HASH_SEPARATOR ':' @@ -43,19 +43,85 @@ ABSL_FLAG(bool, ca_native, false, "Load CA certs from the OS."); std::ostream& operator<<(std::ostream& o, asio::error_code ec) { -#ifdef _WIN32 +#if BUILDFLAG(IS_WIN) return o << ec.message() << " value: " << ec.value(); #else return o << ec.message(); #endif } +void print_openssl_error() { + const char* file; + int line; + while (uint32_t error = ERR_get_error_line(&file, &line)) { + char buf[120]; + ERR_error_string_n(error, buf, sizeof(buf)); + ::gurl_base::logging::LogMessage(file, line, ::gurl_base::logging::LOGGING_ERROR).stream() + << "OpenSSL error: " << buf; + } +} + +static bool found_isrg_root_x1 = false; +static bool found_isrg_root_x2 = false; +static bool found_digicert_root_g2 = false; +static bool found_gts_root_r4 = false; + +static bool load_ca_to_x509_store_from_cert(X509_STORE* store, bssl::UniquePtr cert) { + char buf[4096] = {}; + const char* const subject_name = X509_NAME_oneline(X509_get_subject_name(cert.get()), buf, sizeof(buf)); + + if (X509_cmp_current_time(X509_get0_notBefore(cert.get())) < 0 && + X509_cmp_current_time(X509_get0_notAfter(cert.get())) >= 0) { + // look at the CN field for ISRG Root X1 and ISRG_Root X2 ca certificates + int lastpos = -1; + for (;;) { + lastpos = X509_NAME_get_index_by_NID(X509_get_subject_name(cert.get()), NID_commonName, lastpos); + if (lastpos == -1) { + break; + } + + X509_NAME_ENTRY* entry = X509_NAME_get_entry(X509_get_subject_name(cert.get()), lastpos); + + const ASN1_STRING* value = X509_NAME_ENTRY_get_data(entry); + std::string_view commonName((const char*)ASN1_STRING_get0_data(value), ASN1_STRING_length(value)); + using std::string_view_literals::operator""sv; + if (commonName == "ISRG Root X1"sv) { + VLOG(1) << "Loading ISRG Root X1 CA"; + found_isrg_root_x1 = true; + } + if (commonName == "ISRG Root X2"sv) { + VLOG(1) << "Loading ISRG Root X2 CA"; + found_isrg_root_x2 = true; + } + if (commonName == "DigiCert Global Root G2"sv) { + VLOG(1) << "Loading DigiCert Global Root G2 CA"; + found_digicert_root_g2 = true; + } + if (commonName == "GTS Root R4"sv) { + VLOG(1) << "Loading GTS Root R4 CA"; + found_gts_root_r4 = true; + } + } + + if (X509_STORE_add_cert(store, cert.get()) == 1) { + VLOG(2) << "Loaded ca: " << subject_name; + return true; + } else { + print_openssl_error(); + LOG(WARNING) << "Loading ca failure with: " << subject_name; + } + } else { + LOG(WARNING) << "Ignore inactive cert: " << subject_name; + } + return false; +} + +namespace { + #if BUILDFLAG(IS_MAC) using namespace gurl_base::apple; -namespace { - // The rules for interpreting trust settings are documented at: // https://developer.apple.com/reference/security/1400261-sectrustsettingscopytrustsetting?language=objc @@ -239,396 +305,7 @@ bool IsNotAcceptableIntermediate(const bssl::ParsedCertificate* cert, const CFSt return false; } -} // namespace -#endif - -static bool found_isrg_root_x1 = false; -static bool found_isrg_root_x2 = false; -static bool found_digicert_root_g2 = false; -static bool found_gts_root_r4 = false; - -void print_openssl_error() { - const char* file; - int line; - while (uint32_t error = ERR_get_error_line(&file, &line)) { - char buf[120]; - ERR_error_string_n(error, buf, sizeof(buf)); - ::gurl_base::logging::LogMessage(file, line, ::gurl_base::logging::LOGGING_ERROR).stream() - << "OpenSSL error: " << buf; - } -} - -static bool load_ca_cert_to_x509_trust(X509_STORE* store, bssl::UniquePtr cert) { - char buf[4096] = {}; - const char* const subject_name = X509_NAME_oneline(X509_get_subject_name(cert.get()), buf, sizeof(buf)); - - if (X509_cmp_current_time(X509_get0_notBefore(cert.get())) < 0 && - X509_cmp_current_time(X509_get0_notAfter(cert.get())) >= 0) { - // look at the CN field for ISRG Root X1 and ISRG_Root X2 ca certificates - int lastpos = -1; - for (;;) { - lastpos = X509_NAME_get_index_by_NID(X509_get_subject_name(cert.get()), NID_commonName, lastpos); - if (lastpos == -1) { - break; - } - - X509_NAME_ENTRY* entry = X509_NAME_get_entry(X509_get_subject_name(cert.get()), lastpos); - - const ASN1_STRING* value = X509_NAME_ENTRY_get_data(entry); - std::string_view commonName((const char*)ASN1_STRING_get0_data(value), ASN1_STRING_length(value)); - using std::string_view_literals::operator""sv; - if (commonName == "ISRG Root X1"sv) { - VLOG(1) << "Loading ISRG Root X1 CA"; - found_isrg_root_x1 = true; - } - if (commonName == "ISRG Root X2"sv) { - VLOG(1) << "Loading ISRG Root X2 CA"; - found_isrg_root_x2 = true; - } - if (commonName == "DigiCert Global Root G2"sv) { - VLOG(1) << "Loading DigiCert Global Root G2 CA"; - found_digicert_root_g2 = true; - } - if (commonName == "GTS Root R4"sv) { - VLOG(1) << "Loading GTS Root R4 CA"; - found_gts_root_r4 = true; - } - } - - if (X509_STORE_add_cert(store, cert.get()) == 1) { - VLOG(2) << "Loaded ca: " << subject_name; - return true; - } else { - print_openssl_error(); - LOG(WARNING) << "Loading ca failure with: " << subject_name; - } - } else { - LOG(WARNING) << "Ignore inactive cert: " << subject_name; - } - return false; -} - -static bool load_ca_content_to_x509_trust(X509_STORE* store, std::string_view cacert) { - bssl::UniquePtr bio(BIO_new_mem_buf(cacert.data(), cacert.size())); - bssl::UniquePtr cert(PEM_read_bio_X509(bio.get(), nullptr, 0, nullptr)); - if (!cert) { - print_openssl_error(); - LOG(WARNING) << "Loading ca failure: with " << cacert; - return false; - } - return load_ca_cert_to_x509_trust(store, std::move(cert)); -} - -static constexpr std::string_view kEndCertificateMark = "-----END CERTIFICATE-----\n"; -int load_ca_to_ssl_ctx_from_mem(SSL_CTX* ssl_ctx, std::string_view cadata) { - X509_STORE* store = nullptr; - int count = 0; - store = SSL_CTX_get_cert_store(ssl_ctx); - if (!store) { - LOG(WARNING) << "Can't get SSL CTX cert store"; - goto out; - } - for (size_t pos = 0, end = pos; end < cadata.size(); pos = end) { - end = cadata.find(kEndCertificateMark, pos); - if (end == std::string_view::npos) { - break; - } - end += kEndCertificateMark.size(); - - std::string_view cacert = cadata.substr(pos, end - pos); - if (load_ca_content_to_x509_trust(store, cacert)) { - ++count; - } - } - -out: - VLOG(2) << "Loaded ca from memory: " << count << " certificates"; - return count; -} - -static int load_ca_to_ssl_ctx_bundle(SSL_CTX* ssl_ctx, const std::string& bundle_path) { - PlatformFile pf = OpenReadFile(bundle_path); - if (pf == gurl_base::kInvalidPlatformFile) { - return 0; - } - gurl_base::MemoryMappedFile mappedFile; - // take ownship of pf - if (!(mappedFile.Initialize(pf, gurl_base::MemoryMappedFile::Region::kWholeFile))) { - LOG(ERROR) << "Couldn't mmap file: " << bundle_path; - return 0; // To debug http://crbug.com/445616. - } - - std::string_view buffer(reinterpret_cast(mappedFile.data()), mappedFile.length()); - - return load_ca_to_ssl_ctx_from_mem(ssl_ctx, buffer); -} - -static int load_ca_to_ssl_ctx_path(SSL_CTX* ssl_ctx, const std::string& dir_path) { - int count = 0; - -#ifdef _WIN32 - std::wstring wdir_path = SysUTF8ToWide(dir_path); - _WDIR* dir; - struct _wdirent* dent; - dir = _wopendir(wdir_path.c_str()); - if (dir != nullptr) { - while ((dent = _wreaddir(dir)) != nullptr) { - if (dent->d_type != DT_REG && dent->d_type != DT_LNK) { - continue; - } - std::filesystem::path wca_bundle = std::filesystem::path(wdir_path) / dent->d_name; - std::string ca_bundle = SysWideToUTF8(wca_bundle); - int result = load_ca_to_ssl_ctx_bundle(ssl_ctx, ca_bundle); - if (result > 0) { - VLOG(1) << "Loaded cert from: " << ca_bundle << " with " << result << " certificates"; - count += result; - } - } - _wclosedir(dir); - } -#else - DIR* dir; - struct dirent* dent; - dir = opendir(dir_path.c_str()); - if (dir != nullptr) { - while ((dent = readdir(dir)) != nullptr) { - if (dent->d_type != DT_REG && dent->d_type != DT_LNK) { - continue; - } - if (dent->d_name[0] == '.') { - continue; - } - std::string ca_bundle = absl::StrCat(dir_path, "/", dent->d_name); - int result = load_ca_to_ssl_ctx_bundle(ssl_ctx, ca_bundle); - if (result > 0) { - VLOG(1) << "Loaded ca cert from: " << ca_bundle << " with " << result << " certificates"; - count += result; - } - } - closedir(dir); - } -#endif - - return count; -} - -static bool load_ca_to_ssl_ctx_yass_ca_bundle(SSL_CTX* ssl_ctx) { -#ifdef _WIN32 -#define CA_BUNDLE L"yass-ca-bundle.crt" - // The windows version will automatically look for a CA certs file named 'ca-bundle.crt', - // either in the same directory as yass.exe, or in the Current Working Directory, - // or in any folder along your PATH. - - std::vector wca_bundles; - - // 1. search under executable directory - std::wstring exe_path; - CHECK(GetExecutablePath(&exe_path)); - std::filesystem::path exe_dir = std::filesystem::path(exe_path).parent_path(); - - wca_bundles.push_back(exe_dir / CA_BUNDLE); - - // 2. search under current directory - std::wstring current_dir; - { - wchar_t buf[32767]; - DWORD ret = GetCurrentDirectoryW(sizeof(buf), buf); - if (ret == 0) { - PLOG(FATAL) << "GetCurrentDirectoryW failed"; - } - // the return value specifies the number of characters that are written to - // the buffer, not including the terminating null character. - current_dir = std::wstring(buf, ret); - } - - wca_bundles.push_back(std::filesystem::path(current_dir) / CA_BUNDLE); - - // 3. search under path directory - std::string path; - { - wchar_t buf[32767]; - DWORD ret = GetEnvironmentVariableW(L"PATH", buf, sizeof(buf)); - if (ret == 0) { - PLOG(FATAL) << "GetEnvironmentVariableW failed on PATH"; - } - // the return value is the number of characters stored in the buffer pointed - // to by lpBuffer, not including the terminating null character. - path = SysWideToUTF8(std::wstring(buf, ret)); - } - std::vector paths = absl::StrSplit(path, DIR_HASH_SEPARATOR); - for (const auto& path : paths) { - if (path.empty()) - continue; - wca_bundles.push_back(std::filesystem::path(path) / CA_BUNDLE); - } - - for (const auto& wca_bundle : wca_bundles) { - auto ca_bundle = SysWideToUTF8(wca_bundle); - VLOG(1) << "Attempt to load ca bundle from: " << ca_bundle; - int result = load_ca_to_ssl_ctx_bundle(ssl_ctx, ca_bundle); - if (result > 0) { - LOG(INFO) << "Loaded ca bundle from: " << ca_bundle << " with " << result << " certificates"; - return true; - } - } -#undef CA_BUNDLE -#endif - - return false; -} - -static bool load_ca_to_ssl_ctx_cacert(SSL_CTX* ssl_ctx) { - bool loaded = false; - int count = 0; - if (absl::GetFlag(FLAGS_ca_native)) { - loaded = true; - int result = load_ca_to_ssl_ctx_system(ssl_ctx); - if (!result) { - LOG(WARNING) << "Loading ca bundle failure from system"; - } - count += result; - } - std::string ca_bundle = absl::GetFlag(FLAGS_cacert); - if (!ca_bundle.empty()) { - loaded = true; - int result = load_ca_to_ssl_ctx_bundle(ssl_ctx, ca_bundle); - if (result) { - LOG(INFO) << "Loaded ca bundle from: " << ca_bundle << " with " << result << " certificates"; - count += result; - } else { - print_openssl_error(); - LOG(WARNING) << "Loading ca bundle failure from: " << ca_bundle; - } - } - std::string ca_path = absl::GetFlag(FLAGS_capath); - if (!ca_path.empty()) { - loaded = true; - std::vector paths = absl::StrSplit(ca_path, DIR_HASH_SEPARATOR); - for (const auto& path : paths) { - int result = load_ca_to_ssl_ctx_path(ssl_ctx, path); - if (result) { - LOG(INFO) << "Loaded ca from directory: " << path << " with " << result << " certificates"; - count += result; - } else { - LOG(WARNING) << "Loading ca directory failure from: " << path; - } - } - } - return loaded; -} - -#ifdef _WIN32 -// Returns true if the cert can be used for server authentication, based on -// certificate properties. -// -// While there are a variety of certificate properties that can affect how -// trust is computed, the main property is CERT_ENHKEY_USAGE_PROP_ID, which -// is intersected with the certificate's EKU extension (if present). -// The intersection is documented in the Remarks section of -// CertGetEnhancedKeyUsage, and is as follows: -// - No EKU property, and no EKU extension = Trusted for all purpose -// - Either an EKU property, or EKU extension, but not both = Trusted only -// for the listed purposes -// - Both an EKU property and an EKU extension = Trusted for the set -// intersection of the listed purposes -// CertGetEnhancedKeyUsage handles this logic, and if an empty set is -// returned, the distinction between the first and third case can be -// determined by GetLastError() returning CRYPT_E_NOT_FOUND. -// -// See: -// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certgetenhancedkeyusage -// -// If we run into any errors reading the certificate properties, we fail -// closed. -bool IsCertTrustedForServerAuth(PCCERT_CONTEXT cert) { - DWORD usage_size = 0; - - if (!CertGetEnhancedKeyUsage(cert, 0, nullptr, &usage_size)) { - return false; - } - - std::vector usage_bytes(usage_size); - CERT_ENHKEY_USAGE* usage = reinterpret_cast(usage_bytes.data()); - if (!CertGetEnhancedKeyUsage(cert, 0, usage, &usage_size)) { - return false; - } - - if (usage->cUsageIdentifier == 0) { - // check GetLastError - HRESULT error_code = GetLastError(); - - switch (error_code) { - case CRYPT_E_NOT_FOUND: - return true; - case S_OK: - return false; - default: - return false; - } - } - for (DWORD i = 0; i < usage->cUsageIdentifier; i++) { - std::string_view eku = std::string_view(usage->rgpszUsageIdentifier[i]); - if ((eku == szOID_PKIX_KP_SERVER_AUTH) || (eku == szOID_ANY_ENHANCED_KEY_USAGE)) { - return true; - } - } - return false; -} - -int load_ca_to_ssl_store_from_schannel_store(X509_STORE* store, HCERTSTORE cert_store) { - PCCERT_CONTEXT cert_context = NULL; - int count = 0; - - while ((cert_context = CertEnumCertificatesInStore(cert_store, cert_context))) { - const char* data = reinterpret_cast(cert_context->pbCertEncoded); - size_t len = cert_context->cbCertEncoded; - bssl::UniquePtr buffer = net::x509_util::CreateCryptoBuffer(std::string_view(data, len)); - bssl::UniquePtr cert(X509_parse_from_buffer(buffer.get())); - if (!cert) { - print_openssl_error(); - LOG(WARNING) << "Loading ca failure from: cert store"; - continue; - } - if (!IsCertTrustedForServerAuth(cert_context)) { - char buf[4096] = {}; - const char* const subject_name = X509_NAME_oneline(X509_get_subject_name(cert.get()), buf, sizeof(buf)); - LOG(WARNING) << "Skip cert without server auth support: " << subject_name; - continue; - } - if (load_ca_cert_to_x509_trust(store, std::move(cert))) { - ++count; - } - } - - return count; -} - -void GatherEnterpriseCertsForLocation(LPCSTR provider, HCERTSTORE cert_store, DWORD location, LPCWSTR store_name) { - if (!(location == CERT_SYSTEM_STORE_LOCAL_MACHINE || location == CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY || - location == CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE || location == CERT_SYSTEM_STORE_CURRENT_USER || - location == CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY)) { - return; - } - - DWORD flags = location | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG; - - HCERTSTORE enterprise_root_store = NULL; - - enterprise_root_store = CertOpenStore(provider, 0, NULL, flags, store_name); - if (!enterprise_root_store) { - return; - } - // Priority of the opened cert store in the collection does not matter, so set - // everything to priority 0. - CertAddStoreToCollection(cert_store, enterprise_root_store, - /*dwUpdateFlags=*/0, /*dwPriority=*/0); - if (!CertCloseStore(enterprise_root_store, 0)) { - PLOG(WARNING) << "CertCloseStore() call failed"; - } -} -#endif // _WIN32 -#if BUILDFLAG(IS_MAC) -int load_ca_to_ssl_store_from_sec_trust_domain(X509_STORE* store, SecTrustSettingsDomain domain) { +int load_ca_to_x509_store_from_sec_trust_domain(X509_STORE* store, SecTrustSettingsDomain domain) { const CFStringRef policy_oid = kSecPolicyAppleSSL; CFArrayRef certs; OSStatus err; @@ -694,7 +371,7 @@ int load_ca_to_ssl_store_from_sec_trust_domain(X509_STORE* store, SecTrustSettin continue; } - if (load_ca_cert_to_x509_trust(store, std::move(cert))) { + if (load_ca_to_x509_store_from_cert(store, std::move(cert))) { ++count; } } @@ -705,10 +382,399 @@ out: VLOG(1) << "Loaded ca from SecTrust: " << count << " certificates at domain 0x" << std::hex << domain; return count; } + #endif // BUILDFLAG(IS_MAC) -int load_ca_to_ssl_ctx_system(SSL_CTX* ssl_ctx) { -#ifdef _WIN32 +int load_ca_to_ssl_ctx_from_bundle(SSL_CTX* ssl_ctx, const std::string& bundle_path) { + PlatformFile pf = OpenReadFile(bundle_path); + if (pf == gurl_base::kInvalidPlatformFile) { + return 0; + } + gurl_base::MemoryMappedFile mappedFile; + // take ownship of pf + if (!(mappedFile.Initialize(pf, gurl_base::MemoryMappedFile::Region::kWholeFile))) { + LOG(ERROR) << "Couldn't mmap file: " << bundle_path; + return 0; // To debug http://crbug.com/445616. + } + + std::string_view buffer(reinterpret_cast(mappedFile.data()), mappedFile.length()); + + return load_ca_to_ssl_ctx_from_mem(ssl_ctx, buffer); +} + +int load_ca_to_ssl_ctx_from_directory(SSL_CTX* ssl_ctx, const std::string& dir_path) { + int count = 0; + +#if BUILDFLAG(IS_WIN) + std::wstring wdir_path = SysUTF8ToWide(dir_path); + _WDIR* dir; + struct _wdirent* dent; + dir = _wopendir(wdir_path.c_str()); + if (dir != nullptr) { + while ((dent = _wreaddir(dir)) != nullptr) { + if (dent->d_type != DT_REG && dent->d_type != DT_LNK) { + continue; + } + std::filesystem::path wca_bundle = std::filesystem::path(wdir_path) / dent->d_name; + std::string ca_bundle = SysWideToUTF8(wca_bundle); + int result = load_ca_to_ssl_ctx_from_bundle(ssl_ctx, ca_bundle); + if (result > 0) { + VLOG(1) << "Loaded cert from: " << ca_bundle << " with " << result << " certificates"; + count += result; + } + } + _wclosedir(dir); + } +#else // BUILDFLAG(IS_WIN) + DIR* dir; + struct dirent* dent; + dir = opendir(dir_path.c_str()); + if (dir != nullptr) { + while ((dent = readdir(dir)) != nullptr) { + if (dent->d_type != DT_REG && dent->d_type != DT_LNK) { + continue; + } + if (dent->d_name[0] == '.') { + continue; + } + std::string ca_bundle = absl::StrCat(dir_path, "/", dent->d_name); + int result = load_ca_to_ssl_ctx_from_bundle(ssl_ctx, ca_bundle); + if (result > 0) { + VLOG(1) << "Loaded ca cert from: " << ca_bundle << " with " << result << " certificates"; + count += result; + } + } + closedir(dir); + } +#endif // BUILDFLAG(IS_WIN) + + return count; +} + +#if BUILDFLAG(IS_WIN) +// Returns true if the cert can be used for server authentication, based on +// certificate properties. +// +// While there are a variety of certificate properties that can affect how +// trust is computed, the main property is CERT_ENHKEY_USAGE_PROP_ID, which +// is intersected with the certificate's EKU extension (if present). +// The intersection is documented in the Remarks section of +// CertGetEnhancedKeyUsage, and is as follows: +// - No EKU property, and no EKU extension = Trusted for all purpose +// - Either an EKU property, or EKU extension, but not both = Trusted only +// for the listed purposes +// - Both an EKU property and an EKU extension = Trusted for the set +// intersection of the listed purposes +// CertGetEnhancedKeyUsage handles this logic, and if an empty set is +// returned, the distinction between the first and third case can be +// determined by GetLastError() returning CRYPT_E_NOT_FOUND. +// +// See: +// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certgetenhancedkeyusage +// +// If we run into any errors reading the certificate properties, we fail +// closed. +bool IsCertTrustedForServerAuth(PCCERT_CONTEXT cert) { + DWORD usage_size = 0; + + if (!CertGetEnhancedKeyUsage(cert, 0, nullptr, &usage_size)) { + return false; + } + + std::vector usage_bytes(usage_size); + CERT_ENHKEY_USAGE* usage = reinterpret_cast(usage_bytes.data()); + if (!CertGetEnhancedKeyUsage(cert, 0, usage, &usage_size)) { + return false; + } + + if (usage->cUsageIdentifier == 0) { + // check GetLastError + HRESULT error_code = GetLastError(); + + switch (error_code) { + case CRYPT_E_NOT_FOUND: + return true; + case S_OK: + return false; + default: + return false; + } + } + for (DWORD i = 0; i < usage->cUsageIdentifier; i++) { + std::string_view eku = std::string_view(usage->rgpszUsageIdentifier[i]); + if ((eku == szOID_PKIX_KP_SERVER_AUTH) || (eku == szOID_ANY_ENHANCED_KEY_USAGE)) { + return true; + } + } + return false; +} + +int load_ca_to_x509_store_from_schannel_store(X509_STORE* store, HCERTSTORE cert_store) { + PCCERT_CONTEXT cert_context = NULL; + int count = 0; + + while ((cert_context = CertEnumCertificatesInStore(cert_store, cert_context))) { + const char* data = reinterpret_cast(cert_context->pbCertEncoded); + size_t len = cert_context->cbCertEncoded; + bssl::UniquePtr buffer = net::x509_util::CreateCryptoBuffer(std::string_view(data, len)); + bssl::UniquePtr cert(X509_parse_from_buffer(buffer.get())); + if (!cert) { + print_openssl_error(); + LOG(WARNING) << "Loading ca failure from: cert store"; + continue; + } + if (!IsCertTrustedForServerAuth(cert_context)) { + char buf[4096] = {}; + const char* const subject_name = X509_NAME_oneline(X509_get_subject_name(cert.get()), buf, sizeof(buf)); + LOG(WARNING) << "Skip cert without server auth support: " << subject_name; + continue; + } + if (load_ca_to_x509_store_from_cert(store, std::move(cert))) { + ++count; + } + } + + return count; +} + +void GatherEnterpriseCertsForLocation(LPCSTR provider, HCERTSTORE cert_store, DWORD location, LPCWSTR store_name) { + if (!(location == CERT_SYSTEM_STORE_LOCAL_MACHINE || location == CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY || + location == CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE || location == CERT_SYSTEM_STORE_CURRENT_USER || + location == CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY)) { + return; + } + + DWORD flags = location | CERT_STORE_OPEN_EXISTING_FLAG | CERT_STORE_READONLY_FLAG; + + HCERTSTORE enterprise_root_store = NULL; + + enterprise_root_store = CertOpenStore(provider, 0, NULL, flags, store_name); + if (!enterprise_root_store) { + return; + } + // Priority of the opened cert store in the collection does not matter, so set + // everything to priority 0. + CertAddStoreToCollection(cert_store, enterprise_root_store, + /*dwUpdateFlags=*/0, /*dwPriority=*/0); + if (!CertCloseStore(enterprise_root_store, 0)) { + PLOG(WARNING) << "CertCloseStore() call failed"; + } +} +#endif // BUILDFLAG(IS_WIN) + +#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_IOS) +int load_ca_to_ssl_ctx_from_unix_store(SSL_CTX* ssl_ctx) { + int count = 0; + // cert list copied from golang src/crypto/x509/root_unix.go + static const char* ca_bundle_paths[] = { +#if BUILDFLAG(IS_LINUX) + "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. + "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL + "/etc/ssl/ca-bundle.pem", // OpenSUSE + "/etc/pki/tls/cacert.pem", // OpenELEC + "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7 + "/etc/ssl/cert.pem", // Alpine Linux +#endif +#if BUILDFLAG(IS_BSD) + "/usr/local/etc/ssl/cert.pem", // FreeBSD + "/etc/ssl/cert.pem", // OpenBSD + "/usr/local/share/certs/ca-root-nss.crt", // DragonFly + "/etc/openssl/certs/ca-certificates.crt", // NetBSD +#endif +#if BUILDFLAG(IS_SOLARIS) + "/etc/certs/ca-certificates.crt", // Solaris 11.2+ + "/etc/ssl/certs/ca-certificates.crt", // Joyent SmartOS + "/etc/ssl/cacert.pem", // OmniOS +#endif + }; + for (auto ca_bundle : ca_bundle_paths) { + int result = load_ca_to_ssl_ctx_from_bundle(ssl_ctx, ca_bundle); + if (result > 0) { + LOG(INFO) << "Loaded ca bundle from: " << ca_bundle << " with " << result << " certificates"; + count += result; + break; + } + } + static const char* ca_paths[] = { +#if BUILDFLAG(IS_LINUX) + "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139 + "/etc/pki/tls/certs", // Fedora/RHEL +#endif +#if BUILDFLAG(IS_OHOS) + "/etc/ssl/certs", // OpenHarmony +#endif +#if BUILDFLAG(IS_ANDROID) + "/system/etc/security/cacerts", // Android system roots + "/data/misc/keychain/certs-added", // User trusted CA folder +#endif +#if BUILDFLAG(IS_BSD) + "/etc/ssl/certs", // FreeBSD 12.2+ + "/usr/local/share/certs", // FreeBSD + "/etc/openssl/certs", // NetBSD +#endif +#if BUILDFLAG(IS_SOLARIS) + "/etc/certs/CA", // Solaris +#endif + }; + + for (auto ca_path : ca_paths) { + int result = load_ca_to_ssl_ctx_from_directory(ssl_ctx, ca_path); + if (result > 0) { + LOG(INFO) << "Loaded ca from directory: " << ca_path << " with " << result << " certificates"; + count += result; + } + } + return count; +} +#endif // !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_IOS) + +bool load_ca_to_ssl_ctx_cacert(SSL_CTX* ssl_ctx) { + bool loaded = false; + int count = 0; + if (absl::GetFlag(FLAGS_ca_native)) { + loaded = true; + int result = load_ca_to_ssl_ctx_from_system(ssl_ctx); + if (!result) { + LOG(WARNING) << "Loading ca bundle failure from system"; + } + count += result; + } + std::string ca_bundle = absl::GetFlag(FLAGS_cacert); + if (!ca_bundle.empty()) { + loaded = true; + int result = load_ca_to_ssl_ctx_from_bundle(ssl_ctx, ca_bundle); + if (result) { + LOG(INFO) << "Loaded ca bundle from: " << ca_bundle << " with " << result << " certificates"; + count += result; + } else { + print_openssl_error(); + LOG(WARNING) << "Loading ca bundle failure from: " << ca_bundle; + } + } + std::string ca_path = absl::GetFlag(FLAGS_capath); + if (!ca_path.empty()) { + loaded = true; + std::vector paths = absl::StrSplit(ca_path, DIR_HASH_SEPARATOR); + for (const auto& path : paths) { + int result = load_ca_to_ssl_ctx_from_directory(ssl_ctx, path); + if (result) { + LOG(INFO) << "Loaded ca from directory: " << path << " with " << result << " certificates"; + count += result; + } else { + LOG(WARNING) << "Loading ca directory failure from: " << path; + } + } + } + return loaded; +} + +bool load_ca_to_ssl_ctx_yass_ca_bundle(SSL_CTX* ssl_ctx) { +#if BUILDFLAG(IS_WIN) +#define CA_BUNDLE L"yass-ca-bundle.crt" + // The windows version will automatically look for a CA certs file named 'ca-bundle.crt', + // either in the same directory as yass.exe, or in the Current Working Directory, + // or in any folder along your PATH. + + std::vector wca_bundles; + + // 1. search under executable directory + std::wstring exe_path; + CHECK(GetExecutablePath(&exe_path)); + std::filesystem::path exe_dir = std::filesystem::path(exe_path).parent_path(); + + wca_bundles.push_back(exe_dir / CA_BUNDLE); + + // 2. search under current directory + std::wstring current_dir; + { + wchar_t buf[32767]; + DWORD ret = GetCurrentDirectoryW(sizeof(buf), buf); + if (ret == 0) { + PLOG(FATAL) << "GetCurrentDirectoryW failed"; + } + // the return value specifies the number of characters that are written to + // the buffer, not including the terminating null character. + current_dir = std::wstring(buf, ret); + } + + wca_bundles.push_back(std::filesystem::path(current_dir) / CA_BUNDLE); + + // 3. search under path directory + std::string path; + { + wchar_t buf[32767]; + DWORD ret = GetEnvironmentVariableW(L"PATH", buf, sizeof(buf)); + if (ret == 0) { + PLOG(FATAL) << "GetEnvironmentVariableW failed on PATH"; + } + // the return value is the number of characters stored in the buffer pointed + // to by lpBuffer, not including the terminating null character. + path = SysWideToUTF8(std::wstring(buf, ret)); + } + std::vector paths = absl::StrSplit(path, DIR_HASH_SEPARATOR); + for (const auto& path : paths) { + if (path.empty()) + continue; + wca_bundles.push_back(std::filesystem::path(path) / CA_BUNDLE); + } + + for (const auto& wca_bundle : wca_bundles) { + auto ca_bundle = SysWideToUTF8(wca_bundle); + VLOG(1) << "Attempt to load ca bundle from: " << ca_bundle; + int result = load_ca_to_ssl_ctx_from_bundle(ssl_ctx, ca_bundle); + if (result > 0) { + LOG(INFO) << "Loaded ca bundle from: " << ca_bundle << " with " << result << " certificates"; + return true; + } + } +#undef CA_BUNDLE +#endif // BUILDFLAG(IS_WIN) + + return false; +} + +bool load_ca_to_x509_store_from_string(X509_STORE* store, std::string_view cacert) { + bssl::UniquePtr bio(BIO_new_mem_buf(cacert.data(), cacert.size())); + bssl::UniquePtr cert(PEM_read_bio_X509(bio.get(), nullptr, 0, nullptr)); + if (!cert) { + print_openssl_error(); + LOG(WARNING) << "Loading ca failure: with " << cacert; + return false; + } + return load_ca_to_x509_store_from_cert(store, std::move(cert)); +} + +} // namespace + +int load_ca_to_ssl_ctx_from_mem(SSL_CTX* ssl_ctx, std::string_view cadata) { + static constexpr std::string_view kEndCertificateMark = "-----END CERTIFICATE-----\n"; + X509_STORE* store = nullptr; + int count = 0; + store = SSL_CTX_get_cert_store(ssl_ctx); + if (!store) { + LOG(WARNING) << "Can't get SSL CTX cert store"; + goto out; + } + for (size_t pos = 0, end = pos; end < cadata.size(); pos = end) { + end = cadata.find(kEndCertificateMark, pos); + if (end == std::string_view::npos) { + break; + } + end += kEndCertificateMark.size(); + + std::string_view cacert = cadata.substr(pos, end - pos); + if (load_ca_to_x509_store_from_string(store, cacert)) { + ++count; + } + } + +out: + VLOG(2) << "Loaded ca from memory: " << count << " certificates"; + return count; +} + +int load_ca_to_ssl_ctx_from_system(SSL_CTX* ssl_ctx) { +#if BUILDFLAG(IS_WIN) HCERTSTORE root_store = NULL; int count = 0; @@ -742,7 +808,7 @@ int load_ca_to_ssl_ctx_system(SSL_CTX* ssl_ctx) { GatherEnterpriseCertsForLocation(CERT_STORE_PROV_SYSTEM_W, root_store, CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, L"CA"); - count = load_ca_to_ssl_store_from_schannel_store(store, root_store); + count = load_ca_to_x509_store_from_schannel_store(store, root_store); if (!CertCloseStore(root_store, 0)) { PLOG(WARNING) << "CertCloseStore() call failed"; @@ -758,9 +824,9 @@ out: LOG(WARNING) << "Can't get SSL CTX cert store"; goto out; } - count += load_ca_to_ssl_store_from_sec_trust_domain(store, kSecTrustSettingsDomainSystem); - count += load_ca_to_ssl_store_from_sec_trust_domain(store, kSecTrustSettingsDomainAdmin); - count += load_ca_to_ssl_store_from_sec_trust_domain(store, kSecTrustSettingsDomainUser); + count += load_ca_to_x509_store_from_sec_trust_domain(store, kSecTrustSettingsDomainSystem); + count += load_ca_to_x509_store_from_sec_trust_domain(store, kSecTrustSettingsDomainAdmin); + count += load_ca_to_x509_store_from_sec_trust_domain(store, kSecTrustSettingsDomainUser); out: LOG(INFO) << "Loaded ca from SecTrust: " << count << " certificates"; @@ -768,68 +834,12 @@ out: #elif BUILDFLAG(IS_IOS) return 0; #else - int count = 0; - // cert list copied from golang src/crypto/x509/root_unix.go - static const char* ca_bundle_paths[] = { -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) - "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. - "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL - "/etc/ssl/ca-bundle.pem", // OpenSUSE - "/etc/pki/tls/cacert.pem", // OpenELEC - "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7 - "/etc/ssl/cert.pem", // Alpine Linux -#endif -#if BUILDFLAG(IS_BSD) - "/usr/local/etc/ssl/cert.pem", // FreeBSD - "/etc/ssl/cert.pem", // OpenBSD - "/usr/local/share/certs/ca-root-nss.crt", // DragonFly - "/etc/openssl/certs/ca-certificates.crt", // NetBSD -#endif -#if BUILDFLAG(IS_SOLARIS) - "/etc/certs/ca-certificates.crt", // Solaris 11.2+ - "/etc/ssl/certs/ca-certificates.crt", // Joyent SmartOS - "/etc/ssl/cacert.pem", // OmniOS -#endif - }; - for (auto ca_bundle : ca_bundle_paths) { - int result = load_ca_to_ssl_ctx_bundle(ssl_ctx, ca_bundle); - if (result > 0) { - LOG(INFO) << "Loaded ca bundle from: " << ca_bundle << " with " << result << " certificates"; - count += result; - } - } - static const char* ca_paths[] = { -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) - "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139 - "/etc/pki/tls/certs", // Fedora/RHEL -#endif -#if BUILDFLAG(IS_ANDROID) - "/system/etc/security/cacerts", // Android system roots - "/data/misc/keychain/certs-added", // User trusted CA folder -#endif -#if BUILDFLAG(IS_BSD) - "/etc/ssl/certs", // FreeBSD 12.2+ - "/usr/local/share/certs", // FreeBSD - "/etc/openssl/certs", // NetBSD -#endif -#if BUILDFLAG(IS_SOLARIS) - "/etc/certs/CA", // Solaris -#endif - }; - - for (auto ca_path : ca_paths) { - int result = load_ca_to_ssl_ctx_path(ssl_ctx, ca_path); - if (result > 0) { - LOG(INFO) << "Loaded ca from directory: " << ca_path << " with " << result << " certificates"; - count += result; - } - } - return count; + return load_ca_to_ssl_ctx_from_unix_store(ssl_ctx); #endif } -int load_ca_to_ssl_ctx_system_extra(SSL_CTX* ssl_ctx) { -#ifdef _WIN32 +int load_ca_to_ssl_ctx_from_system_extra(SSL_CTX* ssl_ctx) { +#if BUILDFLAG(IS_WIN) HCERTSTORE root_store = NULL; int count = 0; @@ -867,7 +877,7 @@ int load_ca_to_ssl_ctx_system_extra(SSL_CTX* ssl_ctx) { GatherEnterpriseCertsForLocation(CERT_STORE_PROV_SYSTEM_REGISTRY_W, root_store, CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY, L"CA"); - count = load_ca_to_ssl_store_from_schannel_store(store, root_store); + count = load_ca_to_x509_store_from_schannel_store(store, root_store); if (!CertCloseStore(root_store, 0)) { PLOG(WARNING) << "CertCloseStore() call failed"; @@ -883,8 +893,8 @@ out: LOG(WARNING) << "Can't get SSL CTX cert store"; goto out; } - count += load_ca_to_ssl_store_from_sec_trust_domain(store, kSecTrustSettingsDomainAdmin); - count += load_ca_to_ssl_store_from_sec_trust_domain(store, kSecTrustSettingsDomainUser); + count += load_ca_to_x509_store_from_sec_trust_domain(store, kSecTrustSettingsDomainAdmin); + count += load_ca_to_x509_store_from_sec_trust_domain(store, kSecTrustSettingsDomainUser); out: LOG(INFO) << "Loaded user-added ca from SecTrust: " << count << " certificates"; @@ -892,63 +902,7 @@ out: #elif BUILDFLAG(IS_IOS) return 0; #else - int count = 0; - // cert list copied from golang src/crypto/x509/root_unix.go - static const char* ca_bundle_paths[] = { -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) - "/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc. - "/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL - "/etc/ssl/ca-bundle.pem", // OpenSUSE - "/etc/pki/tls/cacert.pem", // OpenELEC - "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7 - "/etc/ssl/cert.pem", // Alpine Linux -#endif -#if BUILDFLAG(IS_BSD) - "/usr/local/etc/ssl/cert.pem", // FreeBSD - "/etc/ssl/cert.pem", // OpenBSD - "/usr/local/share/certs/ca-root-nss.crt", // DragonFly - "/etc/openssl/certs/ca-certificates.crt", // NetBSD -#endif -#if BUILDFLAG(IS_SOLARIS) - "/etc/certs/ca-certificates.crt", // Solaris 11.2+ - "/etc/ssl/certs/ca-certificates.crt", // Joyent SmartOS - "/etc/ssl/cacert.pem", // OmniOS -#endif - }; - for (auto ca_bundle : ca_bundle_paths) { - int result = load_ca_to_ssl_ctx_bundle(ssl_ctx, ca_bundle); - if (result > 0) { - LOG(INFO) << "Loaded ca bundle from: " << ca_bundle << " with " << result << " certificates"; - count += result; - } - } - static const char* ca_paths[] = { -#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS) - "/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139 - "/etc/pki/tls/certs", // Fedora/RHEL -#endif -#if BUILDFLAG(IS_ANDROID) - "/system/etc/security/cacerts", // Android system roots - "/data/misc/keychain/certs-added", // User trusted CA folder -#endif -#if BUILDFLAG(IS_BSD) - "/etc/ssl/certs", // FreeBSD 12.2+ - "/usr/local/share/certs", // FreeBSD - "/etc/openssl/certs", // NetBSD -#endif -#if BUILDFLAG(IS_SOLARIS) - "/etc/certs/CA", // Solaris -#endif - }; - - for (auto ca_path : ca_paths) { - int result = load_ca_to_ssl_ctx_path(ssl_ctx, ca_path); - if (result > 0) { - LOG(INFO) << "Loaded ca from directory: " << ca_path << " with " << result << " certificates"; - count += result; - } - } - return count; + return load_ca_to_ssl_ctx_from_unix_store(ssl_ctx); #endif } @@ -971,7 +925,7 @@ void load_ca_to_ssl_ctx(SSL_CTX* ssl_ctx) { goto done; } - load_ca_to_ssl_ctx_system_extra(ssl_ctx); + load_ca_to_ssl_ctx_from_system_extra(ssl_ctx); { std::string_view ca_bundle_content(_binary_ca_bundle_crt_start, _binary_ca_bundle_crt_end - _binary_ca_bundle_crt_start); diff --git a/yass/src/net/asio_ssl_internal.hpp b/yass/src/net/asio_ssl_internal.hpp index 632f488a7f..0a777a8d2b 100644 --- a/yass/src/net/asio_ssl_internal.hpp +++ b/yass/src/net/asio_ssl_internal.hpp @@ -15,7 +15,7 @@ extern "C" const char _binary_supplementary_ca_bundle_crt_start[]; extern "C" const char _binary_supplementary_ca_bundle_crt_end[]; int load_ca_to_ssl_ctx_from_mem(SSL_CTX* ssl_ctx, std::string_view cadata); -int load_ca_to_ssl_ctx_system(SSL_CTX* ssl_ctx); -int load_ca_to_ssl_ctx_system_extra(SSL_CTX* ssl_ctx); +int load_ca_to_ssl_ctx_from_system(SSL_CTX* ssl_ctx); +int load_ca_to_ssl_ctx_from_system_extra(SSL_CTX* ssl_ctx); #endif // H_NET_ASIO_SSL_INTERNAL diff --git a/yass/src/net/asio_ssl_test.cpp b/yass/src/net/asio_ssl_test.cpp index 5e2e1ca091..3c78c7c53e 100644 --- a/yass/src/net/asio_ssl_test.cpp +++ b/yass/src/net/asio_ssl_test.cpp @@ -30,7 +30,7 @@ TEST(SSL_TEST, LoadSupplementaryCaBundle) { TEST(SSL_TEST, LoadSystemCa) { bssl::UniquePtr ssl_ctx; ssl_ctx.reset(::SSL_CTX_new(::TLS_client_method())); - int result = load_ca_to_ssl_ctx_system(ssl_ctx.get()); + int result = load_ca_to_ssl_ctx_from_system(ssl_ctx.get()); #if BUILDFLAG(IS_IOS) // we don't test on iOS GTEST_SKIP() << "skipped as system is not supported";