diff --git a/backend/service/config.go b/backend/service/config.go
index 4e70ed6..85676bc 100644
--- a/backend/service/config.go
+++ b/backend/service/config.go
@@ -146,6 +146,8 @@ func (s *ConfigService) SaveChanges(changes map[string]string, loginUser string)
case "outbounds":
if change.Action == "edit" {
newConfig.Outbounds[change.Index] = rawObject
+ } else if change.Action == "del" {
+ newConfig.Outbounds = append(newConfig.Outbounds[:change.Index], newConfig.Outbounds[change.Index+1:]...)
} else {
newConfig.Outbounds = append(newConfig.Outbounds, rawObject)
}
diff --git a/frontend/src/components/Headers.vue b/frontend/src/components/Headers.vue
new file mode 100644
index 0000000..f0dbb1e
--- /dev/null
+++ b/frontend/src/components/Headers.vue
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/InMulitiplex.vue b/frontend/src/components/InMulitiplex.vue
deleted file mode 100644
index e734de8..0000000
--- a/frontend/src/components/InMulitiplex.vue
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/frontend/src/components/Multiplex.vue b/frontend/src/components/Multiplex.vue
new file mode 100644
index 0000000..84d5f8f
--- /dev/null
+++ b/frontend/src/components/Multiplex.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/Network.vue b/frontend/src/components/Network.vue
index 97aec76..d050bbe 100644
--- a/frontend/src/components/Network.vue
+++ b/frontend/src/components/Network.vue
@@ -9,7 +9,7 @@
\ No newline at end of file
diff --git a/frontend/src/components/Transport.vue b/frontend/src/components/Transport.vue
index 955d624..dea28e2 100644
--- a/frontend/src/components/Transport.vue
+++ b/frontend/src/components/Transport.vue
@@ -28,7 +28,7 @@ import WebSocket from './transports/WebSocket.vue'
import GRPC from './transports/gRPC.vue'
import HttpUpgrade from './transports/HttpUpgrade.vue'
export default {
- props: ['inbound'],
+ props: ['data'],
data() {
return {
trspTypes: TrspTypes
@@ -36,15 +36,15 @@ export default {
},
computed: {
Transport() {
- return this.$props.inbound.transport
+ return this.$props.data.transport
},
tpEnable: {
- get() { return Object.hasOwn(this.$props.inbound.transport, 'type') },
- set(newValue: boolean) { this.$props.inbound.transport = newValue ? { type: 'http' } : {} }
+ get() { return Object.hasOwn(this.$props.data.transport, 'type') },
+ set(newValue: boolean) { this.$props.data.transport = newValue ? { type: 'http' } : {} }
},
transportType: {
get() { return this.Transport.type },
- set(newValue: string) { this.$props.inbound.transport = { type: newValue } }
+ set(newValue: string) { this.$props.data.transport = { type: newValue } }
}
},
components: { Http, WebSocket, GRPC, HttpUpgrade }
diff --git a/frontend/src/components/UoT.vue b/frontend/src/components/UoT.vue
new file mode 100644
index 0000000..b6dc292
--- /dev/null
+++ b/frontend/src/components/UoT.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/WgPeer.vue b/frontend/src/components/WgPeer.vue
new file mode 100644
index 0000000..8cb1f9d
--- /dev/null
+++ b/frontend/src/components/WgPeer.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Direct.vue b/frontend/src/components/protocols/Direct.vue
index 9d98fd9..9231f87 100644
--- a/frontend/src/components/protocols/Direct.vue
+++ b/frontend/src/components/protocols/Direct.vue
@@ -1,14 +1,14 @@
-
-
+
+
+ v-model="data.override_address">
@@ -20,6 +20,16 @@
v-model="override_port">
+
+
+
+
@@ -28,16 +38,20 @@
import Network from '@/components/Network.vue'
export default {
- props: ['inbound'],
- data() {
- return {}
+ props: ['direction','data'],
+ data() {
+ return {}
+ },
+ computed: {
+ override_port: {
+ get() { return this.$props.data.override_port ? this.$props.data.override_port : ''; },
+ set(newValue: any) { this.$props.data.override_port = newValue.length == 0 || newValue == 0 ? undefined : parseInt(newValue); }
},
- computed: {
- override_port: {
- get() { return this.$props.inbound.override_port ? this.$props.inbound.override_port : ''; },
- set(newValue: any) { this.$props.inbound.override_port = newValue.length == 0 || newValue == 0 ? undefined : parseInt(newValue); }
- },
+ proxy_protocol: {
+ get() { return this.$props.data.proxy_protocol ? this.$props.data.proxy_protocol : ''; },
+ set(newValue: any) { this.$props.data.proxy_protocol = newValue.length == 0 || newValue == 0 ? undefined : parseInt(newValue); }
},
- components: { Network }
+ },
+ components: { Network }
}
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Http.vue b/frontend/src/components/protocols/Http.vue
new file mode 100644
index 0000000..71a4995
--- /dev/null
+++ b/frontend/src/components/protocols/Http.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Hysteria.vue b/frontend/src/components/protocols/Hysteria.vue
index 2f3c0e5..c8744e4 100644
--- a/frontend/src/components/protocols/Hysteria.vue
+++ b/frontend/src/components/protocols/Hysteria.vue
@@ -26,38 +26,134 @@
+ v-model="data.obfs">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Hysteria Options
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Hysteria2.vue b/frontend/src/components/protocols/Hysteria2.vue
index 6c77c61..2fa96a6 100644
--- a/frontend/src/components/protocols/Hysteria2.vue
+++ b/frontend/src/components/protocols/Hysteria2.vue
@@ -1,23 +1,37 @@
-
+
+ v-model="data.masquerade">
+
-
+
-
+
+
+
+
+
+
+
+
+
+
@@ -32,12 +46,12 @@
-
+
+ v-model="data.obfs.password">
@@ -45,7 +59,7 @@
- Options
+ Hysteria2 Options
@@ -60,32 +74,29 @@
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Naive.vue b/frontend/src/components/protocols/Naive.vue
index aec55f4..005ef19 100644
--- a/frontend/src/components/protocols/Naive.vue
+++ b/frontend/src/components/protocols/Naive.vue
@@ -2,7 +2,7 @@
-
+
diff --git a/frontend/src/components/protocols/OutShadowTls.vue b/frontend/src/components/protocols/OutShadowTls.vue
new file mode 100644
index 0000000..b37aeac
--- /dev/null
+++ b/frontend/src/components/protocols/OutShadowTls.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Selector.vue b/frontend/src/components/protocols/Selector.vue
new file mode 100644
index 0000000..db7e424
--- /dev/null
+++ b/frontend/src/components/protocols/Selector.vue
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/ShadowTls.vue b/frontend/src/components/protocols/ShadowTls.vue
index 3f03ba0..202280d 100644
--- a/frontend/src/components/protocols/ShadowTls.vue
+++ b/frontend/src/components/protocols/ShadowTls.vue
@@ -92,62 +92,62 @@ import { ShadowTLS } from '@/types/inbounds'
import Dial from '../Dial.vue'
export default {
- props: ['inbound'],
- data() {
- return {
- handshake_server: ''
+ props: ['inbound'],
+ data() {
+ return {
+ handshake_server: ''
+ }
+ },
+ methods: {
+ addHandshakeServer() {
+ this.inbound.handshake_for_server_name[this.handshake_server] = {}
+ // Clear the input field after adding the server
+ this.handshake_server = ''
+ }
+ },
+ mounted() {
+ this.version = this.Inbound.version
+ },
+ computed: {
+ version: {
+ get() { this.version = this.Inbound.version; return this.Inbound.version; },
+ set(newValue: any) {
+ switch (newValue) {
+ case 1:
+ this.Inbound.password = undefined
+ this.Inbound.users = undefined
+ this.Inbound.handshake_for_server_name = undefined
+ break;
+ case 2:
+ if (!this.Inbound.password) {
+ this.Inbound.password = ""
+ }
+ this.Inbound.users = undefined
+ if (!this.Inbound.handshake_for_server_name) {
+ this.Inbound.handshake_for_server_name = {}
+ }
+ break;
+ case 3:
+ this.Inbound.password = undefined
+ if (Object.hasOwn(this.Inbound, 'users')) {
+ this.Inbound.users = []
+ }
+ if (!this.Inbound.handshake_for_server_name) {
+ this.Inbound.handshake_for_server_name = {}
+ }
+ break;
}
- },
- methods: {
- addHandshakeServer() {
- this.inbound.handshake_for_server_name[this.handshake_server] = {}
- // Clear the input field after adding the server
- this.handshake_server = ''
+ this.Inbound.version = newValue;
}
},
- mounted() {
- this.version = this.Inbound.version
+ Inbound(): ShadowTLS {
+ return this.$props.inbound;
},
- computed: {
- version: {
- get() { this.version = this.Inbound.version; return this.Inbound.version; },
- set(newValue: any) {
- switch (newValue) {
- case 1:
- this.Inbound.password = undefined
- this.Inbound.users = undefined
- this.Inbound.handshake_for_server_name = undefined
- break;
- case 2:
- if (!this.Inbound.password) {
- this.Inbound.password = ""
- }
- this.Inbound.users = undefined
- if (!this.Inbound.handshake_for_server_name) {
- this.Inbound.handshake_for_server_name = {}
- }
- break;
- case 3:
- this.Inbound.password = undefined
- if (Object.hasOwn(this.Inbound, 'users')) {
- this.Inbound.users = []
- }
- if (!this.Inbound.handshake_for_server_name) {
- this.Inbound.handshake_for_server_name = {}
- }
- break;
- }
- this.Inbound.version = newValue;
- }
- },
- Inbound(): ShadowTLS {
- return this.$props.inbound;
- },
- server_port: {
- get() { return this.Inbound.handshake.server_port ? this.Inbound.handshake.server_port : 443; },
- set(newValue: any) { this.Inbound.handshake.server_port = newValue.length == 0 || newValue == 0 ? 443 : parseInt(newValue); }
- },
+ server_port: {
+ get() { return this.Inbound.handshake.server_port ? this.Inbound.handshake.server_port : 443; },
+ set(newValue: any) { this.Inbound.handshake.server_port = newValue.length == 0 || newValue == 0 ? 443 : parseInt(newValue); }
},
- components: { Dial }
+ },
+ components: { Dial }
}
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Shadowsocks.vue b/frontend/src/components/protocols/Shadowsocks.vue
index 0177257..6c893ee 100644
--- a/frontend/src/components/protocols/Shadowsocks.vue
+++ b/frontend/src/components/protocols/Shadowsocks.vue
@@ -6,14 +6,17 @@
hide-details
label="Method"
:items="ssMethods"
- v-model="inbound.method">
+ v-model="data.method">
-
+
-
+
+
+
+
@@ -21,24 +24,25 @@
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Socks.vue b/frontend/src/components/protocols/Socks.vue
new file mode 100644
index 0000000..3d14bbe
--- /dev/null
+++ b/frontend/src/components/protocols/Socks.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Ssh.vue b/frontend/src/components/protocols/Ssh.vue
new file mode 100644
index 0000000..0935835
--- /dev/null
+++ b/frontend/src/components/protocols/Ssh.vue
@@ -0,0 +1,151 @@
+
+
+
+
+
+
+ {{ $t('tls.usePath') }}
+ {{ $t('tls.useText') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SSH Options
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/TProxy.vue b/frontend/src/components/protocols/TProxy.vue
index 61c5c34..036bde7 100644
--- a/frontend/src/components/protocols/TProxy.vue
+++ b/frontend/src/components/protocols/TProxy.vue
@@ -2,7 +2,7 @@
-
+
diff --git a/frontend/src/components/protocols/Tor.vue b/frontend/src/components/protocols/Tor.vue
new file mode 100644
index 0000000..3516955
--- /dev/null
+++ b/frontend/src/components/protocols/Tor.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Trojan.vue b/frontend/src/components/protocols/Trojan.vue
new file mode 100644
index 0000000..64a40ad
--- /dev/null
+++ b/frontend/src/components/protocols/Trojan.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Tuic.vue b/frontend/src/components/protocols/Tuic.vue
index 71a2695..ffb4aa9 100644
--- a/frontend/src/components/protocols/Tuic.vue
+++ b/frontend/src/components/protocols/Tuic.vue
@@ -1,20 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ v-model="data.congestion_control">
-
+
-
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/UrlTest.vue b/frontend/src/components/protocols/UrlTest.vue
new file mode 100644
index 0000000..4a63183
--- /dev/null
+++ b/frontend/src/components/protocols/UrlTest.vue
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SSH Options
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Vless.vue b/frontend/src/components/protocols/Vless.vue
new file mode 100644
index 0000000..25126ef
--- /dev/null
+++ b/frontend/src/components/protocols/Vless.vue
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Vmess.vue b/frontend/src/components/protocols/Vmess.vue
new file mode 100644
index 0000000..79dcf43
--- /dev/null
+++ b/frontend/src/components/protocols/Vmess.vue
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/protocols/Wireguard.vue b/frontend/src/components/protocols/Wireguard.vue
new file mode 100644
index 0000000..ab7d8de
--- /dev/null
+++ b/frontend/src/components/protocols/Wireguard.vue
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Wireguard Options
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Peer {{ index+1 }}
+
+
+
+
+
+
+ Peer
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/components/transports/Http.vue b/frontend/src/components/transports/Http.vue
index f544ce8..aaaf58d 100644
--- a/frontend/src/components/transports/Http.vue
+++ b/frontend/src/components/transports/Http.vue
@@ -44,10 +44,12 @@
+
\ No newline at end of file
diff --git a/frontend/src/components/transports/HttpUpgrade.vue b/frontend/src/components/transports/HttpUpgrade.vue
index d62bed7..06a15dc 100644
--- a/frontend/src/components/transports/HttpUpgrade.vue
+++ b/frontend/src/components/transports/HttpUpgrade.vue
@@ -15,14 +15,17 @@
+
\ No newline at end of file
diff --git a/frontend/src/components/transports/WebSocket.vue b/frontend/src/components/transports/WebSocket.vue
index 80f659c..cf9f669 100644
--- a/frontend/src/components/transports/WebSocket.vue
+++ b/frontend/src/components/transports/WebSocket.vue
@@ -33,10 +33,12 @@
+
\ No newline at end of file
diff --git a/frontend/src/layouts/modals/Inbound.vue b/frontend/src/layouts/modals/Inbound.vue
index c678340..89f26ec 100644
--- a/frontend/src/layouts/modals/Inbound.vue
+++ b/frontend/src/layouts/modals/Inbound.vue
@@ -22,18 +22,18 @@
-
-
-
-
+
+
+
+
-
-
+
+
-
+
-
+
@@ -73,56 +73,56 @@ import Tuic from '@/components/protocols/Tuic.vue'
import InTls from '@/components/InTLS.vue'
import TProxy from '@/components/protocols/TProxy.vue'
import RandomUtil from '@/plugins/randomUtil'
-import InMulitiplex from '@/components/InMulitiplex.vue'
+import Multiplex from '@/components/Multiplex.vue'
import Transport from '@/components/Transport.vue'
export default {
- props: ['visible', 'data', 'id', 'stats'],
- emits: ['close', 'save'],
- data() {
- return {
- inbound: createInbound("direct",{ "tag": "" }),
- title: "add",
- loading: false,
- inTypes: InTypes,
- inboundStats: false,
- HasOptionalUser: [InTypes.Mixed,InTypes.SOCKS,InTypes.HTTP,InTypes.Shadowsocks],
- }
+ props: ['visible', 'data', 'id', 'stats'],
+ emits: ['close', 'save'],
+ data() {
+ return {
+ inbound: createInbound("direct",{ "tag": "" }),
+ title: "add",
+ loading: false,
+ inTypes: InTypes,
+ inboundStats: false,
+ HasOptionalUser: [InTypes.Mixed,InTypes.SOCKS,InTypes.HTTP,InTypes.Shadowsocks],
+ }
+ },
+ methods: {
+ updateData() {
+ if (this.$props.id != -1) {
+ const newData = JSON.parse(this.$props.data)
+ this.inbound = createInbound(newData.type, newData)
+ this.title = "edit"
+ }
+ else {
+ const port = RandomUtil.randomIntRange(10000, 60000)
+ this.inbound = createInbound("mixed",{ tag: "in-"+port ,listen: "::", listen_port: port })
+ this.title = "add"
+ }
+ this.inboundStats = this.$props.stats
},
- methods: {
- updateData() {
- if (this.$props.id != -1) {
- const newData = JSON.parse(this.$props.data)
- this.inbound = createInbound(newData.type, newData)
- this.title = "edit"
- }
- else {
- const port = RandomUtil.randomIntRange(10000, 60000)
- this.inbound = createInbound("mixed",{ tag: "in-"+port ,listen: "::", listen_port: port })
- this.title = "add"
- }
- this.inboundStats = this.$props.stats
- },
- changeType() {
- const prevConfig = { tag: this.inbound.tag ,listen: this.inbound.listen, listen_port: this.inbound.listen_port }
- this.inbound = createInbound(this.inbound.type, prevConfig)
- },
- closeModal() {
- this.updateData() // reset
- this.$emit('close')
- },
- saveChanges() {
- this.loading = true
- this.$emit('save', this.inbound, this.inboundStats)
- this.loading = false
- },
+ changeType() {
+ const prevConfig = { tag: this.inbound.tag ,listen: this.inbound.listen, listen_port: this.inbound.listen_port }
+ this.inbound = createInbound(this.inbound.type, prevConfig)
},
- watch: {
- visible(newValue) {
- if (newValue) {
- this.updateData()
- }
- },
+ closeModal() {
+ this.updateData() // reset
+ this.$emit('close')
},
- components: { Listen, InTls, Hysteria2, Naive, Direct, Shadowsocks, Users, Hysteria, ShadowTls, TProxy, InMulitiplex, Tuic, Transport }
+ saveChanges() {
+ this.loading = true
+ this.$emit('save', this.inbound, this.inboundStats)
+ this.loading = false
+ },
+ },
+ watch: {
+ visible(newValue) {
+ if (newValue) {
+ this.updateData()
+ }
+ },
+ },
+ components: { Listen, InTls, Hysteria2, Naive, Direct, Shadowsocks, Users, Hysteria, ShadowTls, TProxy, Multiplex, Tuic, Transport }
}
\ No newline at end of file
diff --git a/frontend/src/layouts/modals/Outbound.vue b/frontend/src/layouts/modals/Outbound.vue
new file mode 100644
index 0000000..b0c74cb
--- /dev/null
+++ b/frontend/src/layouts/modals/Outbound.vue
@@ -0,0 +1,166 @@
+
+
+
+
+ {{ $t('actions.' + title) + " " + $t('objects.outbound') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('actions.close') }}
+
+
+ {{ $t('actions.save') }}
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/store/modules/data.ts b/frontend/src/store/modules/data.ts
index ab99ffa..c03cf39 100644
--- a/frontend/src/store/modules/data.ts
+++ b/frontend/src/store/modules/data.ts
@@ -51,6 +51,15 @@ const Data = defineStore('Data', {
this.loadData()
}
},
+ async delOutbound(index: number) {
+ const diff = {
+ config: JSON.stringify([{key: "outbounds", action: "del", index: index, obj: null}]),
+ }
+ const msg = await HttpUtils.post('api/save',diff)
+ if(msg.success) {
+ this.loadData()
+ }
+ },
async delClient(id: number) {
const diff = {
config: JSON.stringify(FindDiff.Config(this.config,this.oldData.config)),
diff --git a/frontend/src/types/brutal.ts b/frontend/src/types/brutal.ts
new file mode 100644
index 0000000..f05f562
--- /dev/null
+++ b/frontend/src/types/brutal.ts
@@ -0,0 +1,5 @@
+export interface Brutal {
+ enabled: boolean
+ up_mbps: number
+ down_mbps: number
+}
\ No newline at end of file
diff --git a/frontend/src/types/inMultiplex.ts b/frontend/src/types/inMultiplex.ts
deleted file mode 100644
index 34f7f8e..0000000
--- a/frontend/src/types/inMultiplex.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-interface Brutal {
- enabled: boolean
- up_mbps: number
- down_mbps: number
-}
-
-export interface iMultiplex{
- enabled: boolean
- padding?: boolean
- brutal?: Brutal
-}
\ No newline at end of file
diff --git a/frontend/src/types/inbounds.ts b/frontend/src/types/inbounds.ts
index 02b3895..1cdceaa 100644
--- a/frontend/src/types/inbounds.ts
+++ b/frontend/src/types/inbounds.ts
@@ -1,4 +1,4 @@
-import { iMultiplex } from "./inMultiplex"
+import { iMultiplex } from "./multiplex"
import { iTls } from "./inTls"
import { Dial } from "./outbounds"
import { Transport } from "./transport"
@@ -119,10 +119,7 @@ export interface Naive extends InboundBasics {
export interface Hysteria extends InboundBasics {
up_mbps: number
down_mbps: number
- obfs?: {
- type?: "salamander"
- password?: string
- }
+ obfs?: string
users: NameAuth[]
recv_window_conn?: number
recv_window_client?: number
diff --git a/frontend/src/types/multiplex.ts b/frontend/src/types/multiplex.ts
new file mode 100644
index 0000000..720daf8
--- /dev/null
+++ b/frontend/src/types/multiplex.ts
@@ -0,0 +1,14 @@
+import { Brutal } from "./brutal"
+
+export interface iMultiplex{
+ enabled: boolean
+ padding?: boolean
+ brutal?: Brutal
+}
+
+export interface oMultiplex extends iMultiplex{
+ protocol?: "smux" | "yamux" | "h2mux"
+ max_connections?: number
+ min_streams?: number
+ max_streams?: number
+}
\ No newline at end of file
diff --git a/frontend/src/types/outTls.ts b/frontend/src/types/outTls.ts
index 701b5f3..a60e5d0 100644
--- a/frontend/src/types/outTls.ts
+++ b/frontend/src/types/outTls.ts
@@ -1,3 +1,50 @@
export interface oTls {
enabled?: boolean
+ disable_sni?: boolean
+ server_name?: string
+ insecure?: boolean
+ alpn?: string[]
+ min_version?: string
+ max_version?: string
+ cipher_suites?: string[]
+ certificate?: string
+ certificate_path?: string
+ ech?: {
+ enabled: boolean
+ pq_signature_schemes_enabled?: boolean
+ dynamic_record_sizing_disabled?: boolean
+ config?: string[],
+ config_path?: string
+ },
+ utls?: {
+ enabled: boolean
+ fingerprint: string
+ },
+ reality?: {
+ enabled: boolean
+ public_key: string
+ short_id: string
+ }
+}
+
+export const defaultOutTls: oTls = {
+ alpn: ['h3', 'h2', 'http/1.1'],
+ min_version: "1.2",
+ max_version: "1.3",
+ cipher_suites: [],
+ utls: {
+ enabled: true,
+ fingerprint: "chrome",
+ },
+ reality: {
+ enabled: true,
+ public_key: "",
+ short_id: "",
+ },
+ ech: {
+ enabled: true,
+ pq_signature_schemes_enabled: false,
+ dynamic_record_sizing_disabled: false,
+ config_path: "",
+ }
}
\ No newline at end of file
diff --git a/frontend/src/types/outbounds.ts b/frontend/src/types/outbounds.ts
index b147104..dee2140 100644
--- a/frontend/src/types/outbounds.ts
+++ b/frontend/src/types/outbounds.ts
@@ -1,4 +1,6 @@
import { oTls } from "./outTls"
+import { oMultiplex } from "./multiplex"
+import { Transport } from "./transport"
export const OutTypes = {
Direct: 'direct',
@@ -14,7 +16,7 @@ export const OutTypes = {
ShadowTLS: 'shadowtls',
TUIC: 'tuic',
Hysteria2: 'hysteria2',
- Tur: 'tur',
+ Tor: 'tor',
SSH: 'ssh',
DNS: 'dns',
Selector: 'selector',
@@ -43,12 +45,205 @@ interface OutboundBasics {
tag: string
}
+export interface WgPeer {
+ server: string
+ server_port: number
+ public_key: string
+ pre_shared_key?: string
+ allowed_ips?: string[]
+ reserved?: number[]
+}
+
export interface Direct extends OutboundBasics, Dial {
override_address?: string
override_port?: number
proxy_protocol?: 0 | 1 | 2
}
+export interface Block extends OutboundBasics {}
+
+export interface SOCKS extends OutboundBasics, Dial {
+ server: string
+ server_port: number
+ version?: "4" | "4a" | "5"
+ username?: string
+ password?: string
+ network?: "udp" | "tcp"
+ udp_over_tcp?: false | {
+ enabled: true
+ version?: number
+ }
+}
+
+export interface HTTP extends OutboundBasics, Dial {
+ server: string
+ server_port: number
+ username?: string
+ password?: string
+ path?: string
+ headers?: {
+ [key: string]: string
+ }
+ tls?: oTls
+}
+
+export interface Shadowsocks extends OutboundBasics, Dial {
+ server: string
+ server_port: number
+ method: string
+ password: string
+ network?: "udp" | "tcp"
+ udp_over_tcp?: false | {
+ enabled: true
+ version?: number
+ }
+ multiplex?: oMultiplex
+}
+
+export interface VMESS extends OutboundBasics, Dial {
+ server: string
+ server_port: number
+ uuid: string
+ security?: string
+ alter_id: 0
+ global_padding?: boolean
+ authenticated_length?: boolean
+ network?: "udp" | "tcp"
+ packet_encoding?: string
+ tls?: oTls
+ multiplex?: oMultiplex
+ transport?: Transport
+}
+
+export interface Trojan extends OutboundBasics, Dial {
+ server: string
+ server_port: number
+ password: string
+ network?: "udp" | "tcp"
+ tls?: oTls
+ multiplex?: oMultiplex
+ transport?: Transport
+}
+
+export interface WireGuard extends OutboundBasics, Dial {
+ server?: string
+ server_port?: number
+ system_interface?: boolean
+ gso?: boolean
+ interface_name?: string
+ local_address: string[]
+ private_key: string
+ peers?: WgPeer[]
+ peer_public_key?: string
+ pre_shared_key?: string
+ reserved?: number[]
+ workers?: number
+ mtu?: number
+ network?: "udp" | "tcp"
+}
+
+export interface Hysteria extends OutboundBasics, Dial {
+ server: string
+ server_port: number
+ up_mbps: number
+ down_mbps: number
+ obfs?: string
+ auth_str?: string
+ recv_window_conn?: number
+ recv_window?: number
+ disable_mtu_discovery?: boolean
+ network?: "udp" | "tcp"
+ tls: oTls
+}
+
+export interface ShadowTLS extends OutboundBasics, Dial {
+ server: string
+ server_port: number
+ version: 1|2|3
+ password?: string
+ tls: oTls
+}
+
+export interface VLESS extends OutboundBasics, Dial {
+ server: string
+ server_port: number
+ uuid: string
+ flow?: string
+ network?: "udp" | "tcp"
+ packet_encoding?: string
+ tls?: oTls
+ multiplex?: oMultiplex
+ transport?: Transport
+}
+
+export interface TUIC extends OutboundBasics, Dial {
+ server: string
+ server_port: number
+ uuid: string
+ password?: string
+ congestion_control?: "cubic"|"new_reno"|"bbr"
+ udp_relay_mode?: "native" | "quic"
+ udp_over_stream?: boolean
+ zero_rtt_handshake?: boolean
+ heartbeat?: string
+ network?: "udp" | "tcp"
+ tls: oTls
+}
+
+export interface Hysteria2 extends OutboundBasics, Dial {
+ server: string
+ server_port: number
+ up_mbps?: number
+ down_mbps?: number
+ obfs?: {
+ type?: "salamander"
+ password: string
+ }
+ password?: string
+ network?: "udp" | "tcp"
+ tls: oTls
+ brutal_debug?: boolean
+}
+
+export interface Tor extends OutboundBasics, Dial {
+ executable_path?: string
+ extra_args?: string[]
+ data_directory: string
+ torrc?: {
+ ClientOnly: 0 | 1
+ }
+}
+
+export interface SSH extends OutboundBasics, Dial {
+ server: string
+ server_port?: number
+ user?: string
+ password?: string
+ private_key?: string
+ private_key_path?: string
+ private_key_passphrase?: string
+ host_key?: string[]
+ host_key_algorithms?: string[]
+ client_version?: string
+}
+
+export interface DNS extends OutboundBasics {}
+
+export interface Selector extends OutboundBasics {
+ outbounds: string[]
+ url?: string
+ interval?: string
+ tolerance?: number
+ idle_timeout?: string
+ interrupt_exist_connections?: boolean
+}
+
+export interface URLTest extends OutboundBasics {
+ outbounds: string[]
+ default?: string
+ interrupt_exist_connections?: boolean
+}
+
// Create interfaces dynamically based on OutTypes keys
type InterfaceMap = {
[Key in keyof typeof OutTypes]: {
@@ -64,18 +259,18 @@ export type Outbound = InterfaceMap[keyof InterfaceMap]
const defaultValues: Record = {
direct: { type: OutTypes.Direct },
block: { type: OutTypes.Block },
- socks: { type: OutTypes.SOCKS },
- http: { type: OutTypes.HTTP },
- shadowsocks: { type: OutTypes.Shadowsocks },
- vmess: { type: OutTypes.VMess, tls: { enabled: true } },
- trojan: { type: OutTypes.Trojan },
- wireguard: { type: OutTypes.Wireguard },
- hysteria: { type: OutTypes.Hysteria },
- vless: { type: OutTypes.VLESS },
- shadowtls: { type: OutTypes.ShadowTLS },
- tuic: { type: OutTypes.TUIC },
- hysteria2: { type: OutTypes.Hysteria2, users: [], tls: {} },
- tur: { type: OutTypes.Tur },
+ socks: { type: OutTypes.SOCKS, version: "5" },
+ http: { type: OutTypes.HTTP, tls: {} },
+ shadowsocks: { type: OutTypes.Shadowsocks, method: 'none', multiplex: {} },
+ vmess: { type: OutTypes.VMess, tls: {}, multiplex: {}, transport: {}, security: 'auto', global_padding: false },
+ trojan: { type: OutTypes.Trojan, tls: {}, multiplex: {}, transport: {} },
+ wireguard: { type: OutTypes.Wireguard, local_address: ['10.0.0.2/32','fe80::2/128'], private_key: '' },
+ hysteria: { type: OutTypes.Hysteria, up_mbps: 100, down_mbps: 100, tls: { enabled: true } },
+ shadowtls: { type: OutTypes.ShadowTLS, version: 3, tls: { enabled: true } },
+ vless: { type: OutTypes.VLESS, tls: {}, multiplex: {}, transport: {} },
+ tuic: { type: OutTypes.TUIC, congestion_control: 'cubic', tls: { enabled: true } },
+ hysteria2: { type: OutTypes.Hysteria2, tls: { enabled: true } },
+ tor: { type: OutTypes.Tor, executable_path: './tor', data_directory: '$HOME/.cache/tor', torrc: { ClientOnly: 1 } },
ssh: { type: OutTypes.SSH },
dns: { type: OutTypes.DNS },
selector: { type: OutTypes.Selector },
diff --git a/frontend/src/views/Admins.vue b/frontend/src/views/Admins.vue
index 16baf27..58dce60 100644
--- a/frontend/src/views/Admins.vue
+++ b/frontend/src/views/Admins.vue
@@ -9,7 +9,7 @@
-
+
Last Login
diff --git a/frontend/src/views/Basics.vue b/frontend/src/views/Basics.vue
index df9b8fc..f0aae58 100644
--- a/frontend/src/views/Basics.vue
+++ b/frontend/src/views/Basics.vue
@@ -117,7 +117,7 @@
hide-details
type="number"
clearable
- @click:clear="delete appConfig.ntp.server_port"
+ @click:clear="delete appConfig.ntp?.server_port"
label="Server Port"
>
diff --git a/frontend/src/views/Clients.vue b/frontend/src/views/Clients.vue
index 7dc32f9..3909e77 100644
--- a/frontend/src/views/Clients.vue
+++ b/frontend/src/views/Clients.vue
@@ -40,7 +40,7 @@
-
+
{{ item.desc }}
diff --git a/frontend/src/views/Inbounds.vue b/frontend/src/views/Inbounds.vue
index 6068cbd..b17df30 100644
--- a/frontend/src/views/Inbounds.vue
+++ b/frontend/src/views/Inbounds.vue
@@ -23,7 +23,7 @@
-
+
{{ item.type }}
diff --git a/frontend/src/views/Outbounds.vue b/frontend/src/views/Outbounds.vue
index 5669f7c..d29db6e 100644
--- a/frontend/src/views/Outbounds.vue
+++ b/frontend/src/views/Outbounds.vue
@@ -1,8 +1,29 @@
+
+
+
+
+ {{ $t('actions.add') }}
+
+
-
+
{{ item.type }}
@@ -15,6 +36,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t('confirm') }}
+
+ {{ $t('yes') }}
+ {{ $t('no') }}
+
+
+
+
+
@@ -22,13 +69,94 @@
\ No newline at end of file