mirror of
https://github.com/wireadmin/wireadmin
synced 2025-06-26 18:28:06 +00:00
bug fix
This commit is contained in:
parent
440a6189bd
commit
c521faf7df
@ -4,9 +4,6 @@ services:
|
|||||||
image: wireadmin
|
image: wireadmin
|
||||||
volumes:
|
volumes:
|
||||||
- ./src/:/app/
|
- ./src/:/app/
|
||||||
ports:
|
|
||||||
- "4040:4040/udp" # Direct
|
|
||||||
- "4050:4050/udp" # Tor
|
|
||||||
environment:
|
environment:
|
||||||
- UI_PASSWORD=password
|
- UI_PASSWORD=password
|
||||||
- WG_HOST=127.0.0.1
|
- WG_HOST=192.168.1.102
|
||||||
|
@ -19,12 +19,10 @@ fi
|
|||||||
screen -dmS redis bash -c "redis-server --port 6479 --daemonize no --dir /data --appendonly yes"
|
screen -dmS redis bash -c "redis-server --port 6479 --daemonize no --dir /data --appendonly yes"
|
||||||
|
|
||||||
# Start Tor in the background
|
# Start Tor in the background
|
||||||
screen -dmS tor bash -c "tor -f /etc/tor/torrc"
|
screen -dmS tor bash -c "sleep 1; tor -f /etc/tor/torrc"
|
||||||
|
|
||||||
# If WG_HOST exists, again export it as NEXT_PUBLIC_WG_HOST
|
# If WG_HOST exists, again export it as NEXT_PUBLIC_WG_HOST
|
||||||
if [ ! -z "$WG_HOST" ]; then
|
export NEXT_PUBLIC_WG_HOST="$WG_HOST"
|
||||||
export NEXT_PUBLIC_WG_HOST=$WG_HOST
|
|
||||||
fi
|
|
||||||
|
|
||||||
# After 5 seconds, export the database to the WireGuard config file
|
# After 5 seconds, export the database to the WireGuard config file
|
||||||
screen -dm bash -c "sleep 5; curl -s -o /dev/null http://127.0.0.1:3000/api/wireguard/regen"
|
screen -dm bash -c "sleep 5; curl -s -o /dev/null http://127.0.0.1:3000/api/wireguard/regen"
|
||||||
|
@ -29,7 +29,7 @@ export const PortSchema = z
|
|||||||
message: 'Port must be a valid port number'
|
message: 'Port must be a valid port number'
|
||||||
})
|
})
|
||||||
|
|
||||||
export const TypeSchema = z.enum([ 'default', 'tor' ])
|
export const TypeSchema = z.enum([ 'direct', 'tor' ])
|
||||||
|
|
||||||
export const DnsSchema = z
|
export const DnsSchema = z
|
||||||
.string()
|
.string()
|
||||||
|
@ -30,8 +30,9 @@ export function getServerConf(server: WgServer): string {
|
|||||||
|
|
||||||
type Peer = WgServer['peers'][0]
|
type Peer = WgServer['peers'][0]
|
||||||
|
|
||||||
interface GenPeerConParams extends Peer {
|
interface GenPeerConParams extends Peer, Pick<WgServer, 'dns'> {
|
||||||
serverAddress?: string
|
serverAddress?: string
|
||||||
|
serverPublicKey: string
|
||||||
port: number
|
port: number
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,12 +41,13 @@ export function getPeerConf(params: GenPeerConParams): string {
|
|||||||
'# Autogenerated by WireGuard UI (WireAdmin)',
|
'# Autogenerated by WireGuard UI (WireAdmin)',
|
||||||
'[Interface]',
|
'[Interface]',
|
||||||
`PrivateKey = ${params.privateKey}`,
|
`PrivateKey = ${params.privateKey}`,
|
||||||
`Address = ${params.allowedIps}/32`,
|
`Address = ${params.allowedIps}/24`,
|
||||||
|
`${params.dns ? `DNS = ${params.dns}` : 'OMIT'}`,
|
||||||
'',
|
'',
|
||||||
'[Peer]',
|
'[Peer]',
|
||||||
`PublicKey = ${params.publicKey}`,
|
`PublicKey = ${params.serverPublicKey}`,
|
||||||
`${params.preSharedKey ? `PresharedKey = ${params.preSharedKey}` : 'OMIT'}`,
|
`${params.preSharedKey ? `PresharedKey = ${params.preSharedKey}` : 'OMIT'}`,
|
||||||
`AllowedIPs = ${params.allowedIps}/32`,
|
`AllowedIPs = 0.0.0.0/0, ::/0`,
|
||||||
`PersistentKeepalive = ${params.persistentKeepalive}`,
|
`PersistentKeepalive = ${params.persistentKeepalive}`,
|
||||||
`Endpoint = ${params.serverAddress || process.env.NEXT_PUBLIC_WG_HOST}:${params.port}`,
|
`Endpoint = ${params.serverAddress || process.env.NEXT_PUBLIC_WG_HOST}:${params.port}`,
|
||||||
]
|
]
|
||||||
|
@ -16,7 +16,10 @@ export class WGServer {
|
|||||||
console.error('server could not be updated (reason: not exists)')
|
console.error('server could not be updated (reason: not exists)')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
await Shell.exec(`ip link set down dev wg${server.confId}`, true)
|
|
||||||
|
await Shell.exec(`wg-quick down wg${server.confId}`, true)
|
||||||
|
await dropInterface(server.confId)
|
||||||
|
|
||||||
await this.update(id, { status: 'down' })
|
await this.update(id, { status: 'down' })
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -27,8 +30,10 @@ export class WGServer {
|
|||||||
console.error('server could not be updated (reason: not exists)')
|
console.error('server could not be updated (reason: not exists)')
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
await createInterface(server.confId, server.address)
|
|
||||||
await Shell.exec(`ip link set up dev wg${server.confId}`)
|
await Shell.exec(`wg-quick down wg${server.confId}`, true)
|
||||||
|
await Shell.exec(`wg-quick up wg${server.confId}`)
|
||||||
|
|
||||||
await this.update(id, { status: 'up' })
|
await this.update(id, { status: 'up' })
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -189,7 +194,12 @@ export class WGServer {
|
|||||||
console.error('generatePeerConfig: peer not found')
|
console.error('generatePeerConfig: peer not found')
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
return getPeerConf({ ...peer, port: server.listen })
|
return getPeerConf({
|
||||||
|
...peer,
|
||||||
|
serverPublicKey: server.publicKey,
|
||||||
|
port: server.listen,
|
||||||
|
dns: server.dns
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -402,16 +412,14 @@ export async function generateWgServer(config: {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// to ensure interface does not exists
|
// to ensure interface does not exists
|
||||||
|
await Shell.exec(`wg-quick down wg${confId}`, true)
|
||||||
await dropInterface(confId)
|
await dropInterface(confId)
|
||||||
await Shell.exec(`ip link set down dev wg${confId}`, true)
|
|
||||||
|
|
||||||
|
|
||||||
// create a interface
|
// create a interface
|
||||||
await createInterface(confId, config.address)
|
// await createInterface(confId, config.address)
|
||||||
|
|
||||||
// restart WireGuard
|
// restart WireGuard
|
||||||
await Shell.exec(`wg setconf wg${confId} ${CONFIG_PATH}`)
|
await Shell.exec(`wg-quick up wg${confId}`)
|
||||||
await Shell.exec(`ip link set up dev wg${confId}`)
|
|
||||||
|
|
||||||
// return server id
|
// return server id
|
||||||
return uuid
|
return uuid
|
||||||
@ -502,7 +510,7 @@ async function makeWgIptables(s: WgServer): Promise<{
|
|||||||
up: string
|
up: string
|
||||||
down: string
|
down: string
|
||||||
}> {
|
}> {
|
||||||
const inet = Shell.exec('ip route | grep default | grep -oP "(?<=dev )[^ ]+"')
|
const inet = await Shell.exec('ip route list default | awk \'{print $5}\'')
|
||||||
const wgAddress = `${s.address}/24`
|
const wgAddress = `${s.address}/24`
|
||||||
const wgInet = `wg${s.confId}`
|
const wgInet = `wg${s.confId}`
|
||||||
|
|
||||||
|
@ -9,7 +9,9 @@ function publicENV(ex = {}) {
|
|||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
transpilePackages: [],
|
transpilePackages: [],
|
||||||
env: publicENV()
|
env: publicENV({
|
||||||
|
NEXT_PUBLIC_WG_HOST: process.env.WG_HOST
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = nextConfig;
|
module.exports = nextConfig;
|
||||||
|
@ -190,6 +190,8 @@ export default function ServerPage(props: PageProps) {
|
|||||||
key={s.id}
|
key={s.id}
|
||||||
{...s}
|
{...s}
|
||||||
serverId={props.serverId}
|
serverId={props.serverId}
|
||||||
|
serverPublicKey={data?.publicKey}
|
||||||
|
dns={data?.dns}
|
||||||
listenPort={data?.listen}
|
listenPort={data?.listen}
|
||||||
refreshTrigger={() => refresh()}
|
refreshTrigger={() => refresh()}
|
||||||
/>
|
/>
|
||||||
@ -214,8 +216,9 @@ export default function ServerPage(props: PageProps) {
|
|||||||
|
|
||||||
type Peer = WgServer['peers'][0]
|
type Peer = WgServer['peers'][0]
|
||||||
|
|
||||||
interface ClientProps extends Peer {
|
interface ClientProps extends Peer, Pick<WgServer, 'dns'> {
|
||||||
serverId: string
|
serverId: string
|
||||||
|
serverPublicKey: string
|
||||||
listenPort: number
|
listenPort: number
|
||||||
refreshTrigger: () => void
|
refreshTrigger: () => void
|
||||||
}
|
}
|
||||||
@ -229,7 +232,9 @@ function Client(props: ClientProps) {
|
|||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
setConf(getPeerConf({
|
setConf(getPeerConf({
|
||||||
...props,
|
...props,
|
||||||
port: props.listenPort
|
serverPublicKey: props.serverPublicKey,
|
||||||
|
port: props.listenPort,
|
||||||
|
dns: props.dns,
|
||||||
}))
|
}))
|
||||||
console.log('conf', conf)
|
console.log('conf', conf)
|
||||||
}, [ props ])
|
}, [ props ])
|
||||||
@ -254,12 +259,18 @@ function Client(props: ClientProps) {
|
|||||||
return (
|
return (
|
||||||
<List.Item key={props.id} className={'flex items-center justify-between p-4'}>
|
<List.Item key={props.id} className={'flex items-center justify-between p-4'}>
|
||||||
<QRCodeModal ref={qrcodeRef} content={conf?.trim() || 'null'} />
|
<QRCodeModal ref={qrcodeRef} content={conf?.trim() || 'null'} />
|
||||||
<div className={'w-full grid grid-cols-12 items-center gap-x-2'}>
|
<div className={'w-full flex flex-row items-center gap-x-2'}>
|
||||||
<div className={'col-span-12 md:col-span-4'}>
|
<div className={'w-12 aspect-square flex items-center justify-center mr-4 rounded-full bg-gray-200'}>
|
||||||
<span className={'inline-block font-medium'}> {props.name} </span>
|
{/* User Icon */}
|
||||||
|
<i className={'fas fa-user text-gray-400 text-lg'} />
|
||||||
</div>
|
</div>
|
||||||
<div className={'col-span-12 md:col-span-4'}>
|
<div className={'col-span-12 md:col-span-4'}>
|
||||||
<span className={'font-mono text-gray-400 text-sm'}> {props.allowedIps} </span>
|
<div className={'col-span-12 md:col-span-4'}>
|
||||||
|
<span className={'inline-block font-medium'}> {props.name} </span>
|
||||||
|
</div>
|
||||||
|
<div className={'col-span-12 md:col-span-4'}>
|
||||||
|
<span className={'font-mono text-gray-400 text-xs'}> {props.allowedIps} </span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={'flex items-center justify-center gap-x-3'}>
|
<div className={'flex items-center justify-center gap-x-3'}>
|
||||||
@ -310,7 +321,7 @@ function ClientBaseButton(props: {
|
|||||||
<div
|
<div
|
||||||
className={twMerge(
|
className={twMerge(
|
||||||
'group flex items-center justify-center w-10 aspect-square rounded-md',
|
'group flex items-center justify-center w-10 aspect-square rounded-md',
|
||||||
'bg-gray-200/80 hover:bg-gray-100',
|
'bg-gray-200/80 hover:bg-gray-100/50',
|
||||||
'border border-transparent hover:border-primary',
|
'border border-transparent hover:border-primary',
|
||||||
'transition-colors duration-200 ease-in-out',
|
'transition-colors duration-200 ease-in-out',
|
||||||
'cursor-pointer',
|
'cursor-pointer',
|
||||||
|
@ -50,7 +50,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
publicKey: peerKeys.publicKey,
|
publicKey: peerKeys.publicKey,
|
||||||
privateKey: peerKeys.privateKey,
|
privateKey: peerKeys.privateKey,
|
||||||
preSharedKey: peerKeys.preSharedKey,
|
preSharedKey: peerKeys.preSharedKey,
|
||||||
persistentKeepalive: 25,
|
persistentKeepalive: 0,
|
||||||
})
|
})
|
||||||
if (!addedPeer) {
|
if (!addedPeer) {
|
||||||
return res
|
return res
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||||
import safeServe from "@lib/safe-serve";
|
import safeServe from "@lib/safe-serve";
|
||||||
import { getServers } from "@lib/wireguard";
|
import { getServers, WGServer } from "@lib/wireguard";
|
||||||
import { getServerConf } from "@lib/wireguard-utils";
|
import { getServerConf } from "@lib/wireguard-utils";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
@ -17,10 +17,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
|
|
||||||
const servers = await getServers()
|
const servers = await getServers()
|
||||||
|
|
||||||
servers.forEach((s) => {
|
for (const s of servers) {
|
||||||
const CONFIG_PATH = path.join(WG_PATH, `wg${s.confId}.conf`)
|
const CONFIG_PATH = path.join(WG_PATH, `wg${s.confId}.conf`)
|
||||||
fs.writeFileSync(CONFIG_PATH, getServerConf(s), { mode: 0o600 })
|
fs.writeFileSync(CONFIG_PATH, getServerConf(s), { mode: 0o600 })
|
||||||
})
|
await WGServer.start(s.id)
|
||||||
|
}
|
||||||
|
|
||||||
return res
|
return res
|
||||||
.status(200)
|
.status(200)
|
||||||
|
@ -24,7 +24,7 @@ const CreateServerModal = React.forwardRef<
|
|||||||
const innerRef = React.useRef<SmartModalRef | null>(null)
|
const innerRef = React.useRef<SmartModalRef | null>(null)
|
||||||
const [ form ] = Form.useForm()
|
const [ form ] = Form.useForm()
|
||||||
|
|
||||||
const [ type, setType ] = React.useState<'default' | 'tor'>('default')
|
const [ type, setType ] = React.useState<ServerType>('direct')
|
||||||
|
|
||||||
React.useImperativeHandle(ref, () => innerRef.current as SmartModalRef)
|
React.useImperativeHandle(ref, () => innerRef.current as SmartModalRef)
|
||||||
|
|
||||||
@ -206,4 +206,6 @@ const FormSchema = z.object({
|
|||||||
mtu: MtuSchema
|
mtu: MtuSchema
|
||||||
})
|
})
|
||||||
|
|
||||||
|
type ServerType = z.infer<typeof TypeSchema>
|
||||||
|
|
||||||
type FormValues = z.infer<typeof FormSchema>
|
type FormValues = z.infer<typeof FormSchema>
|
||||||
|
Loading…
Reference in New Issue
Block a user