--- a/src/usr/local/www/vpn_openvpn_csc.php +++ b/src/usr/local/www/vpn_openvpn_csc.php @@ -35,7 +35,15 @@ require_once("pkg-utils.inc"); global $openvpn_tls_server_modes; +global $openvpn_topologies; +global $openvpn_ping_action, $openvpn_default_keepalive_interval, $openvpn_default_keepalive_timeout; +// check if submitted form field is not empty +function empty_field($str) { + $has_text = !is_bool($str) && strlen($str) > 0; + return !$has_text; +} + init_config_arr(array('openvpn', 'openvpn-csc')); $a_csc = &$config['openvpn']['openvpn-csc']; init_config_arr(array('openvpn', 'openvpn-server')); @@ -64,7 +72,7 @@ exit; } - if (!$user_can_edit_advanced && !empty($a_csc[$id]['custom_options'])) { + if (!$user_can_edit_advanced && !empty_field($a_csc[$id]['custom_options'])) { $input_errors[] = gettext("This user does not have sufficient privileges to delete an instance with Advanced options set."); } else { $wc_msg = sprintf(gettext('Deleted OpenVPN client specific override %1$s %2$s'), $a_csc[$id]['common_name'], $a_csc[$id]['description']); @@ -86,17 +94,50 @@ $pconfig['tunnel_network'] = $a_csc[$id]['tunnel_network']; $pconfig['tunnel_networkv6'] = $a_csc[$id]['tunnel_networkv6']; + + $pconfig['push_reset'] = $a_csc[$id]['push_reset']; + $pconfig['topology_override'] = $a_csc[$id]['topology_override']; + $pconfig['topology'] = $a_csc[$id]['topology']; + $pconfig['remove_route'] = $a_csc[$id]['remove_route']; + $pconfig['remove_iroute'] = $a_csc[$id]['remove_iroute']; + $pconfig['remove_dnsdomain'] = $a_csc[$id]['remove_dnsdomain']; + $pconfig['remove_dnsservers'] = $a_csc[$id]['remove_dnsservers']; + $pconfig['remove_ntpservers'] = $a_csc[$id]['remove_ntpservers']; + $pconfig['remove_netbios_ntype'] = $a_csc[$id]['remove_netbios_ntype']; + $pconfig['remove_netbios_scope'] = $a_csc[$id]['remove_netbios_scope']; + $pconfig['remove_wins'] = $a_csc[$id]['remove_wins']; + + if ($pconfig['push_reset'] || + $pconfig['topology_override'] || + $pconfig['remove_route'] || + $pconfig['remove_iroute'] || + $pconfig['remove_dnsdomain'] || + $pconfig['remove_dnsservers'] || + $pconfig['remove_ntpservers'] || + $pconfig['remove_netbios_ntype'] || + $pconfig['remove_netbios_scope'] || + $pconfig['remove_wins']) { + $pconfig['server_overrides_enabled'] = true; + } + + $pconfig['gwredir'] = $a_csc[$id]['gwredir']; + $pconfig['gwredir6'] = $a_csc[$id]['gwredir6']; $pconfig['local_network'] = $a_csc[$id]['local_network']; $pconfig['local_networkv6'] = $a_csc[$id]['local_networkv6']; + $pconfig['gateway'] = $a_csc[$id]['gateway']; + //$pconfig['gateway6'] = $a_csc[$id]['gateway6']; + $pconfig['remote_network'] = $a_csc[$id]['remote_network']; $pconfig['remote_networkv6'] = $a_csc[$id]['remote_networkv6']; - $pconfig['gwredir'] = $a_csc[$id]['gwredir']; - $pconfig['push_reset'] = $a_csc[$id]['push_reset']; - $pconfig['remove_route'] = $a_csc[$id]['remove_route']; + $pconfig['ping_push'] = $a_csc[$id]['ping_push']; + $pconfig['ping_seconds'] = $a_csc[$id]['ping_seconds']; + $pconfig['ping_action_push'] = $a_csc[$id]['ping_action_push']; + $pconfig['ping_action'] = $a_csc[$id]['ping_action']; + $pconfig['ping_action_seconds'] = $a_csc[$id]['ping_action_seconds']; $pconfig['dns_domain'] = $a_csc[$id]['dns_domain']; - if ($pconfig['dns_domain']) { + if (!empty_field($pconfig['dns_domain'])) { $pconfig['dns_domain_enable'] = true; } @@ -105,18 +146,21 @@ $pconfig['dns_server3'] = $a_csc[$id]['dns_server3']; $pconfig['dns_server4'] = $a_csc[$id]['dns_server4']; - if ($pconfig['dns_server1'] || - $pconfig['dns_server2'] || - $pconfig['dns_server3'] || - $pconfig['dns_server4']) { + if (!empty_field($pconfig['dns_server1']) || + !empty_field($pconfig['dns_server2']) || + !empty_field($pconfig['dns_server3']) || + !empty_field($pconfig['dns_server4'])) { $pconfig['dns_server_enable'] = true; } + $pconfig['push_blockoutsidedns'] = $a_csc[$id]['push_blockoutsidedns']; + $pconfig['push_register_dns'] = $a_csc[$id]['push_register_dns']; + $pconfig['ntp_server1'] = $a_csc[$id]['ntp_server1']; $pconfig['ntp_server2'] = $a_csc[$id]['ntp_server2']; - if ($pconfig['ntp_server1'] || - $pconfig['ntp_server2']) { + if (!empty_field($pconfig['ntp_server1']) || + !empty_field($pconfig['ntp_server2'])) { $pconfig['ntp_server_enable'] = true; } @@ -127,13 +171,13 @@ $pconfig['wins_server1'] = $a_csc[$id]['wins_server1']; $pconfig['wins_server2'] = $a_csc[$id]['wins_server2']; - if ($pconfig['wins_server1'] || - $pconfig['wins_server2']) { + if (!empty_field($pconfig['wins_server1']) || + !empty_field($pconfig['wins_server2'])) { $pconfig['wins_server_enable'] = true; } $pconfig['nbdd_server1'] = $a_csc[$id]['nbdd_server1']; - if ($pconfig['nbdd_server1']) { + if (!empty_field($pconfig['nbdd_server1'])) { $pconfig['nbdd_server_enable'] = true; } } @@ -155,7 +199,8 @@ !$user_can_edit_advanced) { $input_errors[] = gettext("This user does not have sufficient privileges to edit Advanced options on this instance."); } - if (!$user_can_edit_advanced && !empty($a_csc[$id]['custom_options'])) { + if (!$user_can_edit_advanced && !empty_field($a_csc[$id]['custom_options'])) { + // restore custom options field to its original value $pconfig['custom_options'] = $a_csc[$id]['custom_options']; } @@ -171,22 +216,36 @@ } } - if (!empty($pconfig['tunnel_network']) && !openvpn_validate_tunnel_network($pconfig['tunnel_network'], 'ipv4')) { + if (!empty_field($pconfig['tunnel_network']) && !openvpn_validate_tunnel_network($pconfig['tunnel_network'], 'ipv4')) { $input_errors[] = gettext("The field 'IPv4 Tunnel Network' must contain a valid IPv4 subnet with CIDR mask or an alias with a single IPv4 subnet with CIDR mask."); } - if (!empty($pconfig['tunnel_networkv6']) && !openvpn_validate_tunnel_network($pconfig['tunnel_networkv6'], 'ipv6')) { + if (!empty_field($pconfig['tunnel_networkv6']) && !openvpn_validate_tunnel_network($pconfig['tunnel_networkv6'], 'ipv6')) { $input_errors[] = gettext("The field 'IPv6 Tunnel Network' must contain a valid IPv6 prefix or an alias with a single IPv6 prefix."); } - if ($result = openvpn_validate_cidr($pconfig['local_network'], 'IPv4 Local Network', true, "ipv4", true)) { + if ($pconfig['server_overrides_enabled'] && $pconfig['topology_override'] && !array_key_exists($pconfig['topology'], $openvpn_topologies)) { + $input_errors[] = gettext("The field 'Topology' contains an invalid selection"); + } + + if (!$pconfig['gwredir'] && ($result = openvpn_validate_cidr($pconfig['local_network'], 'IPv4 Local Network', true, "ipv4", true))) { $input_errors[] = $result; } - if ($result = openvpn_validate_cidr($pconfig['local_networkv6'], 'IPv6 Local Network', true, "ipv6", true)) { + if (!$pconfig['gwredir6'] && ($result = openvpn_validate_cidr($pconfig['local_networkv6'], 'IPv6 Local Network', true, "ipv6", true))) { $input_errors[] = $result; } + if (!empty_field($pconfig['gateway']) && !is_ipaddrv4($pconfig['gateway'])) { + $input_errors[] = gettext("A valid IPv4 address must be specified for the gateway."); + } + + /* + if (!empty_field($pconfig['gateway6']) && !is_ipaddrv6($pconfig['gateway6'])) { + $input_errors[] = gettext("A valid IPv6 address must be specified for the gateway."); + } + */ + if ($result = openvpn_validate_cidr($pconfig['remote_network'], 'IPv4 Remote Network', true, "ipv4", true)) { $input_errors[] = $result; } @@ -195,47 +254,57 @@ $input_errors[] = $result; } + if ($pconfig['ping_push'] && !is_numericint($pconfig['ping_seconds'])) { + $input_errors[] = gettext("The supplied Ping Seconds value is invalid."); + } + if ($pconfig['ping_action_push'] && !array_key_exists($pconfig['ping_action'], $openvpn_ping_action)) { + $input_errors[] = gettext("The field 'Ping Action' contains an invalid selection"); + } + if ($pconfig['ping_action_push'] && !is_numericint($pconfig['ping_action_seconds'])) { + $input_errors[] = gettext("The supplied Ping Restart or Exit Seconds value is invalid."); + } + if ($pconfig['dns_server_enable']) { - if (!empty($pconfig['dns_server1']) && !is_ipaddr(trim($pconfig['dns_server1']))) { + if (!empty_field($pconfig['dns_server1']) && !is_ipaddr(trim($pconfig['dns_server1']))) { $input_errors[] = gettext("The field 'DNS Server #1' must contain a valid IP address"); } - if (!empty($pconfig['dns_server2']) && !is_ipaddr(trim($pconfig['dns_server2']))) { + if (!empty_field($pconfig['dns_server2']) && !is_ipaddr(trim($pconfig['dns_server2']))) { $input_errors[] = gettext("The field 'DNS Server #2' must contain a valid IP address"); } - if (!empty($pconfig['dns_server3']) && !is_ipaddr(trim($pconfig['dns_server3']))) { + if (!empty_field($pconfig['dns_server3']) && !is_ipaddr(trim($pconfig['dns_server3']))) { $input_errors[] = gettext("The field 'DNS Server #3' must contain a valid IP address"); } - if (!empty($pconfig['dns_server4']) && !is_ipaddr(trim($pconfig['dns_server4']))) { + if (!empty_field($pconfig['dns_server4']) && !is_ipaddr(trim($pconfig['dns_server4']))) { $input_errors[] = gettext("The field 'DNS Server #4' must contain a valid IP address"); } } if ($pconfig['ntp_server_enable']) { - if (!empty($pconfig['ntp_server1']) && !is_ipaddr(trim($pconfig['ntp_server1']))) { + if (!empty_field($pconfig['ntp_server1']) && !is_ipaddr(trim($pconfig['ntp_server1']))) { $input_errors[] = gettext("The field 'NTP Server #1' must contain a valid IP address"); } - if (!empty($pconfig['ntp_server2']) && !is_ipaddr(trim($pconfig['ntp_server2']))) { + if (!empty_field($pconfig['ntp_server2']) && !is_ipaddr(trim($pconfig['ntp_server2']))) { $input_errors[] = gettext("The field 'NTP Server #2' must contain a valid IP address"); } - if (!empty($pconfig['ntp_server3']) && !is_ipaddr(trim($pconfig['ntp_server3']))) { + if (!empty_field($pconfig['ntp_server3']) && !is_ipaddr(trim($pconfig['ntp_server3']))) { $input_errors[] = gettext("The field 'NTP Server #3' must contain a valid IP address"); } - if (!empty($pconfig['ntp_server4']) && !is_ipaddr(trim($pconfig['ntp_server4']))) { + if (!empty_field($pconfig['ntp_server4']) && !is_ipaddr(trim($pconfig['ntp_server4']))) { $input_errors[] = gettext("The field 'NTP Server #4' must contain a valid IP address"); } } if ($pconfig['netbios_enable']) { if ($pconfig['wins_server_enable']) { - if (!empty($pconfig['wins_server1']) && !is_ipaddr(trim($pconfig['wins_server1']))) { + if (!empty_field($pconfig['wins_server1']) && !is_ipaddr(trim($pconfig['wins_server1']))) { $input_errors[] = gettext("The field 'WINS Server #1' must contain a valid IP address"); } - if (!empty($pconfig['wins_server2']) && !is_ipaddr(trim($pconfig['wins_server2']))) { + if (!empty_field($pconfig['wins_server2']) && !is_ipaddr(trim($pconfig['wins_server2']))) { $input_errors[] = gettext("The field 'WINS Server #2' must contain a valid IP address"); } } if ($pconfig['nbdd_server_enable']) { - if (!empty($pconfig['nbdd_server1']) && !is_ipaddr(trim($pconfig['nbdd_server1']))) { + if (!empty_field($pconfig['nbdd_server1']) && !is_ipaddr(trim($pconfig['nbdd_server1']))) { $input_errors[] = gettext("The field 'NetBIOS Data Distribution Server #1' must contain a valid IP address"); } } @@ -269,14 +338,52 @@ foreach (array('', 'v6') as $ntype) { $csc["tunnel_network{$ntype}"] = openvpn_tunnel_network_fix($pconfig["tunnel_network{$ntype}"]); } + + if ($pconfig['server_overrides_enabled']) { + $csc['push_reset'] = $pconfig['push_reset']; + if (!$pconfig['push_reset']) { + $csc['remove_route'] = $pconfig['remove_route']; + $csc['remove_iroute'] = $pconfig['remove_iroute']; + $csc['remove_dnsdomain'] = $pconfig['remove_dnsdomain']; + $csc['remove_dnsservers'] = $pconfig['remove_dnsservers']; + $csc['remove_ntpservers'] = $pconfig['remove_ntpservers']; + $csc['remove_netbios_ntype'] = $pconfig['remove_netbios_ntype']; + $csc['remove_netbios_scope'] = $pconfig['remove_netbios_scope']; + $csc['remove_wins'] = $pconfig['remove_wins']; + } + + $csc['topology_override'] = $pconfig['topology_override']; + if ($pconfig['topology_override']) { + $csc['topology'] = $pconfig['topology']; + } + } + + $csc['gwredir'] = $pconfig['gwredir']; + if (!$pconfig['gwredir']) { $csc['local_network'] = $pconfig['local_network']; + } + + $csc['gwredir6'] = $pconfig['gwredir6']; + if (!$pconfig['gwredir6']) { $csc['local_networkv6'] = $pconfig['local_networkv6']; + } + + $csc['gateway'] = $pconfig['gateway']; + //$csc['gateway6'] = $pconfig['gateway6']; + $csc['remote_network'] = $pconfig['remote_network']; $csc['remote_networkv6'] = $pconfig['remote_networkv6']; - $csc['gwredir'] = $pconfig['gwredir']; - $csc['push_reset'] = $pconfig['push_reset']; - $csc['remove_route'] = $pconfig['remove_route']; + $csc['ping_push'] = $pconfig['ping_push']; + if ($pconfig['ping_push']) { + $csc['ping_seconds'] = $pconfig['ping_seconds']; + } + $csc['ping_action_push'] = $pconfig['ping_action_push']; + if ($pconfig['ping_action_push']) { + $csc['ping_action'] = $pconfig['ping_action']; + $csc['ping_action_seconds'] = $pconfig['ping_action_seconds']; + } + if ($pconfig['dns_domain_enable']) { $csc['dns_domain'] = $pconfig['dns_domain']; } @@ -288,6 +395,9 @@ $csc['dns_server4'] = $pconfig['dns_server4']; } + $csc['push_blockoutsidedns'] = $pconfig['push_blockoutsidedns']; + $csc['push_register_dns'] = $pconfig['push_register_dns']; + if ($pconfig['ntp_server_enable']) { $csc['ntp_server1'] = $pconfig['ntp_server1']; $csc['ntp_server2'] = $pconfig['ntp_server2']; @@ -323,7 +433,7 @@ $wc_msg = sprintf(gettext('Added OpenVPN client specific override %1$s %2$s'), $csc['common_name'], $csc['description']); } - if (!empty($old_csc['common_name'])) { + if (!empty_field($old_csc['common_name'])) { openvpn_delete_csc($old_csc); } openvpn_resync_csc($csc); @@ -406,6 +516,124 @@ true ))->setHelp('Select the servers that will utilize this override. When no servers are selected, the override will apply to all servers.'); + // Override server client options + $section->addInput(new Form_Checkbox( + 'server_overrides_enabled', + 'Select Server Overrides', + 'Select server options to remove.', + $pconfig['server_overrides_enabled'] + ))->setHelp('If unchecked, any client options specified in below form or Advanced section will be pushed to the client after the server options.%1$s' . + 'If checked, you can select the server options you want to remove. Any specified client option in below form or Advanced section will thus override the corresponding server-defined options.', + '
'); + + $section->addInput(new Form_Checkbox( + 'push_reset', + null, + 'Remove All Server Options', + $pconfig['push_reset'] + ))->setHelp('Prevent this client from receiving any server-defined client settings.%1$s' . + 'This option will send a push-reset to the client. It will thus remove any server-defined routes, the gateway and topology.%1$s' . + 'For the client to properly connect, you will need to enter at least the gateway and topology in the below form or in Advanced section.', + '
'); + + $section->addInput(new Form_Checkbox( + 'topology_override', + null, + 'Override Server Topology', + $pconfig['topology_override'] + )); + + $section->addInput(new Form_Select( + 'topology', + null, + $pconfig['topology'], + $openvpn_topologies + ))->setHelp('This will push the selected topology to the client. It should only be set when option "Remove All Server Options" is checked. It must match the actual topology specified in server.%1$s' . + 'NOTE: This will perform a "push topology [selection]" without a previous "push-remove topology". Alternetively you can push the topology in Advanced section.', + '
'); + + /* as "push-reset" can break subnet topology, + * "push-remove route" removes only IPv4/IPv6 routes, see #9702 */ + $section->addInput(new Form_Checkbox( + 'remove_route', + null, + 'Remove Server Local Routes', + $pconfig['remove_route'] + ))->setHelp('Prevent this client from receiving any server-defined local routes.%1$s' . + 'This option will send a "push-remove route" to the client, removing any server-defined ipv4 or ipv6 local routes, including the gateway.%1$s' . + 'NOTE: Remember to either enter the proper gateway and any additional local routes in the below form or in Advanced section.', + '
'); + + $section->addInput(new Form_Checkbox( + 'remove_iroute', + null, + 'Remove Server Remote Routes', + $pconfig['remove_iroute'] + ))->setHelp('Prevent this client from receiving any server-defined remote routes.%1$s' . + 'This option will send a "push-remove iroute" to the client, removing any server-defined ipv4 or ipv6 remote routes%1$s' . + 'NOTE: You can set new client specific remote routes in below form or in Advanced section.', + '
'); + + $section->addInput(new Form_Checkbox( + 'remove_dnsdomain', + null, + 'Remove Server DNS Domains', + $pconfig['remove_dnsdomain'] + ))->setHelp('Prevent this client from receiving any server-defined remote DNS domains.%1$s' . + 'This option will send a "push-remove dhcp-option DOMAIN" to the client, removing any server-defined DNS domains.%1$s' . + 'NOTE: You can set new client specific DNS domain in below form or in Advanced section.', + '
'); + + $section->addInput(new Form_Checkbox( + 'remove_dnsservers', + null, + 'Remove Server DNS Servers', + $pconfig['remove_dnsservers'] + ))->setHelp('Prevent this client from receiving any server-defined DNS Servers.%1$s' . + 'This option will send a "push-remove dhcp-option DNS" to the client, removing any server-defined ipv4 or ipv6 DNS servers.%1$s' . + 'NOTE: You can set new client specific DNS servers in below form or in Advanced section.', + '
'); + + $section->addInput(new Form_Checkbox( + 'remove_ntpservers', + null, + 'Remove Server NTP Options.', + $pconfig['remove_ntpservers'] + ))->setHelp('Prevent this client from receiving any server-defined NTP Servers.%1$s' . + 'This option will send a "push-remove dhcp-option NTP" to the client, removing any server-defined NTP servers.%1$s' . + 'NOTE: You can set new client specific NTP servers in below form or in Advanced section.', + '
'); + + $section->addInput(new Form_Checkbox( + 'remove_netbios_ntype', + null, + 'Remove Server Netbios Type', + $pconfig['remove_netbios_ntype'] + ))->setHelp('Prevent this client from receiving any server-defined Netbios Node Type.%1$s' . + 'This option will send a "push-remove dhcp-option NBT" to the client, removing any server-defined Netbios Node Type.%1$s' . + 'NOTE: You can set new client specific Netbios options in below form or in Advanced section.', + '
'); + + $section->addInput(new Form_Checkbox( + 'remove_netbios_scope', + null, + 'Remove Server Netbios Scope', + $pconfig['remove_netbios_scope'] + ))->setHelp('Prevent this client from receiving any server-defined Netbios Scope.%1$s' . + 'This option will send a "push-remove dhcp-option NBS" to the client, removing any server-defined Netbios Scope.%1$s' . + 'NOTE: You can set new client specific Netbios Scope in below form or in Advanced section.', + '
'); + + $section->addInput(new Form_Checkbox( + 'remove_wins', + null, + 'Remove Server WINS Options', + $pconfig['remove_wins'] + ))->setHelp('Prevent this client from receiving any server-defined WINS servers.%1$s' . + 'This option will send a "push-remove dhcp-option WINS" to the client, removing any server-defined WINS servers.%1$s' . + 'NOTE: You can set new client specific WINS servers in below form or in Advanced section.', + '
'); + $form->add($section); $section = new Form_Section('Tunnel Settings'); @@ -429,6 +657,24 @@ 'Enter the client IPv6 address and prefix. The prefix must match the IPv6 Tunnel Network prefix on the server. ', '
'); + $form->add($section); + + $section = new Form_Section('Local Routes Settings'); + + $section->addInput(new Form_Checkbox( + 'gwredir', + 'Redirect IPv4 Gateway', + 'Force all client generated traffic through the tunnel.', + $pconfig['gwredir'] + )); + + $section->addInput(new Form_Checkbox( + 'gwredir6', + 'Redirect IPv6 Gateway', + 'Force all client-generated IPv6 traffic through the tunnel.', + $pconfig['gwredir6'] + )); + $section->addInput(new Form_Input( 'local_network', 'IPv4 Local Network/s', @@ -448,6 +694,34 @@ '
'); $section->addInput(new Form_Input( + 'gateway', + 'IPv4 Gateway', + 'text', + $pconfig['gateway'] + ))->setHelp('This is the IPv4 Gateway to push to the client. Normally it is left blank and configured on the server. ' . + 'The gateway IP should be entered if any of the options "Remove Server Local Routes" or "Remove All Server Options" is checked, ' . + 'as these 2 options will remove the gateway defined on the server and connection from the client will likely fail.%1$s' . + 'NOTE: Remember that, unless configured specifically, the gateway should match the IPv4 Tunnel gateway configured on the selected OpenVPN servers settings.', + '
'); + + /* + $section->addInput(new Form_Input( + 'gateway6', + 'IPv6 Gateway', + 'text', + $pconfig['gateway6'] + ))->setHelp('This is the IPv6 Gateway to push to the client. Normally it is left blank and configured on the server. ' . + 'The gateway IP should be entered if any of the options "Remove Server Local Routes" or "Remove All Server Options" is checked, ' . + 'as these 2 options will remove the gateway defined on the server and connection from the client will likely fail.%1$s' . + 'NOTE: Remember that, unless configured specifically, the gateway should match the IPv4 Tunnel gateway configured on the selected OpenVPN servers settings.', + '
'); + */ + + $form->add($section); + + $section = new Form_Section('Remote Routes Settings'); + + $section->addInput(new Form_Input( 'remote_network', 'IPv4 Remote Network/s', 'text', @@ -467,31 +741,51 @@ 'NOTE: Remember to add these subnets to the IPv6 Remote Networks list on the corresponding OpenVPN server settings.', '
'); - $section->addInput(new Form_Checkbox( - 'gwredir', - 'Redirect Gateway', - 'Force all client generated traffic through the tunnel.', - $pconfig['gwredir'] - )); - $form->add($section); - $section = new Form_Section('Client Settings'); + $section = new Form_Section('Other Client Settings'); $section->addInput(new Form_Checkbox( - 'push_reset', - 'Server Definitions', - 'Prevent this client from receiving any server-defined client settings. ', - $pconfig['push_reset'] - )); + 'ping_push', + 'Ping Interval', + 'Push ping to VPN client', + $pconfig['ping_push'] + ))->setHelp('Override server ping interval.%1$s', + '
'); - /* as "push-reset" can break subnet topology, - * "push-remove route" removes only IPv4/IPv6 routes, see #9702 */ + $section->addInput(new Form_Input( + 'ping_seconds', + 'Ping Seconds', + 'number', + $pconfig['ping_seconds'] ?: $openvpn_default_keepalive_interval, + ['min' => '0'] + ))->setHelp('Ping remote over the TCP/UDP control channel if no ' . + 'packets have been sent for at least n seconds.%1$s', + '
'); + $section->addInput(new Form_Checkbox( - 'remove_route', - 'Remove Server Routes', - 'Prevent this client from receiving any server-defined routes without removing any other options. ', - $pconfig['remove_route'] + 'ping_action_push', + 'Ping Action', + 'Push ping-restart/ping-exit to VPN client', + $pconfig['ping_action_push'] + ))->setHelp('Override server ping restart/exit.%1$s', + '
'); + + $section->addInput(new Form_Select( + 'ping_action', + 'Ping restart or exit', + $pconfig['ping_action'], + $openvpn_ping_action + ))->setHelp('Exit or restart OpenVPN after timeout from remote.%1$s', + '
'); + + $section->addInput(new Form_Input( + 'ping_action_seconds', + 'Ping restart or exit seconds', + 'number', + $pconfig['ping_action_seconds'] + ?: $openvpn_default_keepalive_timeout, + ['min' => '0'] )); $section->addInput(new Form_Checkbox( @@ -499,7 +793,7 @@ 'DNS Default Domain', 'Provide a default domain name to clients', $pconfig['dns_domain_enable'] - ))->toggles('.dnsdomain'); + )); $group = new Form_Group('DNS Domain'); $group->addClass('dnsdomain'); @@ -519,7 +813,7 @@ 'DNS Servers', 'Provide a DNS server list to clients', $pconfig['dns_server_enable'] - ))->toggles('.dnsservers'); + )); $group = new Form_Group(null); $group->addClass('dnsservers'); @@ -554,13 +848,27 @@ $section->add($group); + $section->addInput(new Form_Checkbox( + 'push_blockoutsidedns', + 'Block Outside DNS', + 'Make Windows 10 Clients Block access to DNS servers except across OpenVPN while connected, forcing clients to use only VPN DNS servers.', + $pconfig['push_blockoutsidedns'] + ))->setHelp('Requires Windows 10 and OpenVPN 2.3.9 or later. Only Windows 10 is prone to DNS leakage in this way, other clients will ignore the option as they are not affected.'); + + $section->addInput(new Form_Checkbox( + 'push_register_dns', + 'Force DNS cache update', + 'Run "net stop dnscache", "net start dnscache", "ipconfig /flushdns" and "ipconfig /registerdns" on connection initiation.', + $pconfig['push_register_dns'] + ))->setHelp('This is known to kick Windows into recognizing pushed DNS servers.'); + // NTP servers $section->addInput(new Form_Checkbox( 'ntp_server_enable', 'NTP Servers', 'Provide an NTP server list to clients', $pconfig['ntp_server_enable'] - ))->toggles('.ntpservers'); + )); $group = new Form_Group(null); $group->addClass('ntpservers'); @@ -581,7 +889,7 @@ $section->add($group); - // NTP servers - For this section we need to use Javascript hiding since there + // Netbios - For this section we need to use Javascript hiding since there // are nested toggles $section->addInput(new Form_Checkbox( 'netbios_enable', @@ -641,7 +949,8 @@ if (!$user_can_edit_advanced) { $custops->setDisabled(); } - $section->addInput($custops)->setHelp('Enter any additional options to add for this client specific override, separated by a semicolon. %1$s' . + $section->addInput($custops)->setHelp('Enter any additional options to add for this client specific override, separated by a semicolon.%1$s' . + 'The options will be pushed to the client after all above custom options.%1$s' . 'EXAMPLE: push "route 10.0.0.0 255.255.255.0"; ', '
'); @@ -670,7 +979,106 @@ --- a/src/etc/inc/openvpn.inc +++ b/src/etc/inc/openvpn.inc @@ -772,11 +772,11 @@ if ($settings['netbios_enable']) { - if (!empty($settings['dhcp_nbttype']) && ($settings['dhcp_nbttype'] != 0)) { - $conf .= "push \"dhcp-option NBT {$settings['dhcp_nbttype']}\"\n"; + if (!empty($settings['netbios_ntype']) && ($settings['netbios_ntype'] != 0)) { + $conf .= "push \"dhcp-option NBT {$settings['netbios_ntype']}\"\n"; } - if (!empty($settings['dhcp_nbtscope'])) { - $conf .= "push \"dhcp-option NBS {$settings['dhcp_nbtscope']}\"\n"; + if (!empty($settings['netbios_scope'])) { + $conf .= "push \"dhcp-option NBS {$settings['netbios_scope']}\"\n"; } if (!empty($settings['wins_server1'])) { @@ -1692,6 +1692,7 @@ services_unbound_configure(false); } +// set client specific overrides function openvpn_resync_csc(& $settings) { global $g, $config, $openvpn_tls_server_modes; if (isset($settings['disable'])) { @@ -1715,10 +1716,46 @@ $conf .= "push-reset\n"; } + if ($settings['push_reset']) { + $conf .= "push-reset\n"; + } + + if ($settings['topology_override']) { + $conf .= "push \"topology {$settings['topology']}\"\n"; + } + if ($settings['remove_route']) { $conf .= "push-remove route\n"; } + if ($settings['remove_iroute']) { + $conf .= "push-remove iroute\n"; + } + + if ($settings['remove_dnsdomain']) { + $conf .= "push-remove \"dhcp-option DOMAIN\"\n"; + } + + if ($settings['remove_dnsservers']) { + $conf .= "push-remove \"dhcp-option DNS\"\n"; + } + + if ($settings['remove_ntpservers']) { + $conf .= "push-remove \"dhcp-option NTP\"\n"; + } + + if ($settings['remove_netbios_ntype']) { + $conf .= "push-remove \"dhcp-option NBT\"\n"; + } + + if ($settings['remove_netbios_scope']) { + $conf .= "push-remove \"dhcp-option NBS\"\n"; + } + + if ($settings['remove_wins']) { + $conf .= "push-remove \"dhcp-option WINS\"\n"; + } + if ($settings['local_network']) { $conf .= openvpn_gen_routes($settings['local_network'], "ipv4", true); } @@ -1735,9 +1772,34 @@ $conf .= openvpn_gen_routes($settings['remote_networkv6'], "ipv6", false, true); } + // push the ipv4 gateway if specified + if (!empty($settings['gateway']) && is_ipaddrv4($settings['gateway'])) { + $conf .= "push \"route-gateway {$settings['gateway']}\"\n"; + } + + /* Currently route-ipv6-gateway is not supported by openvpn + if (!empty($settings['gateway']) && is_ipaddrv4($settings['gateway'])) { + $conf .= "push \"route-ipv6-gateway {$settings['gateway']}\"\n"; + } + */ + + // Ping override options + if ($settings['ping_push']) { + $conf .= "push \"ping {$settings['ping_seconds']}\"\n"; + } + + if ($settings['ping_action_push']) { + $action = str_replace("_", "-", $settings['ping_action']); + $conf .= "push \"{$action} " . + "{$settings['ping_action_seconds']}\"\n"; + } + + // create client specific dhcp options and gateway redirection openvpn_add_dhcpopts($settings, $conf); + // custom options are added after all client overrides, and before the tunnel options openvpn_add_custom($settings, $conf); + /* Loop through servers, find which ones can use this CSC */ if (is_array($config['openvpn']['openvpn-server'])) { foreach ($config['openvpn']['openvpn-server'] as $serversettings) {