fix: 透明代理状态检测 - 读取实际iptables规则而非仅数据库

This commit is contained in:
2026-06-15 14:32:57 +08:00
parent aef4a9f3e1
commit 4e18e92fcc
+48 -9
View File
@@ -472,12 +472,10 @@ const TransparentProxy = {
const list = settings.transparentProxy.interfaces || [];
if (list.includes(iface)) return { ok: true, message: 'Already enabled' };
// Add iptables rules for this interface
// Add iptables rules for this interface (PRIVATE_RANGES already includes 192.168.10.1)
const rules = [
`iptables -t nat -C PREROUTING -i ${iface} -d 192.168.10.1 -j RETURN 2>/dev/null || iptables -t nat -I PREROUTING 1 -i ${iface} -d 192.168.10.1 -j RETURN`,
...this.PRIVATE_RANGES.map(r => {
const checkR = r.replace('-A', '-C');
return `iptables -t nat -C PREROUTING -i ${iface} ${checkR} 2>/dev/null || iptables -t nat -I PREROUTING 1 -i ${iface} ${r}`;
return `iptables -t nat -C PREROUTING -i ${iface} ${r} 2>/dev/null || iptables -t nat -I PREROUTING 1 -i ${iface} ${r}`;
}),
`iptables -t nat -C PREROUTING -i ${iface} -p tcp -j REDIRECT --to-ports ${this.REDIR_PORT} 2>/dev/null || iptables -t nat -A PREROUTING -i ${iface} -p tcp -j REDIRECT --to-ports ${this.REDIR_PORT}`,
`iptables -t nat -C PREROUTING -i ${iface} -p udp --dport 53 -j REDIRECT --to-ports ${this.DNS_PORT} 2>/dev/null || iptables -t nat -A PREROUTING -i ${iface} -p udp --dport 53 -j REDIRECT --to-ports ${this.DNS_PORT}`,
@@ -543,13 +541,54 @@ const TransparentProxy = {
},
async getStatus() {
const interfaces = await this.getActiveInterfaces();
const rules = [];
// Check actual iptables rules to determine which interfaces have transparent proxy
const activeFromIptables = new Set();
try {
const output = await this._exec('iptables -t nat -L PREROUTING -n -v --line-numbers 2>/dev/null || echo ""');
rules.push(output);
const output = await this._exec('iptables -t nat -L PREROUTING -n 2>/dev/null || echo ""');
const lines = output.split('\n');
for (const line of lines) {
// Match lines like: REDIRECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp redir ports 7893
// preceded by interface match
const ifaceMatch = line.match(/iif\s+(\S+)/);
if (!ifaceMatch) {
// iptables -L format: look for interface in the "in" column
// Format: target prot opt in out source destination
const parts = line.trim().split(/\s+/);
if (parts.length >= 6 && parts[0] === 'REDIRECT' && parts[4] !== '*' && parts[4] !== 'lo') {
activeFromIptables.add(parts[4]);
}
// Also check RETURN rules for private ranges
if (parts.length >= 6 && parts[0] === 'RETURN' && parts[4] !== '*' && parts[4] !== 'lo') {
activeFromIptables.add(parts[4]);
}
}
}
// Also check nft format
const nftOutput = await this._exec('nft list chain ip nat PREROUTING 2>/dev/null || echo ""');
for (const line of nftOutput.split('\n')) {
const m = line.match(/iifname\s+"([^"]+)".*redirect/);
if (m && m[1] !== 'lo') activeFromIptables.add(m[1]);
const m2 = line.match(/iifname\s+"([^"]+)".*return/);
if (m2 && m2[1] !== 'lo') activeFromIptables.add(m2[1]);
}
} catch {}
return { interfaces, rules: rules.join('\n') };
// Sync database with actual iptables state
const settings = DB.settings;
const dbInterfaces = settings.transparentProxy.interfaces || [];
// If iptables shows rules but DB doesn't, sync DB
if (activeFromIptables.size > 0) {
for (const iface of activeFromIptables) {
if (!dbInterfaces.includes(iface)) {
dbInterfaces.push(iface);
}
}
settings.transparentProxy.interfaces = dbInterfaces;
DB.save();
}
return { interfaces: [...new Set([...dbInterfaces, ...activeFromIptables])] };
},
async restoreFromSettings() {