import { useState, useEffect } from 'react'; import { Plus, Trash2, Wifi, Shield, Activity, Settings } from 'lucide-react'; import { routingAPI } from '../services/api'; function Routing() { const [routingStatus, setRoutingStatus] = useState(null); const [isLoading, setIsLoading] = useState(true); const [activeTab, setActiveTab] = useState('overview'); // NAT management state const [natRules, setNatRules] = useState([]); const [natLoading, setNatLoading] = useState(false); const [natError, setNatError] = useState(null); const [showNatForm, setShowNatForm] = useState(false); const [newNat, setNewNat] = useState({ source_network: '', target_interface: '', masquerade: true, nat_type: 'MASQUERADE', protocol: 'ALL', external_port: '', internal_ip: '', internal_port: '' }); const [natSubmitting, setNatSubmitting] = useState(false); // Peer Routes management state const [peerRoutes, setPeerRoutes] = useState([]); const [peersLoading, setPeersLoading] = useState(false); const [peersError, setPeersError] = useState(null); const [showPeerForm, setShowPeerForm] = useState(false); const [newPeerRoute, setNewPeerRoute] = useState({ peer_name: '', peer_ip: '', allowed_networks: '', route_type: 'lan' }); const [peerSubmitting, setPeerSubmitting] = useState(false); // Firewall Rules management state const [firewallRules, setFirewallRules] = useState([]); const [fwLoading, setFwLoading] = useState(false); const [fwError, setFwError] = useState(null); const [showFwForm, setShowFwForm] = useState(false); const [newFwRule, setNewFwRule] = useState({ rule_type: 'INPUT', source: '', destination: '', action: 'ACCEPT', protocol: 'ALL', port_range: '' }); const [fwSubmitting, setFwSubmitting] = useState(false); // Network Configuration state const [networkStatus, setNetworkStatus] = useState(null); const [networkLoading, setNetworkLoading] = useState(false); const [networkError, setNetworkError] = useState(null); const [isSettingUp, setIsSettingUp] = useState(false); useEffect(() => { fetchRoutingStatus(); fetchNatRules(); fetchPeerRoutes(); fetchFirewallRules(); fetchNetworkStatus(); }, []); const fetchRoutingStatus = async () => { try { const response = await routingAPI.getStatus(); setRoutingStatus(response.data); } catch (error) { console.error('Failed to fetch routing status:', error); } finally { setIsLoading(false); } }; const fetchNatRules = async () => { setNatLoading(true); setNatError(null); try { const response = await routingAPI.getNatRules(); setNatRules(response.data.nat_rules || []); } catch (error) { setNatError('Failed to load NAT rules'); } finally { setNatLoading(false); } }; const fetchPeerRoutes = async () => { setPeersLoading(true); setPeersError(null); try { const response = await routingAPI.getPeerRoutes(); setPeerRoutes(response.data.peer_routes || []); } catch (error) { setPeersError('Failed to load peer routes'); } finally { setPeersLoading(false); } }; const fetchFirewallRules = async () => { setFwLoading(true); setFwError(null); try { const response = await routingAPI.getFirewallRules(); setFirewallRules(response.data.firewall_rules || []); } catch (error) { setFwError('Failed to load firewall rules'); } finally { setFwLoading(false); } }; const fetchNetworkStatus = async () => { setNetworkLoading(true); setNetworkError(null); try { const response = await fetch('http://localhost:3000/api/wireguard/network/status'); if (response.ok) { const data = await response.json(); setNetworkStatus(data); } else { throw new Error('Failed to fetch network status'); } } catch (error) { console.error('Failed to fetch network status:', error); setNetworkError('Failed to fetch network status'); } finally { setNetworkLoading(false); } }; const setupNetworkConfiguration = async () => { setIsSettingUp(true); setNetworkError(null); try { const response = await fetch('http://localhost:3000/api/wireguard/network/setup', { method: 'POST', headers: { 'Content-Type': 'application/json', }, }); if (response.ok) { const data = await response.json(); console.log('Network setup successful:', data); // Refresh network status await fetchNetworkStatus(); } else { const errorData = await response.json(); throw new Error(errorData.error || 'Failed to setup network configuration'); } } catch (error) { console.error('Failed to setup network configuration:', error); setNetworkError(error.message); } finally { setIsSettingUp(false); } }; const handleNatInputChange = (e) => { const { name, value, type, checked } = e.target; setNewNat((prev) => ({ ...prev, [name]: type === 'checkbox' ? checked : value, })); }; const handleAddNatRule = async (e) => { e.preventDefault(); setNatSubmitting(true); setNatError(null); try { await routingAPI.addNatRule(newNat); setShowNatForm(false); setNewNat({ source_network: '', target_interface: '', masquerade: true, nat_type: 'MASQUERADE', protocol: 'ALL', external_port: '', internal_ip: '', internal_port: '' }); fetchNatRules(); fetchRoutingStatus(); } catch (error) { setNatError('Failed to add NAT rule'); } finally { setNatSubmitting(false); } }; const handleDeleteNatRule = async (ruleId) => { if (!window.confirm('Delete this NAT rule?')) return; setNatLoading(true); setNatError(null); try { await routingAPI.deleteNatRule(ruleId); fetchNatRules(); fetchRoutingStatus(); } catch (error) { setNatError('Failed to delete NAT rule'); } finally { setNatLoading(false); } }; const handlePeerInputChange = (e) => { const { name, value } = e.target; setNewPeerRoute((prev) => ({ ...prev, [name]: value })); }; const handleAddPeerRoute = async (e) => { e.preventDefault(); setPeerSubmitting(true); setPeersError(null); try { // allowed_networks: comma-separated string to array const payload = { ...newPeerRoute, allowed_networks: newPeerRoute.allowed_networks.split(',').map((s) => s.trim()).filter(Boolean), }; await routingAPI.addPeerRoute(payload); setShowPeerForm(false); setNewPeerRoute({ peer_name: '', peer_ip: '', allowed_networks: '', route_type: 'lan' }); fetchPeerRoutes(); fetchRoutingStatus(); } catch (error) { setPeersError('Failed to add peer route'); } finally { setPeerSubmitting(false); } }; const handleDeletePeerRoute = async (peerName) => { if (!window.confirm('Delete this peer route?')) return; setPeersLoading(true); setPeersError(null); try { await routingAPI.deletePeerRoute(peerName); fetchPeerRoutes(); fetchRoutingStatus(); } catch (error) { setPeersError('Failed to delete peer route'); } finally { setPeersLoading(false); } }; const handleFwInputChange = (e) => { const { name, value } = e.target; setNewFwRule((prev) => ({ ...prev, [name]: value })); }; const handleAddFwRule = async (e) => { e.preventDefault(); setFwSubmitting(true); setFwError(null); try { const payload = { ...newFwRule }; if (!payload.port) delete payload.port; await routingAPI.addFirewallRule(payload); setShowFwForm(false); setNewFwRule({ rule_type: 'INPUT', source: '', destination: '', action: 'ACCEPT', protocol: 'ALL', port_range: '' }); fetchFirewallRules(); fetchRoutingStatus(); } catch (error) { setFwError('Failed to add firewall rule'); } finally { setFwSubmitting(false); } }; const handleDeleteFwRule = async (ruleId) => { if (!window.confirm('Delete this firewall rule?')) return; setFwLoading(true); setFwError(null); try { await routingAPI.deleteFirewallRule(ruleId); fetchFirewallRules(); fetchRoutingStatus(); } catch (error) { setFwError('Failed to delete firewall rule'); } finally { setFwLoading(false); } }; if (isLoading) { return (
); } const tabs = [ { id: 'overview', name: 'Overview', icon: Activity }, { id: 'network', name: 'Network Config', icon: Wifi }, { id: 'nat', name: 'NAT Rules', icon: Shield }, { id: 'peers', name: 'Peer Routes', icon: Wifi }, { id: 'firewall', name: 'Firewall', icon: Settings }, ]; return (

Routing & Gateway

Manage VPN gateway, NAT rules, and routing configuration

{/* Status Overview */} {routingStatus && (

NAT Rules

{routingStatus.nat_rules_count || 0}

Peer Routes

{routingStatus.peer_routes_count || 0}

Firewall Rules

{routingStatus.firewall_rules_count || 0}

Exit Nodes

{routingStatus.exit_nodes_count || 0}

)} {/* Tabs */}
{/* Tab Content */}
{activeTab === 'overview' && (

Routing Overview

{routingStatus?.routing_table && routingStatus.routing_table.length > 0 ? (
{routingStatus.routing_table.map((route, index) => (
{route.route}
{route.parsed?.via && `via ${route.parsed.via}`}
))}
) : (

No routing table entries available.

)}
)} {activeTab === 'network' && (

Network Configuration

{networkError && (

{networkError}

)} {networkLoading ? (
) : networkStatus ? (
{/* Network Status Cards */}

IP Forwarding

{networkStatus.ip_forwarding ? 'Enabled' : 'Disabled'}

WireGuard Interface

{networkStatus.interface_status ? 'Up' : 'Down'}

NAT Rules

{networkStatus.nat_rules ? 'Configured' : 'Missing'}

Forwarding Rules

{networkStatus.forwarding_rules ? 'Configured' : 'Missing'}

{/* Configuration Details */}

Configuration Details

Last Updated: {new Date(networkStatus.timestamp).toLocaleString()}
IP Forwarding: {networkStatus.ip_forwarding ? 'Enabled' : 'Disabled'}
WireGuard Interface: {networkStatus.interface_status ? 'Up (wg0)' : 'Down'}
NAT Translation: {networkStatus.nat_rules ? 'Active' : 'Not Configured'}
Traffic Forwarding: {networkStatus.forwarding_rules ? 'Allowed' : 'Blocked'}
{/* Quick Actions */}

Quick Actions

) : (

Failed to load network status

)}
)} {activeTab === 'nat' && (

NAT Rules

{showNatForm && (
Advanced: Use DNAT for port forwarding, specify protocol/ports as needed.
{natError &&

{natError}

}
)} {natLoading ? (
Loading NAT rules...
) : natError ? (
{natError}
) : natRules.length === 0 ? (
No NAT rules configured.
) : ( {natRules.map((rule, idx) => ( ))}
Source Network Target Interface Masquerade Type Protocol Ext Port Int IP Int Port
{rule.source_network} {rule.target_interface} {rule.masquerade ? 'Yes' : 'No'} {rule.nat_type || 'MASQUERADE'} {rule.protocol || 'ALL'} {rule.external_port || '-'} {rule.internal_ip || '-'} {rule.internal_port || '-'}
)}
)} {activeTab === 'peers' && (

Peer Routes

{showPeerForm && (
{peersError &&

{peersError}

}
)} {peersLoading ? (
Loading peer routes...
) : peersError ? (
{peersError}
) : peerRoutes.length === 0 ? (
No peer routes configured.
) : ( {peerRoutes.map((route, idx) => ( ))}
Peer Name Peer IP Allowed Networks Route Type
{route.peer_name} {route.peer_ip} {Array.isArray(route.allowed_networks) ? route.allowed_networks.join(', ') : route.allowed_networks} {route.route_type}
)}
)} {activeTab === 'firewall' && (

Firewall Rules

{showFwForm && (
Advanced: Specify protocol and port/range for granular matching.
{fwError &&

{fwError}

}
)} {fwLoading ? (
Loading firewall rules...
) : fwError ? (
{fwError}
) : firewallRules.length === 0 ? (
No firewall rules configured.
) : ( {firewallRules.map((rule, idx) => ( ))}
Rule Type Source Destination Protocol Port/Range Action
{rule.rule_type} {rule.source} {rule.destination} {rule.protocol || 'ALL'} {rule.port_range || '-'} {rule.action}
)}
)}
); } export default Routing;