/** * Disconnect all clients with this CN from all pools and instances * managed by this service. * * @param string $commonName the CN to kill */ public function kill($commonName) { $clientsKilled = 0; // loop over all pools foreach (array_keys($this->instanceConfig->v('vpnPools')) as $poolNumber => $poolId) { $poolConfig = new PoolConfig($this->instanceConfig->v('vpnPools', $poolId)); $managementIp = sprintf('127.42.%d.%d', 100 + $this->instanceConfig->v('instanceNumber'), 100 + $poolNumber); // loop over all processes for ($i = 0; $i < $poolConfig->v('processCount'); ++$i) { // add all kills from this instance to poolKills try { // open the socket connection $this->managementSocket->open(sprintf('tcp://%s:%d', $managementIp, 11940 + $i)); $response = $this->managementSocket->command(sprintf('kill %s', $commonName)); if (0 === mb_strpos($response[0], 'SUCCESS: ')) { ++$clientsKilled; } // close the socket connection $this->managementSocket->close(); } catch (ManagementSocketException $e) { // we log the error, but continue with the next instance $this->logger->error(sprintf('error with socket "%s:%s", message: "%s"', $managementIp, 11940 + $i, $e->getMessage())); } } } return 0 !== $clientsKilled; }
public function write($instanceId, InstanceConfig $instanceConfig) { $instanceNumber = $instanceConfig->v('instanceNumber'); foreach (array_keys($instanceConfig->v('vpnPools')) as $poolNumber => $poolId) { $poolConfig = new PoolConfig($instanceConfig->v('vpnPools', $poolId)); $this->writePool($instanceNumber, $instanceId, $poolNumber, $poolId, $poolConfig); } }
private function fetchGroups($bearerToken) { $httpClient = new Client(); try { return $httpClient->get($this->instanceConfig->v('groupProviders', 'VootProvider', 'apiUrl'), ['headers' => ['Authorization' => sprintf('Bearer %s', $bearerToken)]])->json(); } catch (TransferException $e) { return []; } }
public function init(Service $service) { $service->get('/server_pools', function (Request $request, array $hookData) { Utils::requireUser($hookData, ['vpn-admin-portal', 'vpn-user-portal']); $responseData = []; foreach (array_keys($this->instanceConfig->v('vpnPools')) as $poolId) { $poolConfig = new PoolConfig($this->instanceConfig->v('vpnPools', $poolId)); $responseData[$poolId] = $poolConfig->v(); } return new ApiResponse('server_pools', $responseData); }); $service->get('/server_pool', function (Request $request, array $hookData) { Utils::requireUser($hookData, ['vpn-admin-portal', 'vpn-user-portal']); $poolId = $request->getQueryParameter('pool_id'); InputValidation::poolId($poolId); $poolConfig = new PoolConfig($this->instanceConfig->v('vpnPools', $poolId)); return new ApiResponse('server_pool', $poolConfig->v()); }); }
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; }
* * IPv6: * The IPv6 address is generated according to RFC 4193 (Global ID), it results * in a /60 network. */ try { $p = new CliParser('Automatically generate an IP address and basic config for a pool', ['instance' => ['the instance to target, e.g. vpn.example', true, true], 'pool' => ['the pool to target, e.g. internet', true, true], 'host' => ['the hostname clients connect to', true, true], 'ext' => ['the external interface, e.g. eth0', true, true]]); $opt = $p->parse($argv); if ($opt->e('help')) { echo $p->help(); exit(0); } $v4 = sprintf('10.%s.%s.0/24', hexdec(bin2hex(random_bytes(1))), hexdec(bin2hex(random_bytes(1)))); $v6 = sprintf('fd%s:%s:%s:%s::/60', bin2hex(random_bytes(1)), bin2hex(random_bytes(2)), bin2hex(random_bytes(2)), bin2hex(random_bytes(2) & hex2bin('fff0'))); echo sprintf('IPv4 CIDR : %s', $v4) . PHP_EOL; echo sprintf('IPv6 prefix: %s', $v6) . PHP_EOL; $configFile = sprintf('%s/config/%s/config.yaml', dirname(__DIR__), $opt->v('instance')); $instanceConfig = InstanceConfig::fromFile($configFile); $poolConfig = new PoolConfig($instanceConfig->v('vpnPools', $opt->v('pool'))); $instanceConfigData = $instanceConfig->v(); $poolConfigData = $poolConfig->v(); $poolConfigData['range'] = $v4; $poolConfigData['range6'] = $v6; $poolConfigData['hostName'] = $opt->v('host'); $poolConfigData['extIf'] = $opt->v('ext'); $instanceConfigData['vpnPools'][$opt->v('pool')] = $poolConfigData; InstanceConfig::toFile($configFile, $instanceConfigData); } catch (Exception $e) { echo sprintf('ERROR: %s', $e->getMessage()) . PHP_EOL; exit(1); }
* License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ require_once sprintf('%s/vendor/autoload.php', dirname(__DIR__)); use SURFnet\VPN\Server\InstanceConfig; use SURFnet\VPN\Common\Logger; use SURFnet\VPN\Server\OpenVpn\ServerManager; use SURFnet\VPN\Server\OpenVpn\ManagementSocket; use SURFnet\VPN\Common\CliParser; try { $p = new CliParser('Get the connection status of an instance', ['instance' => ['the instance', true, true]]); $opt = $p->parse($argv); if ($opt->e('help')) { echo $p->help(); exit(0); } $configFile = sprintf('%s/config/%s/config.yaml', dirname(__DIR__), $opt->v('instance')); $config = InstanceConfig::fromFile($configFile); $serverManager = new ServerManager($config, new ManagementSocket(), new Logger($argv[0])); var_dump($serverManager->connections()); } catch (Exception $e) { echo sprintf('ERROR: %s', $e->getMessage()) . PHP_EOL; exit(1); }
use SURFnet\VPN\Server\InstanceConfig; use SURFnet\VPN\Common\FileIO; use SURFnet\VPN\Common\CliParser; try { $p = new CliParser('Generate firewall rules for all instances', ['install' => ['install the firewall', false, false]]); $opt = $p->parse($argv); if ($opt->e('help')) { echo $p->help(); exit(0); } // detect all instances $configList = []; $configDir = sprintf('%s/config', dirname(__DIR__)); foreach (glob(sprintf('%s/*', $configDir), GLOB_ONLYDIR | GLOB_ERR) as $instanceDir) { $instanceId = basename($instanceDir); $configList[$instanceId] = InstanceConfig::fromFile(sprintf('%s/%s/config.yaml', $configDir, $instanceId)); } $firewall = Firewall::getFirewall4($configList); $firewall6 = Firewall::getFirewall6($configList); if ($opt->e('install')) { FileIO::writeFile('/etc/sysconfig/iptables', $firewall, 0600); FileIO::writeFile('/etc/sysconfig/ip6tables', $firewall6, 0600); } else { echo '##########################################' . PHP_EOL; echo '# IPv4' . PHP_EOL; echo '##########################################' . PHP_EOL; echo $firewall; echo '##########################################' . PHP_EOL; echo '# IPv6' . PHP_EOL; echo '##########################################' . PHP_EOL; echo $firewall6;
use SURFnet\VPN\Server\Api\OpenVpnModule; use SURFnet\VPN\Common\Http\Service; use SURFnet\VPN\Server\Api\Users; use SURFnet\VPN\Server\Api\UsersModule; use SURFnet\VPN\Server\InstanceConfig; use SURFnet\VPN\Common\Logger; use SURFnet\VPN\Server\OpenVpn\ManagementSocket; use SURFnet\VPN\Server\OpenVpn\ServerManager; $logger = new Logger('vpn-server-api'); try { // this is provided by Apache, using CanonicalName $request = new Request($_SERVER, $_GET, $_POST); $instanceId = $request->getServerName(); $dataDir = sprintf('%s/data/%s', dirname(__DIR__), $instanceId); $configDir = sprintf('%s/config/%s', dirname(__DIR__), $instanceId); $config = InstanceConfig::fromFile(sprintf('%s/config.yaml', $configDir)); $service = new Service(); $basicAuthentication = new BasicAuthenticationHook($config->v('apiConsumers'), 'vpn-server-api'); $service->addBeforeHook('auth', $basicAuthentication); $service->addModule(new LogModule($dataDir)); $service->addModule(new OpenVpnModule(new ServerManager($config, new ManagementSocket(), $logger))); $service->addModule(new CommonNamesModule(new CommonNames(sprintf('%s/common_names', $dataDir)), $logger)); $service->addModule(new UsersModule(new Users(sprintf('%s/users', $dataDir)), $logger)); $groupProviders = []; if ($config->e('groupProviders')) { foreach (array_keys($config->v('groupProviders')) as $groupProviderId) { $groupProviderClass = sprintf('SURFnet\\VPN\\Server\\GroupProvider\\%s', $groupProviderId); $groupProviders[] = new $groupProviderClass($dataDir, $config); } } $service->addModule(new GroupsModule($groupProviders, $logger));