add configurable items for web/gui
Some checks are pending
EasyTier Core / pre_job (push) Waiting to run
EasyTier Core / build (freebsd-13.2-x86_64, 13.2, ubuntu-22.04, x86_64-unknown-freebsd) (push) Blocked by required conditions
EasyTier Core / build (linux-aarch64, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-arm, ubuntu-22.04, arm-unknown-linux-musleabi) (push) Blocked by required conditions
EasyTier Core / build (linux-armhf, ubuntu-22.04, arm-unknown-linux-musleabihf) (push) Blocked by required conditions
EasyTier Core / build (linux-armv7, ubuntu-22.04, armv7-unknown-linux-musleabi) (push) Blocked by required conditions
EasyTier Core / build (linux-armv7hf, ubuntu-22.04, armv7-unknown-linux-musleabihf) (push) Blocked by required conditions
EasyTier Core / build (linux-mips, ubuntu-22.04, mips-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-mipsel, ubuntu-22.04, mipsel-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (linux-x86_64, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier Core / build (macos-aarch64, macos-latest, aarch64-apple-darwin) (push) Blocked by required conditions
EasyTier Core / build (macos-x86_64, macos-latest, x86_64-apple-darwin) (push) Blocked by required conditions
EasyTier Core / build (windows-arm64, windows-latest, aarch64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier Core / build (windows-x86_64, windows-latest, x86_64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier Core / core-result (push) Blocked by required conditions
EasyTier GUI / pre_job (push) Waiting to run
EasyTier GUI / build-gui (linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier GUI / build-gui (linux-x86_64, x86_64-unknown-linux-gnu, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Blocked by required conditions
EasyTier GUI / build-gui (macos-aarch64, aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Blocked by required conditions
EasyTier GUI / build-gui (macos-x86_64, x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Blocked by required conditions
EasyTier GUI / build-gui (windows-arm64, aarch64-pc-windows-msvc, windows-latest, aarch64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier GUI / build-gui (windows-x86_64, x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Blocked by required conditions
EasyTier GUI / gui-result (push) Blocked by required conditions
EasyTier Mobile / pre_job (push) Waiting to run
EasyTier Mobile / build-mobile (android, ubuntu-22.04, android) (push) Blocked by required conditions
EasyTier Mobile / mobile-result (push) Blocked by required conditions
EasyTier Test / pre_job (push) Waiting to run
EasyTier Test / test (push) Blocked by required conditions

enable_exit_node
relay_all_peer_rpc
multi_thread
proxy_forward_by_system
relay_network_whitelist
manual_routes
exit_nodes
This commit is contained in:
kevin
2025-03-11 22:30:39 +08:00
committed by GitHub
parent ed08707c98
commit 1f4340e82f
10 changed files with 303 additions and 96 deletions

View File

@@ -120,6 +120,23 @@ function searchListenerSuggestions(e: { query: string }) {
listenerSuggestions.value = ret listenerSuggestions.value = ret
} }
const exitNodesSuggestions = ref([''])
function searchExitNodesSuggestions(e: { query: string }) {
const ret = []
ret.push(e.query)
exitNodesSuggestions.value = ret
}
const whitelistSuggestions = ref([''])
function searchWhitelistSuggestions(e: { query: string }) {
const ret = []
ret.push(e.query)
whitelistSuggestions.value = ret
}
interface BoolFlag { interface BoolFlag {
field: keyof NetworkConfig field: keyof NetworkConfig
help: string help: string
@@ -133,6 +150,10 @@ const bool_flags: BoolFlag[] = [
{ field: 'disable_p2p', help: 'disable_p2p_help' }, { field: 'disable_p2p', help: 'disable_p2p_help' },
{ field: 'bind_device', help: 'bind_device_help' }, { field: 'bind_device', help: 'bind_device_help' },
{ field: 'no_tun', help: 'no_tun_help' }, { field: 'no_tun', help: 'no_tun_help' },
{ field: 'enable_exit_node', help: 'enable_exit_node_help' },
{ field: 'relay_all_peer_rpc', help: 'relay_all_peer_rpc_help' },
{ field: 'multi_thread', help: 'multi_thread_help' },
{ field: 'proxy_forward_by_system', help: 'proxy_forward_by_system_help' },
] ]
</script> </script>
@@ -209,7 +230,7 @@ const bool_flags: BoolFlag[] = [
<label> {{ t('flags_switch') }} </label> <label> {{ t('flags_switch') }} </label>
<div class="flex flex-row flex-wrap"> <div class="flex flex-row flex-wrap">
<div class="basis-64 flex" v-for="flag in bool_flags"> <div class="basis-[20rem] flex items-center" v-for="flag in bool_flags">
<Checkbox v-model="curNetwork[flag.field]" :input-id="flag.field" :binary="true" /> <Checkbox v-model="curNetwork[flag.field]" :input-id="flag.field" :binary="true" />
<label :for="flag.field" class="ml-2"> {{ t(flag.field) }} </label> <label :for="flag.field" class="ml-2"> {{ t(flag.field) }} </label>
<span class="pi pi-question-circle ml-2 self-center" v-tooltip="t(flag.help)"></span> <span class="pi pi-question-circle ml-2 self-center" v-tooltip="t(flag.help)"></span>
@@ -242,17 +263,20 @@ const bool_flags: BoolFlag[] = [
<ToggleButton v-model="curNetwork.enable_vpn_portal" on-icon="pi pi-check" off-icon="pi pi-times" <ToggleButton v-model="curNetwork.enable_vpn_portal" on-icon="pi pi-check" off-icon="pi pi-times"
:on-label="t('off_text')" :off-label="t('on_text')" class="w-48" /> :on-label="t('off_text')" :off-label="t('on_text')" class="w-48" />
<div v-if="curNetwork.enable_vpn_portal" class="items-center flex flex-row gap-x-4"> <div v-if="curNetwork.enable_vpn_portal" class="items-center flex flex-row gap-x-4">
<div class="min-w-64"> <div class="flex flex-row gap-x-9 flex-wrap w-full">
<InputGroup> <div class="flex flex-col gap-2 basis-8/12 grow">
<InputText v-model="curNetwork.vpn_portal_client_network_addr" <InputGroup>
:placeholder="t('vpn_portal_client_network')" /> <InputText v-model="curNetwork.vpn_portal_client_network_addr"
<InputGroupAddon> :placeholder="t('vpn_portal_client_network')" />
<span>/{{ curNetwork.vpn_portal_client_network_len }}</span> <InputGroupAddon>
</InputGroupAddon> <span>/{{ curNetwork.vpn_portal_client_network_len }}</span>
</InputGroup> </InputGroupAddon>
</InputGroup>
<InputNumber v-model="curNetwork.vpn_portal_listen_port" :allow-empty="false" :format="false" </div>
:min="0" :max="65535" class="w-8/12" fluid /> <div class="flex flex-col gap-2 basis-3/12 grow">
<InputNumber v-model="curNetwork.vpn_portal_listen_port" :allow-empty="false" :format="false"
:min="0" :max="65535" fluid />
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -283,6 +307,56 @@ const bool_flags: BoolFlag[] = [
:placeholder="t('dev_name_placeholder')" /> :placeholder="t('dev_name_placeholder')" />
</div> </div>
</div> </div>
<div class="flex flex-row gap-x-9 flex-wrap">
<div class="flex flex-col gap-2 basis-5/12 grow">
<div class="flex">
<label for="relay_network_whitelist">{{ t('relay_network_whitelist') }}</label>
<span class="pi pi-question-circle ml-2 self-center"
v-tooltip="t('relay_network_whitelist_help')"></span>
</div>
<ToggleButton v-model="curNetwork.enable_relay_network_whitelist" on-icon="pi pi-check" off-icon="pi pi-times"
:on-label="t('off_text')" :off-label="t('on_text')" class="w-48" />
<div v-if="curNetwork.enable_relay_network_whitelist" class="items-center flex flex-row gap-x-4">
<div class="min-w-64 w-full">
<AutoComplete id="relay_network_whitelist" v-model="curNetwork.relay_network_whitelist"
:placeholder="t('relay_network_whitelist')" class="w-full" multiple fluid
:suggestions="whitelistSuggestions" @complete="searchWhitelistSuggestions" />
</div>
</div>
</div>
</div>
<div class="flex flex-row gap-x-9 flex-wrap ">
<div class="flex flex-col gap-2 grow">
<div class="flex">
<label for="routes">{{ t('manual_routes') }}</label>
<span class="pi pi-question-circle ml-2 self-center" v-tooltip="t('manual_routes_help')"></span>
</div>
<ToggleButton v-model="curNetwork.enable_manual_routes" on-icon="pi pi-check" off-icon="pi pi-times"
:on-label="t('off_text')" :off-label="t('on_text')" class="w-48" />
<div v-if="curNetwork.enable_manual_routes" class="items-center flex flex-row gap-x-4">
<div class="min-w-64 w-full">
<AutoComplete id="routes" v-model="curNetwork.routes"
:placeholder="t('chips_placeholder', ['192.168.0.0/16'])" class="w-full" multiple fluid
:suggestions="inetSuggestions" @complete="searchInetSuggestions" />
</div>
</div>
</div>
</div>
<div class="flex flex-row gap-x-9 flex-wrap w-full">
<div class="flex flex-col gap-2 grow p-fluid">
<div class="flex">
<label for="exit_nodes">{{ t('exit_nodes') }}</label>
<span class="pi pi-question-circle ml-2 self-center" v-tooltip="t('exit_nodes_help')"></span>
</div>
<AutoComplete id="exit_nodes" v-model="curNetwork.exit_nodes"
:placeholder="t('chips_placeholder', ['192.168.8.8'])" class="w-full" multiple fluid
:suggestions="exitNodesSuggestions" @complete="searchExitNodesSuggestions" />
</div>
</div>
</div> </div>
</Panel> </Panel>

View File

@@ -5,7 +5,7 @@ import { NetworkInstance, type NodeInfo, type PeerRoutePair } from '../types/net
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { computed, onMounted, onUnmounted, ref } from 'vue'; import { computed, onMounted, onUnmounted, ref } from 'vue';
import { ipv4InetToString, ipv4ToString, ipv6ToString } from '../modules/utils'; import { ipv4InetToString, ipv4ToString, ipv6ToString } from '../modules/utils';
import { DataTable, Column, Tag, Chip, Button, Dialog, ScrollPanel, Timeline, Divider, Card, } from 'primevue'; import { DataTable, Column, Tag, Chip, Button, Dialog, ScrollPanel, Timeline, Divider, Panel, } from 'primevue';
const props = defineProps<{ const props = defineProps<{
curNetworkInst: NetworkInstance | null, curNetworkInst: NetworkInstance | null,
@@ -318,107 +318,101 @@ function showEventLogs() {
</Timeline> </Timeline>
</Dialog> </Dialog>
<Card v-if="curNetworkInst?.error_msg"> <Panel v-if="curNetworkInst?.error_msg">
<template #title> <template #header>
Run Network Error Run Network Error
</template> </template>
<template #content> <div class="flex flex-col gap-y-5">
<div class="flex flex-col gap-y-5"> <div class="text-red-500">
<div class="text-red-500"> {{ curNetworkInst.error_msg }}
{{ curNetworkInst.error_msg }}
</div>
</div> </div>
</template> </div>
</Card> </Panel>
<template v-else> <template v-else>
<Card> <Panel>
<template #title> <template #header>
{{ t('my_node_info') }} {{ t('my_node_info') }}
</template> </template>
<template #content> <div class="flex w-full flex-col gap-y-5">
<div class="flex w-full flex-col gap-y-5"> <div class="m-0 flex flex-row justify-center gap-x-5">
<div class="m-0 flex flex-row justify-center gap-x-5"> <div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid green">
<div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid green"> <div class="font-bold">
<div class="font-bold"> {{ t('peer_count') }}
{{ t('peer_count') }}
</div>
<div class="text-5xl mt-1">
{{ peerCount }}
</div>
</div> </div>
<div class="text-5xl mt-1">
<div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid purple"> {{ peerCount }}
<div class="font-bold">
{{ t('upload') }}
</div>
<div class="text-xl mt-2">
{{ txRate }}/s
</div>
</div>
<div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid fuchsia">
<div class="font-bold">
{{ t('download') }}
</div>
<div class="text-xl mt-2">
{{ rxRate }}/s
</div>
</div> </div>
</div> </div>
<div class="flex flex-row items-center flex-wrap w-full max-h-40 overflow-scroll"> <div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid purple">
<Chip v-for="(chip, i) in myNodeInfoChips" :key="i" :label="chip.label" :icon="chip.icon" <div class="font-bold">
class="mr-2 mt-2 text-sm" /> {{ t('upload') }}
</div>
<div class="text-xl mt-2">
{{ txRate }}/s
</div>
</div> </div>
<div v-if="myNodeInfo" class="m-0 flex flex-row justify-center gap-x-5 text-sm"> <div class="rounded-full w-32 h-32 flex flex-col items-center pt-6" style="border: 1px solid fuchsia">
<Button severity="info" :label="t('show_vpn_portal_config')" @click="showVpnPortalConfig" /> <div class="font-bold">
<Button severity="info" :label="t('show_event_log')" @click="showEventLogs" /> {{ t('download') }}
</div>
<div class="text-xl mt-2">
{{ rxRate }}/s
</div>
</div> </div>
</div> </div>
</template>
</Card> <div class="flex flex-row items-center flex-wrap w-full max-h-40 overflow-scroll">
<Chip v-for="(chip, i) in myNodeInfoChips" :key="i" :label="chip.label" :icon="chip.icon"
class="mr-2 mt-2 text-sm" />
</div>
<div v-if="myNodeInfo" class="m-0 flex flex-row justify-center gap-x-5 text-sm">
<Button severity="info" :label="t('show_vpn_portal_config')" @click="showVpnPortalConfig" />
<Button severity="info" :label="t('show_event_log')" @click="showEventLogs" />
</div>
</div>
</Panel>
<Divider /> <Divider />
<Card> <Panel>
<template #title> <template #header>
{{ t('peer_info') }} {{ t('peer_info') }}
</template> </template>
<template #content> <DataTable :value="peerRouteInfos" column-resize-mode="fit" table-class="w-full">
<DataTable :value="peerRouteInfos" column-resize-mode="fit" table-class="w-full"> <Column :field="ipFormat" :header="t('virtual_ipv4')" />
<Column :field="ipFormat" :header="t('virtual_ipv4')" /> <Column :header="t('hostname')">
<Column :header="t('hostname')"> <template #body="slotProps">
<template #body="slotProps"> <div v-if="!slotProps.data.route.cost || !slotProps.data.route.feature_flag.is_public_server"
<div v-if="!slotProps.data.route.cost || !slotProps.data.route.feature_flag.is_public_server" v-tooltip="slotProps.data.route.hostname">
v-tooltip="slotProps.data.route.hostname"> {{
{{ slotProps.data.route.hostname }}
slotProps.data.route.hostname }} </div>
</div> <div v-else v-tooltip="slotProps.data.route.hostname" class="space-x-1">
<div v-else v-tooltip="slotProps.data.route.hostname" class="space-x-1"> <Tag v-if="slotProps.data.route.feature_flag.is_public_server" severity="info" value="Info">
<Tag v-if="slotProps.data.route.feature_flag.is_public_server" severity="info" value="Info"> {{ t('status.server') }}
{{ t('status.server') }} </Tag>
</Tag> <Tag v-if="slotProps.data.route.feature_flag.avoid_relay_data" severity="warn" value="Warn">
<Tag v-if="slotProps.data.route.feature_flag.avoid_relay_data" severity="warn" value="Warn"> {{ t('status.relay') }}
{{ t('status.relay') }} </Tag>
</Tag> </div>
</div> </template>
</template> </Column>
</Column> <Column :field="routeCost" :header="t('route_cost')" />
<Column :field="routeCost" :header="t('route_cost')" /> <Column :field="latencyMs" :header="t('latency')" />
<Column :field="latencyMs" :header="t('latency')" /> <Column :field="txBytes" :header="t('upload_bytes')" />
<Column :field="txBytes" :header="t('upload_bytes')" /> <Column :field="rxBytes" :header="t('download_bytes')" />
<Column :field="rxBytes" :header="t('download_bytes')" /> <Column :field="lossRate" :header="t('loss_rate')" />
<Column :field="lossRate" :header="t('loss_rate')" /> <Column :header="t('status.version')">
<Column :header="t('status.version')"> <template #body="slotProps">
<template #body="slotProps"> <span>{{ version(slotProps.data) }}</span>
<span>{{ version(slotProps.data) }}</span> </template>
</template> </Column>
</Column> </DataTable>
</DataTable> </Panel>
</template>
</Card>
</template> </template>
</div> </div>
</template> </template>

View File

@@ -92,6 +92,32 @@ bind_device_help: 仅使用物理网卡,避免 EasyTier 通过其他虚拟网
no_tun: 无 TUN 模式 no_tun: 无 TUN 模式
no_tun_help: 不使用 TUN 网卡,适合无管理员权限时使用。本节点仅允许被访问。访问其他节点需要使用 SOCK5 no_tun_help: 不使用 TUN 网卡,适合无管理员权限时使用。本节点仅允许被访问。访问其他节点需要使用 SOCK5
enable_exit_node: 启用出口节点
enable_exit_node_help: 允许此节点成为出口节点
relay_all_peer_rpc: 转发RPC包
relay_all_peer_rpc_help: |
允许转发所有对等节点的RPC数据包即使对等节点不在转发网络白名单中。
这可以帮助白名单外网络中的对等节点建立P2P连接。
multi_thread: 启用多线程
multi_thread_help: 使用多线程运行时
proxy_forward_by_system: 系统转发
proxy_forward_by_system_help: 通过系统内核转发子网代理数据包禁用内置NAT
relay_network_whitelist: 网络白名单
relay_network_whitelist_help: |
仅转发白名单网络的流量,支持通配符字符串。多个网络名称间可以使用英文空格间隔。
如果该参数为空,则禁用转发。默认允许所有网络。
例如:'*'(所有网络),'def*'以def为前缀的网络'net1 net2'只允许net1和net2
manual_routes: 自定义路由
manual_routes_help: 手动分配路由CIDR将禁用子网代理和从对等节点传播的wireguard路由。例如192.168.0.0/16
exit_nodes: 出口节点列表
exit_nodes_help: 转发所有流量的出口节点虚拟IPv4地址优先级由列表顺序决定
status: status:
version: 内核版本 version: 内核版本
local: 本机 local: 本机

View File

@@ -91,6 +91,33 @@ bind_device_help: Use only the physical network interface to prevent EasyTier fr
no_tun: No TUN Mode no_tun: No TUN Mode
no_tun_help: Do not use a TUN interface, suitable for environments without administrator privileges. This node is only accessible; accessing other nodes requires SOCKS5. no_tun_help: Do not use a TUN interface, suitable for environments without administrator privileges. This node is only accessible; accessing other nodes requires SOCKS5.
enable_exit_node: Enable Exit Node
enable_exit_node_help: Allow this node to be an exit node
relay_all_peer_rpc: Relay RPC Packets
relay_all_peer_rpc_help: |
Relay all peer rpc packets, even if the peer is not in the relay network whitelist.
This can help peers not in relay network whitelist to establish p2p connection.
multi_thread: Multi Thread
multi_thread_help: Use multi-thread runtime
proxy_forward_by_system: System Forward
proxy_forward_by_system_help: Forward packet to proxy networks via system kernel, disable internal nat for network proxy
relay_network_whitelist: Network Whitelist
relay_network_whitelist_help: |
Only forward traffic from the whitelist networks, supporting wildcard strings, multiple network names can be separated by spaces.
If this parameter is empty, forwarding is disabled. By default, all networks are allowed.
e.g.: '*' (all networks), 'def*' (networks with the prefix 'def'), 'net1 net2' (only allow net1 and net2)
manual_routes: Manual Route
manual_routes_help: |
Assign routes cidr manually, will disable subnet proxy and wireguard routes propagated from peers. e.g.:192.168.0.0/16
exit_nodes: Exit Nodes
exit_nodes_help: Exit nodes to forward all traffic to, a virtual ipv4 address, priority is determined by the order of the list
status: status:
version: Version version: Version
local: Local local: Local

View File

@@ -51,4 +51,8 @@
background-color: #0000005d; background-color: #0000005d;
} }
}
.v-popper__inner {
white-space: pre-wrap;
} }

View File

@@ -42,6 +42,18 @@ export interface NetworkConfig {
disable_p2p?: boolean disable_p2p?: boolean
bind_device?: boolean bind_device?: boolean
no_tun?: boolean no_tun?: boolean
enable_exit_node?: boolean
relay_all_peer_rpc?: boolean
multi_thread?: boolean
proxy_forward_by_system?: boolean
enable_relay_network_whitelist?: boolean
relay_network_whitelist: string[]
enable_manual_routes: boolean
routes: string[]
exit_nodes: string[]
} }
export function DEFAULT_NETWORK_CONFIG(): NetworkConfig { export function DEFAULT_NETWORK_CONFIG(): NetworkConfig {
@@ -83,6 +95,15 @@ export function DEFAULT_NETWORK_CONFIG(): NetworkConfig {
disable_p2p: false, disable_p2p: false,
bind_device: true, bind_device: true,
no_tun: false, no_tun: false,
enable_exit_node: false,
relay_all_peer_rpc: false,
multi_thread: true,
proxy_forward_by_system: false,
enable_relay_network_whitelist: false,
relay_network_whitelist: [],
enable_manual_routes: false,
routes: [],
exit_nodes: [],
} }
} }

View File

@@ -102,7 +102,7 @@ const selectedDeviceHostname = computed<string | undefined>(() => {
</DataTable> </DataTable>
<Drawer v-model:visible="deviceManageVisible" :header="`Manage ${selectedDeviceHostname}`" position="right" <Drawer v-model:visible="deviceManageVisible" :header="`Manage ${selectedDeviceHostname}`" position="right"
class="w-1/2 min-w-96"> class="w-3/5 min-w-96">
<RouterView v-slot="{ Component }"> <RouterView v-slot="{ Component }">
<component :is="Component" :api="api" :deviceList="deviceList" @update="loadDevices" /> <component :is="Component" :api="api" :deviceList="deviceList" @update="loadDevices" />
</RouterView> </RouterView>

View File

@@ -1,5 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import { Toolbar, IftaLabel, Select, Button, ConfirmPopup, Dialog, useConfirm, useToast } from 'primevue'; import {Toolbar, IftaLabel, Select, Button, ConfirmPopup, Dialog, useConfirm, useToast, Divider} from 'primevue';
import { NetworkTypes, Status, Utils, Api, } from 'easytier-frontend-lib'; import { NetworkTypes, Status, Utils, Api, } from 'easytier-frontend-lib';
import { watch, computed, onMounted, onUnmounted, ref } from 'vue'; import { watch, computed, onMounted, onUnmounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router'; import { useRoute, useRouter } from 'vue-router';
@@ -251,10 +251,13 @@ onUnmounted(() => {
</template> </template>
</Toolbar> </Toolbar>
<Divider />
<!-- For running network, show the status --> <!-- For running network, show the status -->
<div v-if="needShowNetworkStatus"> <div v-if="needShowNetworkStatus">
<Status v-bind:cur-network-inst="curNetworkInfo" v-if="needShowNetworkStatus"> <Status v-bind:cur-network-inst="curNetworkInfo" v-if="needShowNetworkStatus">
</Status> </Status>
<Divider />
<center> <center>
<Button @click="updateNetworkState(true)" label="Disable Network" severity="warn" /> <Button @click="updateNetworkState(true)" label="Disable Network" severity="warn" />
</center> </center>

View File

@@ -517,6 +517,29 @@ impl NetworkConfig {
})?, })?,
}); });
} }
if self.enable_manual_routes.unwrap_or_default() {
let mut routes = Vec::<cidr::Ipv4Cidr>::with_capacity(self.routes.len());
for route in self.routes.iter() {
routes.push(
route.parse()
.with_context(|| format!("failed to parse route: {}", route))?,
);
}
cfg.set_routes(Some(routes));
}
if self.exit_nodes.len() > 0 {
let mut exit_nodes = Vec::<std::net::Ipv4Addr>::with_capacity(self.exit_nodes.len());
for node in self.exit_nodes.iter() {
exit_nodes.push(
node.parse()
.with_context(|| format!("failed to parse exit node: {}", node))?,
);
}
cfg.set_exit_nodes(exit_nodes);
}
let mut flags = gen_default_flags(); let mut flags = gen_default_flags();
if let Some(latency_first) = self.latency_first { if let Some(latency_first) = self.latency_first {
flags.latency_first = latency_first; flags.latency_first = latency_first;
@@ -550,6 +573,31 @@ impl NetworkConfig {
flags.no_tun = no_tun; flags.no_tun = no_tun;
} }
if let Some(enable_exit_node) = self.enable_exit_node {
flags.enable_exit_node = enable_exit_node;
}
if let Some(relay_all_peer_rpc) = self.relay_all_peer_rpc {
flags.relay_all_peer_rpc = relay_all_peer_rpc;
}
if let Some(multi_thread) = self.multi_thread {
flags.multi_thread = multi_thread;
}
if let Some(proxy_forward_by_system) = self.proxy_forward_by_system {
flags.proxy_forward_by_system = proxy_forward_by_system;
}
if self.enable_relay_network_whitelist.unwrap_or_default() {
if self.relay_network_whitelist.len() > 0 {
flags.relay_network_whitelist = self.relay_network_whitelist.join(" ")
} else {
flags.relay_network_whitelist = "".to_string()
}
}
cfg.set_flags(flags); cfg.set_flags(flags);
Ok(cfg) Ok(cfg)
} }

View File

@@ -47,6 +47,16 @@ message NetworkConfig {
optional bool disable_p2p = 24; optional bool disable_p2p = 24;
optional bool bind_device = 25; optional bool bind_device = 25;
optional bool no_tun = 26; optional bool no_tun = 26;
optional bool enable_exit_node = 27;
optional bool relay_all_peer_rpc = 28;
optional bool multi_thread = 29;
optional bool enable_relay_network_whitelist = 30;
repeated string relay_network_whitelist = 31;
optional bool enable_manual_routes = 32;
repeated string routes = 33;
repeated string exit_nodes = 34;
optional bool proxy_forward_by_system = 35;
} }
message MyNodeInfo { message MyNodeInfo {