Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a5519c2f6c |
@@ -41,6 +41,7 @@ type Instance struct {
|
|||||||
AccessMode AccessMode `json:"access_mode"` // open | whitelist
|
AccessMode AccessMode `json:"access_mode"` // open | whitelist
|
||||||
AllowNetworks []string `json:"allow_networks"` // 实例级白名单 CIDR 列表
|
AllowNetworks []string `json:"allow_networks"` // 实例级白名单 CIDR 列表
|
||||||
AuthMode AuthMode `json:"auth_mode"` // cert | cert+password
|
AuthMode AuthMode `json:"auth_mode"` // cert | cert+password
|
||||||
|
PublicHost string `json:"public_host"` // 公网域名/IP,生成 .ovpn 时优先用它;空则用下载时前端传入的 host
|
||||||
Status string `json:"status"` // running/stopped/error
|
Status string `json:"status"` // running/stopped/error
|
||||||
PID int `json:"pid"`
|
PID int `json:"pid"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
|
|||||||
@@ -400,7 +400,8 @@ func (s *Service) CreateUser(u model.VPNUser) (*model.VPNUser, error) {
|
|||||||
return &u, nil
|
return &u, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenerateOVPN 下载/重新生成 .ovpn,remoteHost 由前端传入。
|
// GenerateOVPN 下载/重新生成 .ovpn。
|
||||||
|
// remoteHost 优先级:Instance.PublicHost > 传入的 remoteHost > "vpn.example.com"。
|
||||||
func (s *Service) GenerateOVPN(userID, remoteHost string) (string, error) {
|
func (s *Service) GenerateOVPN(userID, remoteHost string) (string, error) {
|
||||||
u, err := s.Store.GetUser(userID)
|
u, err := s.Store.GetUser(userID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -410,7 +411,11 @@ func (s *Service) GenerateOVPN(userID, remoteHost string) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return s.Ovm.GenerateClientOVPNFor(u, in, remoteHost)
|
host := in.PublicHost
|
||||||
|
if host == "" {
|
||||||
|
host = remoteHost
|
||||||
|
}
|
||||||
|
return s.Ovm.GenerateClientOVPNFor(u, in, host)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RevokeUser 吊销用户:禁用 + 标记。
|
// RevokeUser 吊销用户:禁用 + 标记。
|
||||||
|
|||||||
@@ -12,6 +12,12 @@
|
|||||||
<el-table-column prop="proto" label="协议" width="80" />
|
<el-table-column prop="proto" label="协议" width="80" />
|
||||||
<el-table-column prop="dev" label="设备" width="80" />
|
<el-table-column prop="dev" label="设备" width="80" />
|
||||||
<el-table-column prop="subnet" label="子网" />
|
<el-table-column prop="subnet" label="子网" />
|
||||||
|
<el-table-column prop="public_host" label="公网地址">
|
||||||
|
<template #default="{row}">
|
||||||
|
<span v-if="row.public_host" style="font-family:monospace">{{ row.public_host }}</span>
|
||||||
|
<span v-else class="muted">未配置</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column label="访问控制" width="110">
|
<el-table-column label="访问控制" width="110">
|
||||||
<template #default="{row}">
|
<template #default="{row}">
|
||||||
<el-tag :type="row.access_mode==='whitelist'?'warning':'info'" size="small">
|
<el-tag :type="row.access_mode==='whitelist'?'warning':'info'" size="small">
|
||||||
@@ -53,6 +59,12 @@
|
|||||||
<el-select v-model="form.dev"><el-option label="tun" value="tun"/><el-option label="tap" value="tap"/></el-select>
|
<el-select v-model="form.dev"><el-option label="tun" value="tun"/><el-option label="tap" value="tap"/></el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="子网"><el-input v-model="form.subnet" placeholder="10.8.0.0/24"/></el-form-item>
|
<el-form-item label="子网"><el-input v-model="form.subnet" placeholder="10.8.0.0/24"/></el-form-item>
|
||||||
|
<el-form-item label="公网地址">
|
||||||
|
<el-input v-model="form.public_host" placeholder="vpn.example.com 或 203.0.113.10" />
|
||||||
|
<div class="muted" style="margin-top:4px">
|
||||||
|
客户端连接时用的服务端地址。<b>留空</b>则下载 .ovpn 时手动输入;<b>填写</b>则所有用户下载的 .ovpn 自动用此地址,无需修改。
|
||||||
|
</div>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="加密">
|
<el-form-item label="加密">
|
||||||
<el-select v-model="form.cipher"><el-option label="AES-256-GCM" value="AES-256-GCM"/><el-option label="AES-128-GCM" value="AES-128-GCM"/><el-option label="CHACHA20-POLY1305" value="CHACHA20-POLY1305"/></el-select>
|
<el-select v-model="form.cipher"><el-option label="AES-256-GCM" value="AES-256-GCM"/><el-option label="AES-128-GCM" value="AES-128-GCM"/><el-option label="CHACHA20-POLY1305" value="CHACHA20-POLY1305"/></el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -103,7 +115,7 @@ const router = useRouter()
|
|||||||
|
|
||||||
async function load() { list.value = await Inst.list() }
|
async function load() { list.value = await Inst.list() }
|
||||||
function openCreate() {
|
function openCreate() {
|
||||||
Object.assign(form, { name:'', port:1194, proto:'udp', dev:'tun', subnet:'10.8.0.0/24', cipher:'AES-256-GCM', auth_digest:'SHA256', push_dns:'', push_routes:'', extra:'', access_mode:'open', allow_networks:[], id:'' })
|
Object.assign(form, { name:'', port:1194, proto:'udp', dev:'tun', subnet:'10.8.0.0/24', cipher:'AES-256-GCM', auth_digest:'SHA256', push_dns:'', push_routes:'', extra:'', access_mode:'open', allow_networks:[], public_host:'', id:'' })
|
||||||
dlg.value = true
|
dlg.value = true
|
||||||
}
|
}
|
||||||
function openEdit(row) {
|
function openEdit(row) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<el-option v-for="i in instances" :key="i.id" :value="i.id" :label="`${i.name} (${i.proto}/${i.port})`" />
|
<el-option v-for="i in instances" :key="i.id" :value="i.id" :label="`${i.name} (${i.proto}/${i.port})`" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6"><el-input v-model="host" placeholder="客户端连接的远端域名/IP" /></el-col>
|
<el-col :span="6"><el-input v-model="host" placeholder="可选: 覆盖实例公网地址" /></el-col>
|
||||||
<el-col :span="4"><el-button @click="loadUsers">刷新</el-button></el-col>
|
<el-col :span="4"><el-button @click="loadUsers">刷新</el-button></el-col>
|
||||||
<el-col :span="6" style="text-align:right">
|
<el-col :span="6" style="text-align:right">
|
||||||
<el-button type="primary" :disabled="!instanceId" @click="openCreate"><el-icon><Plus /></el-icon>新建用户</el-button>
|
<el-button type="primary" :disabled="!instanceId" @click="openCreate"><el-icon><Plus /></el-icon>新建用户</el-button>
|
||||||
|
|||||||
Reference in New Issue
Block a user