option warp endpoint #345
This commit is contained in:
@@ -9,6 +9,7 @@ type Endpoint struct {
|
|||||||
Type string `json:"type" form:"type"`
|
Type string `json:"type" form:"type"`
|
||||||
Tag string `json:"tag" form:"tag" gorm:"unique"`
|
Tag string `json:"tag" form:"tag" gorm:"unique"`
|
||||||
Options json.RawMessage `json:"-" form:"-"`
|
Options json.RawMessage `json:"-" form:"-"`
|
||||||
|
Ext json.RawMessage `json:"ext" form:"ext"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Endpoint) UnmarshalJSON(data []byte) error {
|
func (o *Endpoint) UnmarshalJSON(data []byte) error {
|
||||||
@@ -27,9 +28,11 @@ func (o *Endpoint) UnmarshalJSON(data []byte) error {
|
|||||||
delete(raw, "type")
|
delete(raw, "type")
|
||||||
o.Tag = raw["tag"].(string)
|
o.Tag = raw["tag"].(string)
|
||||||
delete(raw, "tag")
|
delete(raw, "tag")
|
||||||
|
o.Ext, _ = json.MarshalIndent(raw["ext"], "", " ")
|
||||||
|
delete(raw, "ext")
|
||||||
|
|
||||||
// Remaining fields
|
// Remaining fields
|
||||||
o.Options, err = json.Marshal(raw)
|
o.Options, err = json.MarshalIndent(raw, "", " ")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,7 +40,12 @@ func (o *Endpoint) UnmarshalJSON(data []byte) error {
|
|||||||
func (o Endpoint) MarshalJSON() ([]byte, error) {
|
func (o Endpoint) MarshalJSON() ([]byte, error) {
|
||||||
// Combine fixed fields and dynamic fields into one map
|
// Combine fixed fields and dynamic fields into one map
|
||||||
combined := make(map[string]interface{})
|
combined := make(map[string]interface{})
|
||||||
combined["type"] = o.Type
|
switch o.Type {
|
||||||
|
case "warp":
|
||||||
|
combined["type"] = "wireguard"
|
||||||
|
default:
|
||||||
|
combined["type"] = o.Type
|
||||||
|
}
|
||||||
combined["tag"] = o.Tag
|
combined["tag"] = o.Tag
|
||||||
|
|
||||||
if o.Options != nil {
|
if o.Options != nil {
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EndpointService struct{}
|
type EndpointService struct {
|
||||||
|
WarpService
|
||||||
|
}
|
||||||
|
|
||||||
func (o *EndpointService) GetAll() (*[]map[string]interface{}, error) {
|
func (o *EndpointService) GetAll() (*[]map[string]interface{}, error) {
|
||||||
db := database.GetDB()
|
db := database.GetDB()
|
||||||
@@ -25,6 +27,7 @@ func (o *EndpointService) GetAll() (*[]map[string]interface{}, error) {
|
|||||||
"id": endpoint.Id,
|
"id": endpoint.Id,
|
||||||
"type": endpoint.Type,
|
"type": endpoint.Type,
|
||||||
"tag": endpoint.Tag,
|
"tag": endpoint.Tag,
|
||||||
|
"ext": endpoint.Ext,
|
||||||
}
|
}
|
||||||
if endpoint.Options != nil {
|
if endpoint.Options != nil {
|
||||||
var restFields map[string]json.RawMessage
|
var restFields map[string]json.RawMessage
|
||||||
@@ -68,6 +71,25 @@ func (s *EndpointService) Save(tx *gorm.DB, act string, data json.RawMessage) er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if endpoint.Type == "warp" {
|
||||||
|
if act == "new" {
|
||||||
|
err = s.WarpService.RegisterWarp(&endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var old_license string
|
||||||
|
err = tx.Model(model.Endpoint{}).Select("json_extract(ext, '$.license_key')").Where("id = ?", endpoint.Id).Find(&old_license).Error
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = s.WarpService.SetWarpLicense(old_license, &endpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if corePtr.IsRunning() {
|
if corePtr.IsRunning() {
|
||||||
configData, err := endpoint.MarshalJSON()
|
configData, err := endpoint.MarshalJSON()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -0,0 +1,229 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/base64"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"s-ui/database/model"
|
||||||
|
"s-ui/logger"
|
||||||
|
"s-ui/util/common"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WarpService struct{}
|
||||||
|
|
||||||
|
func (s *WarpService) getWarpInfo(ep *model.Endpoint) ([]byte, error) {
|
||||||
|
var warpData map[string]string
|
||||||
|
err := json.Unmarshal(ep.Ext, &warpData)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
url := fmt.Sprintf("https://api.cloudflareclient.com/v0a2158/reg/%s", warpData["device_id"])
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", "Bearer "+warpData["access_token"])
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
buffer := bytes.NewBuffer(make([]byte, 8192))
|
||||||
|
buffer.Reset()
|
||||||
|
_, err = buffer.ReadFrom(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *WarpService) RegisterWarp(ep *model.Endpoint) error {
|
||||||
|
tos := time.Now().UTC().Format("2006-01-02T15:04:05.000Z")
|
||||||
|
privateKey, _ := wgtypes.GenerateKey()
|
||||||
|
publicKey := privateKey.PublicKey().String()
|
||||||
|
hostName, _ := os.Hostname()
|
||||||
|
|
||||||
|
data := fmt.Sprintf(`{"key":"%s","tos":"%s","type": "PC","model": "s-ui", "name": "%s"}`, publicKey, tos, hostName)
|
||||||
|
url := "https://api.cloudflareclient.com/v0a2158/reg"
|
||||||
|
|
||||||
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer([]byte(data)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Header.Add("CF-Client-Version", "a-7.21-0721")
|
||||||
|
req.Header.Add("Content-Type", "application/json")
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
buffer := bytes.NewBuffer(make([]byte, 8192))
|
||||||
|
buffer.Reset()
|
||||||
|
_, err = buffer.ReadFrom(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var rspData map[string]interface{}
|
||||||
|
err = json.Unmarshal(buffer.Bytes(), &rspData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
deviceId := rspData["id"].(string)
|
||||||
|
token := rspData["token"].(string)
|
||||||
|
license, ok := rspData["account"].(map[string]interface{})["license"].(string)
|
||||||
|
if !ok {
|
||||||
|
logger.Debug("Error accessing license value.")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
warpData := map[string]string{
|
||||||
|
"access_token": token,
|
||||||
|
"device_id": deviceId,
|
||||||
|
"license_key": license,
|
||||||
|
}
|
||||||
|
|
||||||
|
ep.Ext, err = json.MarshalIndent(warpData, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
warpInfo, err := s.getWarpInfo(ep)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var warpDetails map[string]interface{}
|
||||||
|
err = json.Unmarshal(warpInfo, &warpDetails)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
warpConfig, _ := warpDetails["config"].(map[string]interface{})
|
||||||
|
clientId, _ := warpConfig["client_id"].(string)
|
||||||
|
reserved := s.getReserved(clientId)
|
||||||
|
interfaceConfig, _ := warpConfig["interface"].(map[string]interface{})
|
||||||
|
addresses, _ := interfaceConfig["addresses"].(map[string]interface{})
|
||||||
|
v4, _ := addresses["v4"].(string)
|
||||||
|
v6, _ := addresses["v6"].(string)
|
||||||
|
peer, _ := warpConfig["peers"].([]interface{})[0].(map[string]interface{})
|
||||||
|
peerEndpoint, _ := peer["endpoint"].(map[string]interface{})["host"].(string)
|
||||||
|
peerEpAddress, peerEpPort, err := net.SplitHostPort(peerEndpoint)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
peerPublicKey, _ := peer["public_key"].(string)
|
||||||
|
peerPort, _ := strconv.Atoi(peerEpPort)
|
||||||
|
|
||||||
|
peers := []map[string]interface{}{
|
||||||
|
{
|
||||||
|
"address": peerEpAddress,
|
||||||
|
"port": peerPort,
|
||||||
|
"public_key": peerPublicKey,
|
||||||
|
"allowed_ips": []string{"0.0.0.0/0", "::/0"},
|
||||||
|
"reserved": reserved,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var epOptions map[string]interface{}
|
||||||
|
err = json.Unmarshal(ep.Options, &epOptions)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
epOptions["private_key"] = privateKey.String()
|
||||||
|
epOptions["address"] = []string{fmt.Sprintf("%s/32", v4), fmt.Sprintf("%s/128", v6)}
|
||||||
|
epOptions["listen_port"] = 0
|
||||||
|
epOptions["peers"] = peers
|
||||||
|
|
||||||
|
ep.Options, err = json.MarshalIndent(epOptions, "", " ")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *WarpService) getReserved(clientID string) []int {
|
||||||
|
var reserved []int
|
||||||
|
decoded, err := base64.StdEncoding.DecodeString(clientID)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
hexString := ""
|
||||||
|
for _, char := range decoded {
|
||||||
|
hex := fmt.Sprintf("%02x", char)
|
||||||
|
hexString += hex
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < len(hexString); i += 2 {
|
||||||
|
hexByte := hexString[i : i+2]
|
||||||
|
decValue, err := strconv.ParseInt(hexByte, 16, 32)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
reserved = append(reserved, int(decValue))
|
||||||
|
}
|
||||||
|
|
||||||
|
return reserved
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *WarpService) SetWarpLicense(old_license string, ep *model.Endpoint) error {
|
||||||
|
var warpData map[string]string
|
||||||
|
err := json.Unmarshal(ep.Ext, &warpData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if warpData["license_key"] == old_license {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
url := fmt.Sprintf("https://api.cloudflareclient.com/v0a2158/reg/%s/account", warpData["device_id"])
|
||||||
|
data := fmt.Sprintf(`{"license": "%s"}`, warpData["license_key"])
|
||||||
|
|
||||||
|
req, err := http.NewRequest("PUT", url, bytes.NewBuffer([]byte(data)))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", "Bearer "+warpData["access_token"])
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
buffer := bytes.NewBuffer(make([]byte, 8192))
|
||||||
|
buffer.Reset()
|
||||||
|
_, err = buffer.ReadFrom(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
var response map[string]interface{}
|
||||||
|
err = json.Unmarshal(buffer.Bytes(), &response)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if success, ok := response["success"].(bool); ok && success == false {
|
||||||
|
errorArr, _ := response["errors"].([]interface{})
|
||||||
|
errorObj := errorArr[0].(map[string]interface{})
|
||||||
|
return common.NewError(errorObj["code"], errorObj["message"])
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
<template>
|
||||||
|
<v-card subtitle="Warp">
|
||||||
|
<template v-if="data.id>0">
|
||||||
|
<table dir="ltr" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td>Device ID</td>
|
||||||
|
<td>{{ data.ext.device_id }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Access Token</td>
|
||||||
|
<td>{{ data.ext.access_token }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ $t('types.wg.privKey') }}</td>
|
||||||
|
<td>{{ data.private_key }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ $t('types.wg.localIp') }}</td>
|
||||||
|
<td>{{ data.address.join(',') }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<v-text-field
|
||||||
|
v-model="data.ext.license_key"
|
||||||
|
label="License Key"
|
||||||
|
hide-details>
|
||||||
|
</v-text-field>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<v-card :subtitle="$t('types.wg.peer')">
|
||||||
|
<table dir="ltr" width="100%">
|
||||||
|
<tr>
|
||||||
|
<td>{{ $t('out.addr') }}</td>
|
||||||
|
<td>{{ data.peers[0].address + ":" + data.peers[0].port }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ $t('types.wg.pubKey') }}</td>
|
||||||
|
<td>{{ data.peers[0].public_key }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{{ $t('types.wg.allowedIp') }}</td>
|
||||||
|
<td>{{ data.peers[0].allowed_ips.join(',') }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Reserved</td>
|
||||||
|
<td>[{{ data.peers[0].reserved.join(',') }}]</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" sm="6" md="4" v-if="data.udp_timeout != undefined">
|
||||||
|
<v-text-field
|
||||||
|
label="UDP Timeout"
|
||||||
|
hide-details
|
||||||
|
type="number"
|
||||||
|
min=0
|
||||||
|
:suffix="$t('date.m')"
|
||||||
|
v-model.number="udp_timeout">
|
||||||
|
</v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="6" md="4" v-if="data.workers != undefined">
|
||||||
|
<v-text-field
|
||||||
|
:label="$t('types.wg.worker')"
|
||||||
|
hide-details
|
||||||
|
type="number"
|
||||||
|
min=1
|
||||||
|
v-model.number="data.workers">
|
||||||
|
</v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="6" md="4" v-if="data.mtu != undefined">
|
||||||
|
<v-text-field
|
||||||
|
label="MTU"
|
||||||
|
hide-details
|
||||||
|
type="number"
|
||||||
|
min=0
|
||||||
|
v-model.number="data.mtu">
|
||||||
|
</v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" sm="6" md="4">
|
||||||
|
<v-switch v-model="data.system" color="primary" :label="$t('types.wg.sysIf')" hide-details></v-switch>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" sm="6" md="4" v-if="data.system">
|
||||||
|
<v-text-field
|
||||||
|
:label="$t('types.wg.ifName')"
|
||||||
|
hide-details
|
||||||
|
v-model="ifName">
|
||||||
|
</v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-card-actions>
|
||||||
|
<v-spacer></v-spacer>
|
||||||
|
<v-menu v-model="menu" :close-on-content-click="false" location="start">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn v-bind="props" hide-details variant="tonal">{{ $t('types.wg.options') }}</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-card>
|
||||||
|
<v-list>
|
||||||
|
<v-list-item>
|
||||||
|
<v-switch v-model="optionUdp" color="primary" label="UDP Timeout" hide-details></v-switch>
|
||||||
|
</v-list-item>
|
||||||
|
<v-list-item>
|
||||||
|
<v-switch v-model="optionWorker" color="primary" :label="$t('types.wg.worker')" hide-details></v-switch>
|
||||||
|
</v-list-item>
|
||||||
|
<v-list-item>
|
||||||
|
<v-switch v-model="optionMtu" color="primary" label="MTU" hide-details></v-switch>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-card>
|
||||||
|
</v-menu>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: ['data'],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
menu: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
optionUdp: {
|
||||||
|
get(): boolean { return this.$props.data.udp_timeout != undefined },
|
||||||
|
set(v:boolean) { this.$props.data.udp_timeout = v ? "5m" : undefined }
|
||||||
|
},
|
||||||
|
optionWorker: {
|
||||||
|
get(): boolean { return this.$props.data.workers != undefined },
|
||||||
|
set(v:boolean) { this.$props.data.workers = v ? 2 : undefined }
|
||||||
|
},
|
||||||
|
optionMtu: {
|
||||||
|
get(): boolean { return this.$props.data.mtu != undefined },
|
||||||
|
set(v:boolean) { this.$props.data.mtu = v ? 1408 : undefined }
|
||||||
|
},
|
||||||
|
ifName: {
|
||||||
|
get() { return this.$props.data.name?? '' },
|
||||||
|
set(v:string) { this.$props.data.name = v.length > 0 ? v : undefined }
|
||||||
|
},
|
||||||
|
udp_timeout: {
|
||||||
|
get() { return this.$props.data.udp_timeout ? parseInt(this.$props.data.udp_timeout.replace('m','')) : 5 },
|
||||||
|
set(v:number) { this.$props.data.udp_timeout = v > 0 ? v + 'm' : '5m' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<Wireguard v-if="endpoint.type == epTypes.Wireguard" :data="endpoint" :options="options" @getWgPubKey="getWgPubKey" @newWgKey="newWgKey" />
|
<Wireguard v-if="endpoint.type == epTypes.Wireguard" :data="endpoint" :options="options" @getWgPubKey="getWgPubKey" @newWgKey="newWgKey" />
|
||||||
|
<Warp v-if="endpoint.type == epTypes.Warp" :data="endpoint" />
|
||||||
<Dial :dial="endpoint" :outTags="tags" />
|
<Dial :dial="endpoint" :outTags="tags" />
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
<v-card-actions>
|
<v-card-actions>
|
||||||
@@ -50,6 +51,7 @@ import { EpTypes, createEndpoint } from '@/types/endpoints'
|
|||||||
import RandomUtil from '@/plugins/randomUtil'
|
import RandomUtil from '@/plugins/randomUtil'
|
||||||
import Dial from '@/components/Dial.vue'
|
import Dial from '@/components/Dial.vue'
|
||||||
import Wireguard from '@/components/protocols/Wireguard.vue'
|
import Wireguard from '@/components/protocols/Wireguard.vue'
|
||||||
|
import Warp from '@/components/protocols/Warp.vue'
|
||||||
import HttpUtils from '@/plugins/httputil'
|
import HttpUtils from '@/plugins/httputil'
|
||||||
import { push } from 'notivue'
|
import { push } from 'notivue'
|
||||||
import { i18n } from '@/locales'
|
import { i18n } from '@/locales'
|
||||||
@@ -151,6 +153,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: { Dial, Wireguard }
|
components: { Dial, Wireguard, Warp }
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -2,6 +2,7 @@ import { Dial } from "./outbounds"
|
|||||||
|
|
||||||
export const EpTypes = {
|
export const EpTypes = {
|
||||||
Wireguard: 'wireguard',
|
Wireguard: 'wireguard',
|
||||||
|
Warp: 'warp',
|
||||||
}
|
}
|
||||||
|
|
||||||
type EpType = typeof EpTypes[keyof typeof EpTypes]
|
type EpType = typeof EpTypes[keyof typeof EpTypes]
|
||||||
@@ -34,6 +35,10 @@ export interface WireGuard extends EndpointBasics, Dial {
|
|||||||
workers?: number
|
workers?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface Warp extends WireGuard {
|
||||||
|
ext: any
|
||||||
|
}
|
||||||
|
|
||||||
// Create interfaces dynamically based on EpTypes keys
|
// Create interfaces dynamically based on EpTypes keys
|
||||||
type InterfaceMap = {
|
type InterfaceMap = {
|
||||||
[Key in keyof typeof EpTypes]: {
|
[Key in keyof typeof EpTypes]: {
|
||||||
@@ -48,6 +53,7 @@ export type Endpoint = InterfaceMap[keyof InterfaceMap]
|
|||||||
// Create defaultValues object dynamically
|
// Create defaultValues object dynamically
|
||||||
const defaultValues: Record<EpType, Endpoint> = {
|
const defaultValues: Record<EpType, Endpoint> = {
|
||||||
wireguard: { type: EpTypes.Wireguard, address: ['10.0.0.2/32','fe80::2/128'], private_key: '', listen_port: 0, peers: [{ address: '', port: 0, public_key: ''}] },
|
wireguard: { type: EpTypes.Wireguard, address: ['10.0.0.2/32','fe80::2/128'], private_key: '', listen_port: 0, peers: [{ address: '', port: 0, public_key: ''}] },
|
||||||
|
warp: { type: EpTypes.Warp, address: [], private_key: '', listen_port: 0, mtu: 1420, peers: [{ address: '', port: 0, public_key: ''}] },
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createEndpoint<T extends Endpoint>(type: string,json?: Partial<T>): Endpoint {
|
export function createEndpoint<T extends Endpoint>(type: string,json?: Partial<T>): Endpoint {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
<v-row>
|
<v-row>
|
||||||
<v-col>{{ $t('in.port') }}</v-col>
|
<v-col>{{ $t('in.port') }}</v-col>
|
||||||
<v-col>
|
<v-col>
|
||||||
{{ item.listen_port?? '-' }}
|
{{ item.listen_port>0 ? item.listen_port : '-' }}
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
<v-row>
|
<v-row>
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ const outboundTags = computed((): string[] => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const inboundTags = computed((): string[] => {
|
const inboundTags = computed((): string[] => {
|
||||||
return [...Data().inbounds?.map((o:any) => o.tag), ...Data().endpoints?.map((e:any) => e.tag)]
|
return [...Data().inbounds?.map((o:any) => o.tag), ...Data().endpoints?.filter((e:any) => e.listen_port > 0).map((e:any) => e.tag)]
|
||||||
})
|
})
|
||||||
|
|
||||||
let delRuleOverlay = ref(new Array<boolean>)
|
let delRuleOverlay = ref(new Array<boolean>)
|
||||||
|
|||||||
Reference in New Issue
Block a user