mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-04-23 00:27:06 +08:00
67cba2c326
EasyTier Core / pre_job (push) Has been cancelled
EasyTier GUI / pre_job (push) Has been cancelled
EasyTier Mobile / pre_job (push) Has been cancelled
EasyTier OHOS / cargo_fmt_check (push) Has been cancelled
EasyTier OHOS / pre_job (push) Has been cancelled
EasyTier Test / pre_job (push) Has been cancelled
EasyTier Core / build_web (push) Has been cancelled
EasyTier Core / build (freebsd-13.2-x86_64, 13.2, ubuntu-22.04, x86_64-unknown-freebsd) (push) Has been cancelled
EasyTier Core / build (linux-aarch64, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-arm, ubuntu-22.04, arm-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armhf, ubuntu-22.04, arm-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-armv7, ubuntu-22.04, armv7-unknown-linux-musleabi) (push) Has been cancelled
EasyTier Core / build (linux-armv7hf, ubuntu-22.04, armv7-unknown-linux-musleabihf) (push) Has been cancelled
EasyTier Core / build (linux-loongarch64, ubuntu-24.04, loongarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-mips, ubuntu-22.04, mips-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-mipsel, ubuntu-22.04, mipsel-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-riscv64, ubuntu-22.04, riscv64gc-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (linux-x86_64, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier Core / build (macos-aarch64, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (macos-x86_64, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier Core / build (windows-arm64, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-i686, windows-latest, i686-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / build (windows-x86_64, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier Core / core-result (push) Has been cancelled
EasyTier Core / magisk_build (push) Has been cancelled
EasyTier GUI / build-gui (linux-aarch64, aarch64-unknown-linux-gnu, ubuntu-22.04, aarch64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (linux-x86_64, x86_64-unknown-linux-gnu, ubuntu-22.04, x86_64-unknown-linux-musl) (push) Has been cancelled
EasyTier GUI / build-gui (macos-aarch64, aarch64-apple-darwin, macos-latest, aarch64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (macos-x86_64, x86_64-apple-darwin, macos-latest, x86_64-apple-darwin) (push) Has been cancelled
EasyTier GUI / build-gui (windows-arm64, aarch64-pc-windows-msvc, windows-latest, aarch64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-i686, i686-pc-windows-msvc, windows-latest, i686-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / build-gui (windows-x86_64, x86_64-pc-windows-msvc, windows-latest, x86_64-pc-windows-msvc) (push) Has been cancelled
EasyTier GUI / gui-result (push) Has been cancelled
EasyTier Mobile / build-mobile (android, ubuntu-22.04, android) (push) Has been cancelled
EasyTier Mobile / mobile-result (push) Has been cancelled
EasyTier OHOS / build-ohos (push) Has been cancelled
EasyTier Test / test (push) Has been cancelled
* Add DNS route if accept_dns is enabled * Update doStartVpn to accept optional DNS parameter
202 lines
5.0 KiB
TypeScript
202 lines
5.0 KiB
TypeScript
import type { NetworkTypes } from 'easytier-frontend-lib'
|
|
import { addPluginListener } from '@tauri-apps/api/core'
|
|
import { Utils } from 'easytier-frontend-lib'
|
|
import { prepare_vpn, start_vpn, stop_vpn } from 'tauri-plugin-vpnservice-api'
|
|
|
|
type Route = NetworkTypes.Route
|
|
|
|
interface vpnStatus {
|
|
running: boolean
|
|
ipv4Addr: string | null | undefined
|
|
ipv4Cidr: number | null | undefined
|
|
routes: string[]
|
|
dns: string | null | undefined
|
|
}
|
|
|
|
const curVpnStatus: vpnStatus = {
|
|
running: false,
|
|
ipv4Addr: undefined,
|
|
ipv4Cidr: undefined,
|
|
routes: [],
|
|
dns: undefined,
|
|
}
|
|
|
|
async function waitVpnStatus(target_status: boolean, timeout_sec: number) {
|
|
const start_time = Date.now()
|
|
while (curVpnStatus.running !== target_status) {
|
|
if (Date.now() - start_time > timeout_sec * 1000) {
|
|
throw new Error('wait vpn status timeout')
|
|
}
|
|
await new Promise(r => setTimeout(r, 50))
|
|
}
|
|
}
|
|
|
|
async function doStopVpn() {
|
|
if (!curVpnStatus.running) {
|
|
return
|
|
}
|
|
console.log('stop vpn')
|
|
const stop_ret = await stop_vpn()
|
|
console.log('stop vpn', JSON.stringify((stop_ret)))
|
|
await waitVpnStatus(false, 3)
|
|
|
|
curVpnStatus.ipv4Addr = undefined
|
|
curVpnStatus.routes = []
|
|
curVpnStatus.dns = undefined
|
|
}
|
|
|
|
async function doStartVpn(ipv4Addr: string, cidr: number, routes: string[], dns?: string) {
|
|
if (curVpnStatus.running) {
|
|
return
|
|
}
|
|
|
|
console.log('start vpn service', ipv4Addr, cidr, routes, dns)
|
|
const start_ret = await start_vpn({
|
|
ipv4Addr: `${ipv4Addr}/${cidr}`,
|
|
routes,
|
|
dns,
|
|
disallowedApplications: ['com.kkrainbow.easytier'],
|
|
mtu: 1300,
|
|
})
|
|
if (start_ret?.errorMsg?.length) {
|
|
throw new Error(start_ret.errorMsg)
|
|
}
|
|
await waitVpnStatus(true, 3)
|
|
|
|
curVpnStatus.ipv4Addr = ipv4Addr
|
|
curVpnStatus.routes = routes
|
|
curVpnStatus.dns = dns
|
|
}
|
|
|
|
async function onVpnServiceStart(payload: any) {
|
|
console.log('vpn service start', JSON.stringify(payload))
|
|
curVpnStatus.running = true
|
|
if (payload.fd) {
|
|
setTunFd(payload.fd)
|
|
}
|
|
}
|
|
|
|
async function onVpnServiceStop(payload: any) {
|
|
console.log('vpn service stop', JSON.stringify(payload))
|
|
curVpnStatus.running = false
|
|
}
|
|
|
|
async function registerVpnServiceListener() {
|
|
console.log('register vpn service listener')
|
|
await addPluginListener(
|
|
'vpnservice',
|
|
'vpn_service_start',
|
|
onVpnServiceStart,
|
|
)
|
|
|
|
await addPluginListener(
|
|
'vpnservice',
|
|
'vpn_service_stop',
|
|
onVpnServiceStop,
|
|
)
|
|
}
|
|
|
|
function getRoutesForVpn(routes: Route[], node_config: NetworkTypes.NetworkConfig): string[] {
|
|
if (!routes) {
|
|
return []
|
|
}
|
|
|
|
const ret = []
|
|
for (const r of routes) {
|
|
for (let cidr of r.proxy_cidrs) {
|
|
if (!cidr.includes('/')) {
|
|
cidr += '/32'
|
|
}
|
|
ret.push(cidr)
|
|
}
|
|
}
|
|
|
|
node_config.routes.forEach(r => {
|
|
ret.push(r)
|
|
})
|
|
|
|
if (node_config.enable_magic_dns) {
|
|
ret.push('100.100.100.101/32')
|
|
}
|
|
|
|
// sort and dedup
|
|
return Array.from(new Set(ret)).sort()
|
|
}
|
|
|
|
export async function onNetworkInstanceChange(instanceId: string) {
|
|
console.error('vpn service network instance change id', instanceId)
|
|
if (!instanceId) {
|
|
await doStopVpn()
|
|
return
|
|
}
|
|
const config = await getConfig(instanceId)
|
|
if (config.no_tun) {
|
|
return
|
|
}
|
|
const curNetworkInfo = (await collectNetworkInfo(instanceId)).info.map[instanceId]
|
|
if (!curNetworkInfo || curNetworkInfo?.error_msg?.length) {
|
|
await doStopVpn()
|
|
return
|
|
}
|
|
|
|
const virtual_ip = Utils.ipv4ToString(curNetworkInfo?.my_node_info?.virtual_ipv4.address)
|
|
if (!virtual_ip || !virtual_ip.length) {
|
|
await doStopVpn()
|
|
return
|
|
}
|
|
|
|
let network_length = curNetworkInfo?.my_node_info?.virtual_ipv4.network_length
|
|
if (!network_length) {
|
|
network_length = 24
|
|
}
|
|
|
|
const routes = getRoutesForVpn(curNetworkInfo?.routes, config)
|
|
|
|
const dns = config.enable_magic_dns ? '100.100.100.101' : undefined;
|
|
|
|
const ipChanged = virtual_ip !== curVpnStatus.ipv4Addr
|
|
const routesChanged = JSON.stringify(routes) !== JSON.stringify(curVpnStatus.routes)
|
|
const dnsChanged = dns != curVpnStatus.dns
|
|
|
|
if (ipChanged || routesChanged || dnsChanged) {
|
|
console.info('vpn service virtual ip changed', JSON.stringify(curVpnStatus), virtual_ip)
|
|
try {
|
|
await doStopVpn()
|
|
}
|
|
catch (e) {
|
|
console.error(e)
|
|
}
|
|
|
|
try {
|
|
await doStartVpn(virtual_ip, network_length, routes, dns)
|
|
}
|
|
catch (e) {
|
|
console.error('start vpn service failed, stop all other network insts.', e)
|
|
await runNetworkInstance(config, true); //on android config should always be saved
|
|
}
|
|
}
|
|
}
|
|
|
|
async function isNoTunEnabled(instanceId: string | undefined) {
|
|
if (!instanceId) {
|
|
return false
|
|
}
|
|
return (await getConfig(instanceId)).no_tun ?? false
|
|
}
|
|
|
|
export async function initMobileVpnService() {
|
|
await registerVpnServiceListener()
|
|
}
|
|
|
|
export async function prepareVpnService(instanceId: string) {
|
|
if (await isNoTunEnabled(instanceId)) {
|
|
return
|
|
}
|
|
console.log('prepare vpn')
|
|
const prepare_ret = await prepare_vpn()
|
|
console.log('prepare vpn', JSON.stringify((prepare_ret)))
|
|
if (prepare_ret?.errorMsg?.length) {
|
|
throw new Error(prepare_ret.errorMsg)
|
|
}
|
|
}
|