auto generate cert keys

This commit is contained in:
Alireza Ahmadi
2024-06-13 20:16:04 +02:00
parent d057076251
commit b144aecb6a
11 changed files with 215 additions and 20 deletions
+66 -4
View File
@@ -30,9 +30,23 @@
>{{ $t('tls.useText') }}</v-btn>
</v-btn-toggle>
</v-col>
<v-spacer></v-spacer>
<v-col cols="auto">
<v-btn
variant="tonal"
density="compact"
icon="mdi-key-star"
@click="genECH"
:loading="loading">
<v-icon />
<v-tooltip activator="parent" location="top">
{{ $t('actions.generate') }}
</v-tooltip>
</v-btn>
</v-col>
</v-row>
<v-row v-if="useEchPath == 0">
<v-col cols="12" sm="6">
<v-col cols="12">
<v-text-field
:label="$t('tls.keyPath')"
hide-details
@@ -41,19 +55,21 @@
</v-col>
</v-row>
<v-row v-else>
<v-col cols="12" sm="6">
<v-col cols="12">
<v-textarea
:label="$t('tls.key')"
hide-details
rows="3"
v-model="echKeyText">
</v-textarea>
</v-col>
</v-row>
<v-row>
<v-col cols="12" sm="6">
<v-col cols="12">
<v-textarea
:label="$t('tls.cert')"
hide-details
rows="3"
v-model="echConfigText">
</v-textarea>
</v-col>
@@ -63,15 +79,61 @@
</template>
<script lang="ts">
import { i18n } from '@/locales'
import HttpUtils from '@/plugins/httputil'
import { ech } from '@/types/inTls'
import { push } from 'notivue'
export default {
props: ['iTls','oTls'],
data() {
return {
useEchPath: 0
useEchPath: 0,
loading: false,
}
},
methods: {
async genECH(){
this.loading = true
const msg = await HttpUtils.get('api/keypairs', { k: "ech", o: this.iTls.server_name?? "''" })
this.loading = false
if (msg.success && this.iTls.ech && this.oTls.ech) {
this.iTls.ech.key_path=undefined
this.useEchPath = 1
if (msg.obj.length>0){
let config = <string[]>[]
let key = <string[]>[]
let isConfig = false
let isKey = false
msg.obj.forEach((line:string) => {
if (line === "-----BEGIN ECH CONFIGS-----") {
isConfig = true
isKey = false
} else if (line === "-----END ECH CONFIGS-----") {
isConfig = false
} else if (line === "-----BEGIN ECH KEYS-----") {
isKey = true
isConfig = false
} else if (line === "-----END ECH KEYS-----") {
isKey = false
} else if (isConfig) {
config.push(line)
} else if (isKey) {
key.push(line)
}
})
this.iTls.ech.key = key?? undefined
this.oTls.ech.config = config?? undefined
} else {
push.error({
message: i18n.global.t('error') + ": " + msg.obj
})
}
}
},
},
computed: {
ech() {
return <ech>this.$props.iTls.ech
+108 -6
View File
@@ -90,6 +90,20 @@
>{{ $t('tls.useText') }}</v-btn>
</v-btn-toggle>
</v-col>
<v-spacer></v-spacer>
<v-col cols="auto">
<v-btn
variant="tonal"
density="compact"
icon="mdi-key-star"
@click="genSelfSigned"
:loading="loading">
<v-icon />
<v-tooltip activator="parent" location="top">
{{ $t('actions.generate') }}
</v-tooltip>
</v-btn>
</v-col>
</v-row>
<v-row v-if="usePath == 0">
<v-col cols="12" sm="6">
@@ -108,14 +122,14 @@
</v-col>
</v-row>
<v-row v-else>
<v-col cols="12" sm="6">
<v-col cols="12">
<v-textarea
:label="$t('tls.cert')"
hide-details
v-model="certText">
</v-textarea>
</v-col>
<v-col cols="12" sm="6">
<v-col cols="12">
<v-textarea
:label="$t('tls.key')"
hide-details
@@ -158,26 +172,42 @@
v-model="server_port">
</v-text-field>
</v-col>
<v-spacer></v-spacer>
<v-col cols="auto">
<v-btn
variant="tonal"
density="compact"
icon="mdi-key-star"
@click="genRealityKey"
:loading="loading">
<v-icon />
<v-tooltip activator="parent" location="top">
{{ $t('actions.generate') }}
</v-tooltip>
</v-btn>
</v-col>
</v-row>
<v-row>
<v-col cols="12" md="6">
<v-col cols="12">
<v-text-field
:label="$t('tls.privKey')"
hide-details
v-model="inTls.reality.private_key">
</v-text-field>
</v-col>
<v-col cols="12" md="6">
<v-col cols="12">
<v-text-field
:label="$t('tls.pubKey')"
hide-details
v-model="outTls.reality.public_key">
</v-text-field>
</v-col>
<v-col cols="12" md="4">
<v-col cols="12">
<v-text-field
label="Short IDs"
hide-details
append-icon="mdi-refresh"
@click:append="randomSID"
v-model="short_id">
</v-text-field>
</v-col>
@@ -261,6 +291,10 @@ import { iTls, defaultInTls } from '@/types/inTls'
import { oTls, defaultOutTls } from '@/types/outTls'
import AcmeVue from '@/components/Acme.vue'
import EchVue from '@/components/Ech.vue'
import HttpUtils from '@/plugins/httputil'
import { push } from 'notivue'
import { i18n } from '@/locales'
import RandomUtil from '@/plugins/randomUtil'
export default {
props: ['visible', 'data', 'index'],
emits: ['close', 'save'],
@@ -334,7 +368,10 @@ export default {
},
changeTlsType(){
if (this.tlsType) {
this.tls.server = <iTls>{ enabled: true, reality: { enabled: true, handshake: { server_port: 443 } }, server_name: "" }
this.tls.server = <iTls>{
enabled: true,
reality: { enabled: true, handshake: { server_port: 443 }, short_id: RandomUtil.randomShortId() },
server_name: "" }
this.tls.client = <oTls>{ reality: { public_key: "" } }
} else {
this.tls.server = <iTls>{ enabled: true }
@@ -350,6 +387,71 @@ export default {
this.$emit('save', this.tls)
this.loading = false
},
async genSelfSigned(){
this.loading = true
const msg = await HttpUtils.get('api/keypairs', { k: "tls", o: this.inTls.server_name?? "''" })
this.loading = false
if (msg.success) {
this.inTls.key_path=undefined
this.inTls.certificate_path=undefined
this.usePath = 1
if (msg.obj.length>0){
let privateKey = <string[]>[]
let publicKey = <string[]>[]
let isPrivateKey = false
let isPublicKey = false
msg.obj.forEach((line:string) => {
if (line === "-----BEGIN PRIVATE KEY-----") {
isPrivateKey = true
isPublicKey = false
} else if (line === "-----END PRIVATE KEY-----") {
isPrivateKey = false
} else if (line === "-----BEGIN CERTIFICATE-----") {
isPublicKey = true
isPrivateKey = false
} else if (line === "-----END CERTIFICATE-----") {
isPublicKey = false
} else if (isPrivateKey) {
privateKey.push(line)
} else if (isPublicKey) {
publicKey.push(line)
}
})
this.inTls.key = privateKey?? undefined
this.inTls.certificate = publicKey?? undefined
} else {
push.error({
message: i18n.global.t('error') + ": " + msg.obj
})
}
}
},
async genRealityKey(){
this.loading = true
const msg = await HttpUtils.get('api/keypairs', { k: "reality" })
this.loading = false
if (msg.success) {
msg.obj.forEach((line:string) => {
if (this.inTls.reality && this.outTls.reality){
if (line.startsWith("PrivateKey")){
this.inTls.reality.private_key = line.substring(12)
}
if (line.startsWith("PublicKey")){
this.outTls.reality.public_key = line.substring(11)
}
}
})
} else {
push.error({
message: i18n.global.t('error') + ": " + msg.obj
})
}
},
randomSID(){
this.short_id = RandomUtil.randomShortId().join(',')
}
},
computed: {
inTls(): iTls {
+2 -1
View File
@@ -87,13 +87,14 @@ export default {
actions: {
action: "Action",
add: "Add",
new: "Add",
new: "New",
edit: "Edit",
del: "Delete",
save: "Save",
update: "Update",
submit: "Submit",
set: "Set",
generate: "Generate",
disable: "Disable",
close: "Close",
restartApp: "Restart App",
+2 -1
View File
@@ -86,13 +86,14 @@ export default {
actions: {
action: "فرمان",
add: "ایجاد",
new: "ایجاد",
new: "جدید",
edit: "ویرایش",
del: "حذف",
save: "ذخیره",
update: "بروزرسانی",
submit: "ارسال",
set: "تنظیم",
generate: "تولید",
disable: "غیرفعال",
close: "بستن",
restartApp: "ریستارت پنل",
+2 -1
View File
@@ -87,13 +87,14 @@ export default {
actions: {
action: "Hành động",
add: "Thêm",
new: "Thêm",
new: "Mới",
edit: "Chỉnh sửa",
del: "Xóa",
save: "Lưu",
update: "Cập nhật",
submit: "Gửi",
set: "Đặt",
generate: "Tạo ra",
disable: "Vô hiệu hóa",
close: "Đóng",
restartApp: "Khởi động lại ứng dụng",
+2 -1
View File
@@ -87,13 +87,14 @@ export default {
actions: {
action: "操作",
add: "添加",
new: "添加",
new: "新建",
edit: "编辑",
del: "删除",
save: "保存",
update: "更新",
submit: "提交",
set: "设置",
generate: "生成",
disable: "禁用",
close: "关闭",
restartApp: "重启面板",
+2 -1
View File
@@ -88,13 +88,14 @@ export default {
actions: {
action: "操作",
add: "添加",
new: "添加",
new: "新建",
edit: "編輯",
del: "刪除",
save: "保存",
update: "更新",
submit: "提交",
set: "設置",
generate: "生成",
disable: "禁用",
close: "關閉",
restartApp: "重啟面板",
+4 -3
View File
@@ -1,5 +1,6 @@
import { Hysteria, Hysteria2, InTypes, Inbound, Naive, Shadowsocks, TUIC, Trojan, VLESS, VMess } from "@/types/inbounds"
import { HTTP, WebSocket, gRPC, HTTPUpgrade, Transport, TrspTypes } from "@/types/transport";
import { HTTP, WebSocket, gRPC, HTTPUpgrade, Transport, TrspTypes } from "@/types/transport"
import RandomUtil from "./randomUtil"
export interface Link {
type: "local" | "external" | "sub"
@@ -185,7 +186,7 @@ export namespace LinkUtil {
allowInsecure: tlsClient?.insecure ? 1 : null,
fp: tlsClient?.utls?.enabled ? tlsClient.utls.fingerprint : null,
pbk: tlsClient?.reality?.public_key?? null,
sid: inbound.tls?.reality?.enabled ? (inbound.tls?.reality?.short_id?.length>0 ? inbound.tls.reality.short_id[0] : null) : null
sid: inbound.tls?.reality?.enabled ? (inbound.tls?.reality?.short_id?.length>0 ? inbound.tls.reality.short_id[RandomUtil.randomInt(inbound.tls.reality.short_id.length)] : null) : null
}
const uri = new URL(`vless://${u?.uuid}@${addr}:${inbound.listen_port}`)
for (const [key, value] of Object.entries({...params, ...tParams})){
@@ -211,7 +212,7 @@ export namespace LinkUtil {
allowInsecure: tlsClient?.insecure ? 1 : null,
fp: tlsClient?.utls?.enabled ? tlsClient.utls.fingerprint : null,
pbk: tlsClient?.reality?.public_key?? null,
sid: inbound.tls?.reality?.enabled ? (inbound.tls?.reality?.short_id?.length>0 ? inbound.tls.reality.short_id[0] : null) : null
sid: inbound.tls?.reality?.enabled ? (inbound.tls?.reality?.short_id?.length>0 ? inbound.tls.reality.short_id[RandomUtil.randomInt(inbound.tls.reality.short_id.length)] : null) : null
}
const uri = new URL(`trojan://${u?.password}@${addr}:${inbound.listen_port}`)
for (const [key, value] of Object.entries({...params, ...tParams})){
+2 -2
View File
@@ -35,8 +35,8 @@ const RandomUtil = {
return btoa(String.fromCharCode(...array))
},
randomShortId(): string[] {
let shortIds = ['','','','']
for (var ii = 0; ii < 4; ii++) {
let shortIds = new Array(24).fill('')
for (var ii = 0; ii < 24; ii++) {
for (var jj = 0; jj < this.randomInt(8); jj++){
let randomNum = this.randomInt(256)
shortIds[ii] += ('0' + randomNum.toString(16)).slice(-2)