Netgate Discussion Forum
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search
    • Register
    • Login

    Restarting OpenVPN

    Scheduled Pinned Locked Moved OpenVPN
    29 Posts 5 Posters 19.8k Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C
      cyboc
      last edited by

      Brian,

      I am running the embedded version of pfSense. I just tried storing my custom script in /scripts. Then I rebooted. Low and behold, after rebooting, my script was still in /scripts. I expected that it would have been wiped out by a reboot but I was wrong. That's good. Now I can store my script there. It's not quite the same as storing it in the XML config file but at least I can keep all my scripts in one place.

      1 Reply Last reply Reply Quote 0
      • B
        Briantist
        last edited by

        Yeah the embedded version won't delete your files on you. You might have some trouble writing things if you don't mount the filesystem as RW first, but anyway that's not what I was worried about. I am doing something that will be used at multiple locations, and I just don't want to have backup additional files with the config that I would then have to put back in place in the event of a restore.

        From what I could tell there is no way to do multiple lines with echo in the bourne shell, so you would need to install bash (another dependency I don't want). It just happens that cron does have a way to send mult-line input (the % character) so that helped me out there.

        1 Reply Last reply Reply Quote 0
        • C
          cyboc
          last edited by

          /scripts already seems to be mounted writeable. I did not have to do a remount-rw. :)

          1 Reply Last reply Reply Quote 0
          • C
            cyboc
            last edited by

            Brian,

            I have revised the code a bit. For example, I now write some messages to the system log by calling the logger command. I ran this script once per hour last night using cron. It seems to work fine so far. Still requires more testing. For example, I will have to pull the plug on our primary internet connection to force the VPN client to switchover to the secondary IP (i.e. backup connection). Then I will have to verify that this script forces the connection back to the primary IP.

            Here's the current version of the script:

            #!/usr/local/bin/php -f
            require_once('config.inc');
            include('openvpn.inc');
            
            // Read in all of the OpenVPN client configs.
            global $config;
            if (!is_array($config['openvpn']['openvpn-client']))
            {
              return;
            }
            
            // Find client config for London VPN server
            $found_config = false;
            $name = "London";
            foreach ($config['openvpn']['openvpn-client'] as & $settings)
            {
              if (stripos($settings['description'], $name) !== false)
              {
                 $found_config = true;
                 break;
              }
            }
            
            // If client config not found, exit.
            if (!$found_config)
            {
              echo "Did not find client VPN config for \"$name\".\n";
              exit;
            }
            
            // Print the client config.
            echo "vpnid: {$settings['vpnid']}\n";
            echo "description: {$settings['description']}\n";
            echo "server_addr: {$settings['server_addr']}\n";   
            echo "custom_options: {$settings['custom_options']}\n";
            
            // Resolve the configured host name to an IP address.
            // This is the VPN server's primary IP.
            $ip = gethostbyname($settings['server_addr']);
            echo "VPN server primary IP: $ip\n";
            
            // Tokenize the custom_options to get the VPN 
            // server's secondary IP.
            $tok = strtok($settings['custom_options'], " \n\t;");
            while ($tok !== false) {
              if (strcasecmp($tok, 'remote') == 0)
              {
                $tok = strtok(" \n\t;");
                if ($tok !== false)
                {
                  $ip_secondary = gethostbyname($tok);
                  echo "VPN server secondary IP: $ip_secondary\n";    
                }
              }
              $tok = strtok(" \n\t;");
            }
            
            // Find the status for the VPN client.
            $found_status = false;
            $clients = openvpn_get_active_clients();
            foreach ($clients as $client) 
            {
              if (stripos($client['name'], $name) !== false)
              {
                $found_status = true;
                break;
              }
            }
            
            // If client status not found, exit.
            if (!$found_config)
            {
              echo "Did not find VPN client status for \"$name\".\n";
              exit;
            }
            
            // Print the client status
            echo "name: {$client['name']}\n";
            echo "mgmt: {$client['mgmt']}\n";
            echo "status: {$client['status']}\n";
            echo "remote_host: {$client['remote_host']}";
            
            // See if the client is connected to a secondary IP.
            // Note: $client['remote_host'] has trailing white space that
            // we must trim before comparing to $ip
            $remote_host = rtrim($client['remote_host']);
            if ($client['status'] == 'up' && $remote_host == $ip)
            {
              $msg = "The $name VPN client is connected to $ip (VPN server primary IP). Not restarting client.\n";
              echo $msg;
              exec("logger '$msg'");
              exit;
            }
            else if ($client['status'] == 'up')
            {
              $msg = "The $name VPN client is connected to $ip (VPN server secondary IP).\n";
              echo $msg;
              exec("logger '$msg'");
            }
            else
            {
              $msg = "The $name VPN client is not connected. Current status is {$client['status']}.\n";
              echo $msg;
              exec("logger '$msg'");
              exit;
            }
            
            // If we got this far, we will want to restart the VPN client
            // so it connects to primary IP instead of secondary IP.
            
            // Before trying to connect to primary IP, we have to make sure
            // we can ping it. If we can't ping it, there's no sense in
            // trying to connect to it. Furthermore, that is probably
            // the reason why the client is currently connected to the 
            // secondary IP.
            exec("ping -t 10 -o $ip", $output, $return_var);
            echo "ping return_var: $return_var\n";
            
            // A return value of 0 means at least one ping was replied to.
            // In other words, the IP address is up and we should be
            // able to restart to VPN to connect to it.
            if ($return_var == 0)
            {
              $msg = "VPN server primary IP is up. Restarting $name VPN client.\n";
              echo $msg;
              exec("logger '$msg'");
              openvpn_restart('client', $settings);
              $msg = "Finished restarting $name VPN client.\n";
              echo $msg;
              exec("logger '$msg'");
            }
            else
            {
              $msg = "VPN server primary IP is down. Not restarting $name VPN client.\n";
              echo $msg;
              exec("logger '$msg'");
            }
            ?>
            
            1 Reply Last reply Reply Quote 0
            • GruensFroeschliG
              GruensFroeschli
              last edited by

              Having just read this thread i something think you're shooting on sparrows with cannons. (Writing scripts, changing php).

              Is it not feasible to have 2 OpenVPN tunnels up with two different tranfer subnets.
              Each VPN tunnel on it's own WAN.

              When both tunnels are up a failover-pool forces all traffic to the fast connection.
              Should it go down, the backup connection will be used.
              If the connection comes back up everything switches to the fast connection again.

              Should asymetric routing occur (for whatever reasons) traffic could even be NATed into the tunnel to ensure the answer comes back the same tunnel.

              We do what we must, because we can.

              Asking questions the smart way: http://www.catb.org/esr/faqs/smart-questions.html

              1 Reply Last reply Reply Quote 0
              • C
                cyboc
                last edited by

                Hi GruensFroeschli,

                Thank you for your comments.

                @GruensFroeschli:

                Is it not feasible to have 2 OpenVPN tunnels up with two different tranfer subnets.
                Each VPN tunnel on it's own WAN.

                We don't have 2 tunnels. We have only 1. We use OpenVPN's standard way of connecting to redundant server IPs. That is, our VPN client is configured with two remote settings in the config file. For example:

                
                remote fast.foo.com 1194
                remote slow.foo.com 1194
                
                

                Note that we do not use the –remote-random setting in our config. Therefore, the client will always try the first remote IP first and the second remote IP next. If the first IP is up, the client connects to that one but if it is down, the client connects to the second IP.

                @GruensFroeschli:

                When both tunnels are up a failover-pool forces all traffic to the fast connection.
                Should it go down, the backup connection will be used.

                Yes, I absolutely agree. Our current configuration already does that.

                @GruensFroeschli:

                If the connection comes back up everything switches to the fast connection again.

                I have never seen an OpenVPN client connection switch back to the first remote IP after connecting to the second remote IP. As far as I know, there is NO mechanism in OpenVPN to keep trying the first IP after connecting to the second IP and then automatically switch back to the first one when it is up. If someone can tell me the name of the OpenVPN setting to enable this behaviour, I'm all ears.

                We have successfully been running our VPN server like this for months. When the primary IP goes down, the clients automatically switch over to the secondary IP after a short timeout period (about 1 minute). All of this happens without any intervention required by me. That's good!

                However, since the server side's secondary internet connection is way slower than the primary internet connection, we don't like to run the VPN on the secondary connection for long periods of time.

                We usually don't realize that the VPN clients have switched over to the secondary IP until a user calls a couple of days later to say that the VPN seems kind of slow. When we get that phone call, we manually restart the VPN client to force a reconnection to the primary IP.

                The purpose of my script is to automatically switch the VPN clients back to the primary IP when it comes back up.

                Note that my script runs only on the client side, not on the server side. Note also that we run our VPN in UDP mode. Perhaps the behaviour of the failover pool is different for TCP mode?

                If someone can suggest a simpler way of automatically switching the OpenVPN client back to the primary IP after connecting to the secondary IP, I'm all ears. (And by suggest, I mean, showing the exact config settings or code to accomplish this).

                1 Reply Last reply Reply Quote 0
                • GruensFroeschliG
                  GruensFroeschli
                  last edited by

                  You misunderstand me.
                  My suggestion is to not have a single OpenVPN connection with two remote entries,
                  but to actually have two OpenVPN connections with only one remote entry.

                  Let pfSense handle the switching between the tunnels.
                  Or is this OpenVPN client not a pfSense?

                  With pfSense you can create failover-pools under "System –> Routing"

                  We do what we must, because we can.

                  Asking questions the smart way: http://www.catb.org/esr/faqs/smart-questions.html

                  1 Reply Last reply Reply Quote 0
                  • C
                    cyboc
                    last edited by

                    Yes, do use failover pools. For example, we use failover pools at our main office, the office with the two internet connections (which is also the office where the VPN server is). With the failover pool, users at our main office are automatically switched over the the secondary internet connection when the primary internet connection goes down. Thus, they can keep browsing the web, sending email, etc, even when the primary internet connection goes down.

                    Are you suggesting is to user failover pools on the client side (i.e. at our remote offices), which has only one internet connection? If so, how do I make the two tunnels appear as gateways on the Failover group configuration screen? I have never heard of this. If you have a step-by-step configuration for this, I'd like to see it. When I try to add a gateway using the Edit Gateway screen, the only interfaces I see are the actual WAN and LAN interfaces, not any sort of OpenVPN "pseudo" interface.

                    Even if it is possible to have the tunnels appear as gateways in the failover group configuration screen, I'm not sure that would work for our requirements. We do NOT want ALL of the client's traffic to go over the VPN. We want inter-office traffic to go over the VPN but we want all other traffic (web browsing, etc) to go over the client's own internet connection. We have only limited bandwidth at the main office and we don't want all of the web browsing traffic from the several remote offices to go over the VPN.

                    Again, if you have an actual working example, it would be helpful. Otherwise your comments will not really help me solve the problem, which has already been solved by my script.

                    1 Reply Last reply Reply Quote 0
                    • GruensFroeschliG
                      GruensFroeschli
                      last edited by

                      Well not a step by step for this exact scenario but i'll write something up here:

                      (Everything assuming you're running 2.0)

                      Server:
                      1: Create on the server side two OpenVPN instances and bind one to each WAN.
                      If not specified, OpenVPN will bind to all interfaces. You can specify by setting the "–local host" in the "Advanced" configuration field.
                      Make sure that you use two different transfer-subnets for these servers. (eg. 172.21.0.1/24 and 172.22.0.1/24)

                      2: Assign the created OpenVPN clients as interface (Interface --> assign).
                      Enable these newly added OPTs and set the IP configuration to "none".

                      3: Go to "System --> Routing" and create two gateways. One for each client-side IP inside the tunnel.
                      (If you're using the above subnets, that would be 172.21.0.2 and 172.22.0.2)

                      4: Create a failover-pool under the tab "Groups" (main-VPN Tier1, backup-VPN Tier2)

                      5: Create on your LAN tab firewall-rules.
                      #1: allow, source: LAN-subnet, destination: off_site_subnet, gateway: failoverpool
                      #2: allow, source: LAN-subnet, destination: any, gateway: default

                      Client:
                      1: Create two clients on the pfSense, one pointing to each WAN on your server-side.

                      2: Assign the created OpenVPN clients as interface (Interface --> assign).
                      Enable these newly added OPTs and set the IP configuration to "none".

                      3: Go to "System --> Routing" and create two gateways. One for each server-side IP inside the tunnel.
                      (If you're using the above subnets, that would be 172.21.0.1 and 172.22.0.1)

                      4: Create a failover-pool under the tab "Groups" (main-VPN Tier1, backup-VPN Tier2)

                      5: Create on your LAN tab firewall-rules.
                      #1: allow, source: LAN-subnet, destination: main_site_subnet, gateway: failoverpool
                      #2: allow, source: LAN-subnet, destination: any, gateway: default.

                      With such a setup, the failoverpool is responsible for sending traffic via the correct WAN and no longer the OpenVPN client.

                      Addendum:
                      I'm not sure if OpenVPN-traffic for WAN2 will actually leave via WAN2.
                      If it doesn't, a workaround would be that you bind the two OpenVPN server instances on different ports to the LAN interface and create two portforwards to the LAN interface.
                      With NAT involved i know that traffic will leave via the correct WAN.

                      Another thing i see which might be problematic.
                      Traffic from the pfSense itself also needs to use the failover-pools.
                      I never actually did this, but from what i read you can do this via the floating rules.
                      Maybe someone else can help you on this.

                      Also if one of the WANs goes down and a connection has been established on the second WAN and then the first WAN comes back up, it could be that you have asymetric routing.
                      If NAT is not a problem for your setup you could NAT all traffic into the VPN tunnel.
                      For the other side this would effectively hide the subnet behind the pfSense and traffic would always flow correctly.
                      To configure this go to "Firewall --> NAT --> outbound" and enable manual rule generation.
                      Now create a rule for both WANs and the assigned OpenVPN interfaces.

                      We do what we must, because we can.

                      Asking questions the smart way: http://www.catb.org/esr/faqs/smart-questions.html

                      1 Reply Last reply Reply Quote 0
                      • C
                        cyboc
                        last edited by

                        Thank you very much for that procedure GruensFroeschli! When I have a few spare hours, I'll try that technique in a lab.

                        As for my script, below is a new version with a couple of changes. First, the "VPN client is connected to <ip address="">" message was printing the wrong IP address. Second, I modified the code that does the restart of the openvpn process. Instead of calling the openvpn_restart function in the file /etc/inc/openvpn.inc, I mimicked the restart code in /usr/local/www/status_services.php, which seems to be more reliable. In my testing, the openvpn_restart function sometimes failed to start the new openvpn process after terminating the old process. The main difference between the two seems to be in the way they wait for the old process to terminate.

                        More testing is required but it seems to work right now.

                        #!/usr/local/bin/php -f
                        require_once('config.inc');
                        include('openvpn.inc');
                        
                        // Read in all of the OpenVPN client configs.
                        global $config;
                        if (!is_array($config['openvpn']['openvpn-client']))
                        {
                          return;
                        }
                        
                        // Find client config for London VPN server
                        $found_config = false;
                        $name = "London";
                        foreach ($config['openvpn']['openvpn-client'] as & $settings)
                        {
                          if (stripos($settings['description'], $name) !== false)
                          {
                             $found_config = true;
                             break;
                          }
                        }
                        
                        // If client config not found, exit.
                        if (!$found_config)
                        {
                          echo "Did not find client VPN config for \"$name\".\n";
                          exit;
                        }
                        
                        // Print the client config.
                        echo "vpnid: {$settings['vpnid']}\n";
                        echo "description: {$settings['description']}\n";
                        echo "server_addr: {$settings['server_addr']}\n";   
                        echo "custom_options: {$settings['custom_options']}\n";
                        
                        // Resolve the configured host name to an IP address.
                        // This is the VPN server's primary IP.
                        $ip_primary = gethostbyname($settings['server_addr']);
                        echo "VPN server primary IP: $ip_primary\n";
                        
                        // Tokenize the custom_options to get the VPN 
                        // server's secondary IP.
                        $tok = strtok($settings['custom_options'], " \n\t;");
                        while ($tok !== false) {
                          if (strcasecmp($tok, 'remote') == 0)
                          {
                            $tok = strtok(" \n\t;");
                            if ($tok !== false)
                            {
                              $ip_secondary = gethostbyname($tok);
                              echo "VPN server secondary IP: $ip_secondary\n";    
                            }
                          }
                          $tok = strtok(" \n\t;");
                        }
                        
                        // Find the status for the VPN client.
                        $found_status = false;
                        $clients = openvpn_get_active_clients();
                        foreach ($clients as $client) 
                        {
                          if (stripos($client['name'], $name) !== false)
                          {
                            $found_status = true;
                            break;
                          }
                        }
                        
                        // If client status not found, exit.
                        if (!$found_config)
                        {
                          echo "Did not find VPN client status for \"$name\".\n";
                          exit;
                        }
                        
                        // Print the client status
                        echo "name: {$client['name']}\n";
                        echo "mgmt: {$client['mgmt']}\n";
                        echo "status: {$client['status']}\n";
                        echo "remote_host: {$client['remote_host']}";
                        
                        // See if the client is connected to a secondary IP.
                        // Note: $client['remote_host'] has trailing white space that
                        // we must trim before comparing to $ip_primary
                        $remote_host = rtrim($client['remote_host']);
                        if ($client['status'] == 'up' && $remote_host == $ip_primary)
                        {
                          $msg = "The $name VPN client is connected to $remote_host (VPN server primary IP). Not restarting client.\n";
                          echo $msg;
                          exec("logger '$msg'");
                          exit;
                        }
                        else if ($client['status'] == 'up')
                        {
                          $msg = "The $name VPN client is connected to $remote_host (VPN server secondary IP).\n";
                          echo $msg;
                          exec("logger '$msg'");
                        }
                        else
                        {
                          $msg = "The $name VPN client is not connected. Current status is {$client['status']}.\n";
                          echo $msg;
                          exec("logger '$msg'");
                          exit;
                        }
                        
                        // If we got this far, we will want to restart the VPN client
                        // so it connects to primary IP instead of secondary IP.
                        
                        // Before trying to connect to primary IP, we have to make sure
                        // we can ping it. If we can't ping it, there's no sense in
                        // trying to connect to it. Furthermore, that is probably
                        // the reason why the client is currently connected to the 
                        // secondary IP.
                        exec("ping -t 10 -o $ip_primary", $output, $return_var);
                        echo "ping return_var: $return_var\n";
                        
                        // A return value of 0 means at least one ping was replied to.
                        // In other words, the IP address is up and we should be
                        // able to restart to VPN to connect to it.
                        if ($return_var == 0)
                        {
                          $msg = "VPN server primary IP is up. Restarting $name VPN client.\n";
                          echo $msg;
                          exec("logger '$msg'");
                        
                          // Restart the VPN client by mimicking the technique used in
                          // the file /usr/local/www/status_services.php
                          //openvpn_restart('client', $settings);
                          $configfile = "{$g['varetc_path']}/openvpn/client{$settings['vpnid']}.conf";
                          $pidfile =    "{$g['varrun_path']}/openvpn_client{$settings['vpnid']}.pid";
                          if (file_exists($configfile)) {
                            $msg = "Terminating openvpn using pidfile: $pidfile\n";
                            echo $msg;
                            exec("logger '$msg'");
                            killbypid($pidfile);
                            // wait for process to terminate
                            sleep(1);
                            $msg = "Starting new openvpn process using config file: $configfile\n";
                            echo $msg;
                            exec("logger '$msg'");
                            mwexec_bg("/usr/local/sbin/openvpn --config {$configfile}");
                          }
                        
                          $msg = "Finished restarting $name VPN client.\n";
                          echo $msg;
                          exec("logger '$msg'");
                        }
                        else
                        {
                          $msg = "VPN server primary IP is down. Not restarting $name VPN client.\n";
                          echo $msg;
                          exec("logger '$msg'");
                        }
                        ?>
                        ```</ip>
                        1 Reply Last reply Reply Quote 0
                        • P
                          Philay
                          last edited by

                          Hi cyboc,

                          Very nice work right here. I have try your solution today (we have similar dual WAN config) and it is very simple indeed! Contrary to what GruensFroeschli said, I thinks his solution is the one that is "shooting on sparrows with cannons." Heck, his solution hasn't even been tried yet!

                          One suggestion for your code however. There is problem with these two lines:

                          $ip_primary = gethostbyname($settings['server_addr']);
                          // ...
                          if ($client['status'] == 'up' && $remote_host == $ip_primary)
                          

                          You assuming that PHP function gethostbyname will work correctly every time. However, I had temporary problem with my ISP DNS server today. It was down. So when I try to do the lookup with gethostbyname it fails (timeout). So instead of returning IP address, it returns the hostname I was looking up. So, expression $remote_host == $ip_primary will return false eventhough hostname should resolve to that $remote_host IP if lookup was working. So, VPN as a result will restart when it shouldn't. See it?

                          To explain with example, let's say foo.com should resolve to 192.168.1.1 and $remote_host is currently 192.168.1.1 and that is the primary IP. If lookup works, $remote_host == $ip_primary will return true and VPN will not restart (because 192.168.1.1 equals 192.168.1.1). This is what we want if connection currently on primary IP (is good). But if lookup fails, expression will return false and VPN will restart when it should not (192.168.1.1 is NOT equal to foo.com). Get it?

                          So maybe if lookup fails, you should just abort? Just suggestion here.

                          1 Reply Last reply Reply Quote 0
                          • C
                            cyboc
                            last edited by

                            @Philay:

                            You assuming that PHP function gethostbyname will work correctly every time. However, I had temporary problem with my ISP DNS server today. It was down. So when I try to do the lookup with gethostbyname it fails (timeout). So instead of returning IP address, it returns the hostname I was looking up.

                            Philay, good catch. You are right. The documentation for gethostbyname does say that it "Returns the IPv4 address or a string containing the unmodified hostname on failure."

                            Well when I started this thread, I did say that I'm not a PHP guy. :)

                            I will fix this. Thanks!

                            BTW, I think you are too hard on GruensFroeschli. I think his solution is fine and will probably work. I just don't have time to try it right now.

                            1 Reply Last reply Reply Quote 0
                            • C
                              cyboc
                              last edited by

                              Philay,

                              Here is another new version. As you suggested, I have added a check for DNS lookup errors. I have also turned the client name (full or partial match) into a parameter instead of hard-coding it (usage: restart-vpn-client.php <full or="" partial="" vpn="" client="" name="">). I also made some minor changes to the output.

                              #!/usr/local/bin/php -f
                              require_once('config.inc');
                              include('openvpn.inc');
                              
                              if ($argc != 2)
                              {
                                echo "Usage: " . basename($argv[0]) . " <full or="" partial="" vpn="" client="" name="">\n";
                                exit;
                              }
                              $name = $argv[1];
                              
                              $msg = "Checking whether the $name VPN client needs a restart.";
                              echo $msg."\n";
                              exec("logger '$msg'");
                              
                              // Read in all of the OpenVPN client configs.
                              global $config;
                              if (!is_array($config['openvpn']['openvpn-client']))
                              {
                                return;
                              }
                              
                              // Find client config for given name
                              $found_config = false;
                              foreach ($config['openvpn']['openvpn-client'] as & $settings)
                              {
                                if (stripos($settings['description'], $name) !== false)
                                {
                                   $found_config = true;
                                   break;
                                }
                              }
                              
                              // If client config not found, exit.
                              if (!$found_config)
                              {
                                echo "Did not find client VPN config for \"$name\".\n";
                                exit;
                              }
                              
                              // Print the client config.
                              echo "\n----Client configuration----\n";
                              echo "vpnid: {$settings['vpnid']}\n";
                              echo "description: {$settings['description']}\n";
                              echo "server_addr: {$settings['server_addr']}\n";   
                              echo "custom_options: {$settings['custom_options']}\n\n";
                              
                              // Resolve the configured host name to an IP address.
                              // This is the VPN server's primary IP.
                              if (is_ipaddr($settings['server_addr']))
                              {
                                $ip_primary = $settings['server_addr'];
                              }
                              else
                              {
                                $ip_primary = gethostbyname($settings['server_addr']);
                                if ($ip_primary == $settings['server_addr'])
                                {
                                  echo "DNS lookup failed for VPN server primary hostname ({$settings['server_addr']}). Exiting.\n";
                                  exit;
                                }
                              }
                              echo "VPN server primary IP: $ip_primary\n";
                              
                              // Tokenize the custom_options to get the VPN 
                              // server's secondary IP.
                              $tok = strtok($settings['custom_options'], " \n\t;");
                              while ($tok !== false) 
                              {
                                if (strcasecmp($tok, 'remote') == 0)
                                {
                                  $tok = strtok(" \n\t;");
                                  if ($tok !== false)
                                  {
                                    if (is_ipaddr($tok))
                                    {
                                      $ip_secondary = $tok;
                                    }
                                    else
                                    {
                                      $ip_secondary = gethostbyname($tok);
                                      if ($ip_secondary == $tok)
                                      {
                                        echo "DNS lookup failed for VPN server secondary hostname ($tok). Exiting.\n";
                                        exit;
                                      }
                                    }
                                    echo "VPN server secondary IP: $ip_secondary\n";    
                                  }
                                }
                                $tok = strtok(" \n\t;");
                              }
                              
                              // Find the status for the VPN client.
                              $found_status = false;
                              $clients = openvpn_get_active_clients();
                              foreach ($clients as $client) 
                              {
                                if (stripos($client['name'], $name) !== false)
                                {
                                  $found_status = true;
                                  break;
                                }
                              }
                              
                              // If client status not found, exit.
                              if (!$found_config)
                              {
                                echo "Did not find VPN client status for \"$name\".\n";
                                exit;
                              }
                              
                              // Print the client status
                              echo "\n----Client status----\n";
                              echo "name: {$client['name']}\n";
                              echo "mgmt: {$client['mgmt']}\n";
                              echo "status: {$client['status']}\n";
                              echo "remote_host: {$client['remote_host']}\n";
                              
                              // See if the client is connected to a secondary IP.
                              // Note: $client['remote_host'] has trailing white space that
                              // we must trim before comparing to $ip_primary
                              $remote_host = rtrim($client['remote_host']);
                              if ($client['status'] == 'up' && $remote_host == $ip_primary)
                              {
                                $msg = "The $name VPN client is connected to $remote_host (VPN server primary IP). Not restarting client.";
                                echo $msg."\n";
                                exec("logger '$msg'");
                                exit;
                              }
                              else if ($client['status'] == 'up')
                              {
                                $msg = "The $name VPN client is connected to $remote_host (VPN server secondary IP).";
                                echo $msg."\n";
                                exec("logger '$msg'");
                              }
                              else
                              {
                                $msg = "The $name VPN client is not connected. Current status is {$client['status']}.";
                                echo $msg."\n";
                                exec("logger '$msg'");
                                exit;
                              }
                              
                              // If we got this far, we will want to restart the VPN client
                              // so it connects to primary IP instead of secondary IP.
                              
                              // Before trying to connect to primary IP, we have to make sure
                              // we can ping it. If we can't ping it, there's no sense in
                              // trying to connect to it. Furthermore, that is probably
                              // the reason why the client is currently connected to the 
                              // secondary IP.
                              exec("ping -t 10 -o $ip_primary", $output, $return_var);
                              echo "ping return_var: $return_var\n";
                              
                              // A return value of 0 means at least one ping was replied to.
                              // In other words, the IP address is up and we should be
                              // able to restart to VPN to connect to it.
                              if ($return_var == 0)
                              {
                                $msg = "VPN server primary IP is up. Restarting $name VPN client.";
                                echo $msg."\n";
                                exec("logger '$msg'");
                              
                                // Restart the VPN client by mimicking the technique used in
                                // the file /usr/local/www/status_services.php
                                //openvpn_restart('client', $settings);
                                $configfile = "{$g['varetc_path']}/openvpn/client{$settings['vpnid']}.conf";
                                $pidfile =    "{$g['varrun_path']}/openvpn_client{$settings['vpnid']}.pid";
                                if (file_exists($configfile)) 
                                {
                                  $msg = "Terminating openvpn using pidfile: $pidfile";
                                  echo $msg."\n";
                                  exec("logger '$msg'");
                                  killbypid($pidfile);
                                  // wait for process to terminate
                                  sleep(1);
                                  $msg = "Starting new openvpn process using config file: $configfile";
                                  echo $msg."\n";
                                  exec("logger '$msg'");
                                  mwexec_bg("/usr/local/sbin/openvpn --config {$configfile}");
                                }
                              
                                $msg = "Finished restarting $name VPN client.";
                                echo $msg."\n";
                                exec("logger '$msg'");
                              }
                              else
                              {
                                $msg = "VPN server primary IP is down. Not restarting $name VPN client.";
                                echo $msg."\n";
                                exec("logger '$msg'");
                              }
                              ?></full>
                              ```</full>
                              1 Reply Last reply Reply Quote 0
                              • P
                                Philay
                                last edited by

                                Okay, seems is working a little better now with DNS. Hoping for more improvements soon.

                                1 Reply Last reply Reply Quote 0
                                • First post
                                  Last post
                                Copyright 2025 Rubicon Communications LLC (Netgate). All rights reserved.