private static function getRoutes(PoolConfig $poolConfig) { $routeConfig = []; if ($poolConfig->v('defaultGateway')) { $routeConfig[] = 'push "redirect-gateway def1 bypass-dhcp"'; // for Windows clients we need this extra route to mark the TAP adapter as // trusted and as having "Internet" access to allow the user to set it to // "Home" or "Work" to allow accessing file shares and printers // NOTE: this will break OS X tunnelblick because on disconnect it will // remove all default routes, including the one set before the VPN // was brought up //$routeConfig[] = 'push "route 0.0.0.0 0.0.0.0"'; // for iOS we need this OpenVPN 2.4 "ipv6" flag to redirect-gateway // See https://docs.openvpn.net/docs/openvpn-connect/openvpn-connect-ios-faq.html $routeConfig[] = 'push "redirect-gateway ipv6"'; // we use 2000::/3 instead of ::/0 because it seems to break on native IPv6 // networks where the ::/0 default route already exists $routeConfig[] = 'push "route-ipv6 2000::/3"'; } else { // there may be some routes specified, push those, and not the default foreach ($poolConfig->v('routes') as $route) { $routeIp = new IP($route); if (6 === $routeIp->getFamily()) { // IPv6 $routeConfig[] = sprintf('push "route-ipv6 %s"', $routeIp->getAddressPrefix()); } else { // IPv4 $routeConfig[] = sprintf('push "route %s %s"', $routeIp->getAddress(), $routeIp->getNetmask()); } } } return $routeConfig; }
private static function getForwardChain(InstanceConfig $instanceConfig, $inetFamily) { $forwardChain = []; foreach (array_keys($instanceConfig->v('vpnPools')) as $poolNumber => $poolId) { $poolConfig = new PoolConfig($instanceConfig->v('vpnPools', $poolId)); if (6 === $inetFamily && !$poolConfig->v('forward6')) { // IPv6 forwarding was disabled continue; } if (4 === $inetFamily) { // get the IPv4 range $srcNet = $poolConfig->v('range'); } else { // get the IPv6 range $srcNet = $poolConfig->v('range6'); } $forwardChain[] = sprintf('-N vpn-%s-%s', $instanceConfig->v('instanceNumber'), $poolNumber); $forwardChain[] = sprintf('-A FORWARD -i tun-%s-%s+ -s %s -j vpn-%s-%s', $instanceConfig->v('instanceNumber'), $poolNumber, $srcNet, $instanceConfig->v('instanceNumber'), $poolNumber); // merge outgoing forwarding firewall rules to prevent certain // traffic $forwardChain = array_merge($forwardChain, self::getForwardFirewall($instanceConfig->v('instanceNumber'), $poolNumber, $poolConfig, $inetFamily)); if ($poolConfig->v('clientToClient')) { // allow client-to-client $forwardChain[] = sprintf('-A vpn-%s-%s -o tun-%s-%s+ -d %s -j ACCEPT', $instanceConfig->v('instanceNumber'), $poolNumber, $instanceConfig->v('instanceNumber'), $poolNumber, $srcNet); } if ($poolConfig->v('defaultGateway')) { // allow traffic to all outgoing destinations $forwardChain[] = sprintf('-A vpn-%s-%s -o %s -j ACCEPT', $instanceConfig->v('instanceNumber'), $poolNumber, $poolConfig->v('extIf'), $srcNet); } else { // only allow certain traffic to the external interface foreach ($poolConfig->v('routes') as $route) { $routeIp = new IP($route); if ($inetFamily === $routeIp->getFamily()) { $forwardChain[] = sprintf('-A vpn-%s-%s -o %s -d %s -j ACCEPT', $instanceConfig->v('instanceNumber'), $poolNumber, $poolConfig->v('extIf'), $route); } } } } return $forwardChain; }