124 lines
3.7 KiB
TypeScript
124 lines
3.7 KiB
TypeScript
|
|
import type { IWgPeerConfig } from './smartvpn.interfaces.js';
|
||
|
|
|
||
|
|
// ============================================================================
|
||
|
|
// WireGuard .conf file generator
|
||
|
|
// ============================================================================
|
||
|
|
|
||
|
|
export interface IWgClientConfOptions {
|
||
|
|
/** Client private key (base64) */
|
||
|
|
privateKey: string;
|
||
|
|
/** Client TUN address with prefix (e.g. 10.8.0.2/24) */
|
||
|
|
address: string;
|
||
|
|
/** DNS servers */
|
||
|
|
dns?: string[];
|
||
|
|
/** TUN MTU */
|
||
|
|
mtu?: number;
|
||
|
|
/** Server peer config */
|
||
|
|
peer: {
|
||
|
|
publicKey: string;
|
||
|
|
presharedKey?: string;
|
||
|
|
endpoint: string;
|
||
|
|
allowedIps: string[];
|
||
|
|
persistentKeepalive?: number;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
export interface IWgServerConfOptions {
|
||
|
|
/** Server private key (base64) */
|
||
|
|
privateKey: string;
|
||
|
|
/** Server TUN address with prefix (e.g. 10.8.0.1/24) */
|
||
|
|
address: string;
|
||
|
|
/** UDP listen port */
|
||
|
|
listenPort: number;
|
||
|
|
/** DNS servers */
|
||
|
|
dns?: string[];
|
||
|
|
/** TUN MTU */
|
||
|
|
mtu?: number;
|
||
|
|
/** Enable NAT — adds PostUp/PostDown iptables rules */
|
||
|
|
enableNat?: boolean;
|
||
|
|
/** Network interface for NAT (e.g. eth0). Auto-detected if omitted. */
|
||
|
|
natInterface?: string;
|
||
|
|
/** Configured peers */
|
||
|
|
peers: IWgPeerConfig[];
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Generates standard WireGuard .conf files compatible with wg-quick,
|
||
|
|
* WireGuard iOS/Android apps, and other standard WireGuard clients.
|
||
|
|
*/
|
||
|
|
export class WgConfigGenerator {
|
||
|
|
/**
|
||
|
|
* Generate a client .conf file content.
|
||
|
|
*/
|
||
|
|
public static generateClientConfig(opts: IWgClientConfOptions): string {
|
||
|
|
const lines: string[] = [];
|
||
|
|
|
||
|
|
lines.push('[Interface]');
|
||
|
|
lines.push(`PrivateKey = ${opts.privateKey}`);
|
||
|
|
lines.push(`Address = ${opts.address}`);
|
||
|
|
if (opts.dns && opts.dns.length > 0) {
|
||
|
|
lines.push(`DNS = ${opts.dns.join(', ')}`);
|
||
|
|
}
|
||
|
|
if (opts.mtu) {
|
||
|
|
lines.push(`MTU = ${opts.mtu}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
lines.push('');
|
||
|
|
lines.push('[Peer]');
|
||
|
|
lines.push(`PublicKey = ${opts.peer.publicKey}`);
|
||
|
|
if (opts.peer.presharedKey) {
|
||
|
|
lines.push(`PresharedKey = ${opts.peer.presharedKey}`);
|
||
|
|
}
|
||
|
|
lines.push(`Endpoint = ${opts.peer.endpoint}`);
|
||
|
|
lines.push(`AllowedIPs = ${opts.peer.allowedIps.join(', ')}`);
|
||
|
|
if (opts.peer.persistentKeepalive) {
|
||
|
|
lines.push(`PersistentKeepalive = ${opts.peer.persistentKeepalive}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
lines.push('');
|
||
|
|
return lines.join('\n');
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Generate a server .conf file content.
|
||
|
|
*/
|
||
|
|
public static generateServerConfig(opts: IWgServerConfOptions): string {
|
||
|
|
const lines: string[] = [];
|
||
|
|
|
||
|
|
lines.push('[Interface]');
|
||
|
|
lines.push(`PrivateKey = ${opts.privateKey}`);
|
||
|
|
lines.push(`Address = ${opts.address}`);
|
||
|
|
lines.push(`ListenPort = ${opts.listenPort}`);
|
||
|
|
if (opts.dns && opts.dns.length > 0) {
|
||
|
|
lines.push(`DNS = ${opts.dns.join(', ')}`);
|
||
|
|
}
|
||
|
|
if (opts.mtu) {
|
||
|
|
lines.push(`MTU = ${opts.mtu}`);
|
||
|
|
}
|
||
|
|
if (opts.enableNat) {
|
||
|
|
const iface = opts.natInterface || 'eth0';
|
||
|
|
lines.push(`PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o ${iface} -j MASQUERADE`);
|
||
|
|
lines.push(`PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o ${iface} -j MASQUERADE`);
|
||
|
|
}
|
||
|
|
|
||
|
|
for (const peer of opts.peers) {
|
||
|
|
lines.push('');
|
||
|
|
lines.push('[Peer]');
|
||
|
|
lines.push(`PublicKey = ${peer.publicKey}`);
|
||
|
|
if (peer.presharedKey) {
|
||
|
|
lines.push(`PresharedKey = ${peer.presharedKey}`);
|
||
|
|
}
|
||
|
|
lines.push(`AllowedIPs = ${peer.allowedIps.join(', ')}`);
|
||
|
|
if (peer.endpoint) {
|
||
|
|
lines.push(`Endpoint = ${peer.endpoint}`);
|
||
|
|
}
|
||
|
|
if (peer.persistentKeepalive) {
|
||
|
|
lines.push(`PersistentKeepalive = ${peer.persistentKeepalive}`);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
lines.push('');
|
||
|
|
return lines.join('\n');
|
||
|
|
}
|
||
|
|
}
|