【问题标题】:How do I programmatically disconnect an OpenVPN connection?如何以编程方式断开 OpenVPN 连接?
【发布时间】:2009-07-07 11:44:16
【问题描述】:

我正在创建一个 WinForms 应用程序来启动和停止 Windows 上的 OpenVPN 连接。我正在尝试实现与 OpenVPN GUI for Windows (http://openvpn.se/) 提供的相同功能,但使用的是我自己的基于 .NET 的 UI。

我正在使用以下方法开始连接:

Process openVpnProcess = new Process();
openVpnProcess.StartInfo.CreateNoWindow = true;
openVpnProcess.EnableRaisingEvents = true;
openVpnProcess.StartInfo.Arguments = "--config client.ovpn";
openVpnProcess.StartInfo.FileName = "openvpn.exe";
openVpnProcess.StartInfo.WorkingDirectory = @"C:\Program Files\OpenVPN\config";
openVpnProcess.Start();

这会调用 openvpn.exe 并成功建立连接。

但是,一旦建立连接,我无法确定终止连接的方法。我试过使用 Process.Kill()

foreach (var p in Process.GetProcessesByName("openvpn"))
{
    p.Kill();
}

这会杀死进程,但不会恢复初始路由状态。实际上,在我手动禁用/启用我的 LAN 卡之前,我无法访问网络。

在建立 VPN 连接之前'openvpn --show-net' 的输出:

SYSTEM ROUTING TABLE
0.0.0.0 0.0.0.0 10.31.0.254 p=0 i=1376258 t=4 pr=3 a=21 h=0 m=1/-1/-1/-1/-1
10.31.0.0 255.255.240.0 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=26 h=0 m=20/-1/-1/-1/-1
10.31.10.235 255.255.255.255 127.0.0.1 p=0 i=1 t=3 pr=2 a=26 h=0 m=20/-1/-1/-1/-1
10.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=26 h=0 m=20/-1/-1/-1/-1
127.0.0.0 255.0.0.0 127.0.0.1 p=0 i=1 t=3 pr=2 a=116753 h=0 m=1/-1/-1/-1/-1
224.0.0.0 240.0.0.0 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=26 h=0 m=20/-1/-1/-1/-1
255.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=26 h=0 m=1/-1/-1/-1/-1
255.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1441796 t=3 pr=2 a=4 h=0 m=1/-1/-1/-1/-1
SYSTEM ADAPTER LIST
TAP-Win32 Adapter V8
  Index = 1441796
  GUID = {013AB57F-DFE6-4FD9-B25E-9589E77DA4EB}
  IP = 0.0.0.0/0.0.0.0
  MAC = 00:ff:01:3a:b5:7f
  GATEWAY =
  DHCP SERV = 172.16.0.0
  DHCP LEASE OBTAINED = Tue Jul 07 16:35:20 2009
  DHCP LEASE EXPIRES  = Wed Jul 07 16:35:20 2010
D-Link DFE-538TX 10/100 Adapter
  Index = 1376258
  GUID = {FB6051A1-E970-4F46-BB85-F442A194BA3D}
  IP = 10.31.10.235/255.255.240.0
  MAC = 00:08:a1:65:70:93
  GATEWAY = 10.31.0.254/0.0.0.0

使用 Process.Kill() 关闭 VPN 连接后的'openvpn --show-net':

SYSTEM ROUTING TABLE
10.31.0.0 255.255.240.0 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=106 h=0 m=20/-1/-1/-1/-1
10.31.10.235 255.255.255.255 127.0.0.1 p=0 i=1 t=3 pr=2 a=106 h=0 m=20/-1/-1/-1/-1
10.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=106 h=0 m=20/-1/-1/-1/-1
127.0.0.0 255.0.0.0 127.0.0.1 p=0 i=1 t=3 pr=2 a=116833 h=0 m=1/-1/-1/-1/-1
208.94.64.10 255.255.255.255 10.31.0.254 p=0 i=1376258 t=4 pr=3 a=21 h=0 m=1/-1/-1/-1/-1
224.0.0.0 240.0.0.0 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=106 h=0 m=20/-1/-1/-1/-1
255.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1376258 t=3 pr=2 a=106 h=0 m=1/-1/-1/-1/-1
255.255.255.255 255.255.255.255 10.31.10.235 p=0 i=1441796 t=3 pr=2 a=84 h=0 m=1/-1/-1/-1/-1
SYSTEM ADAPTER LIST
TAP-Win32 Adapter V8
  Index = 1441796
  GUID = {013AB57F-DFE6-4FD9-B25E-9589E77DA4EB}
  IP = 0.0.0.0/0.0.0.0
  MAC = 00:ff:01:3a:b5:7f
  GATEWAY =
  DHCP SERV = 172.16.0.0
  DHCP LEASE OBTAINED = Tue Jul 07 17:02:30 2009
  DHCP LEASE EXPIRES  = Wed Jul 07 17:02:30 2010
D-Link DFE-538TX 10/100 Adapter
  Index = 1376258
  GUID = {FB6051A1-E970-4F46-BB85-F442A194BA3D}
  IP = 10.31.10.235/255.255.240.0
  MAC = 00:08:a1:65:70:93
  GATEWAY =

我也尝试发送进程WM_CLOSE / WM_QUIT / WM_ENDMESSAGE 消息,但这些没有产生任何结果。

const int WM_CLOSE = 0x10;
const int WM_QUIT = 0x12;
const int WM_ENDSESSION = 0x0016;

[DllImport("user32.dll")]
public static extern int SendMessage(int hwnd, int msg, int wparam, int lparam);

foreach (var p in Process.GetProcessesByName("openvpn"))
{
    SendMessage(p.Handle.ToInt32(), WM_CLOSE, 0, 0);
    SendMessage(p.Handle.ToInt32(), WM_QUIT, 0, 0);
    SendMessage(p.Handle.ToInt32(), WM_ENDSESSION, 0, 0);
}

有关适当解决方案的更多信息:请参阅 Controlling a running OpenVPN process 中标题为使用管理界面的部分中的说明。

更多关于使用Telnet from C#的信息。

【问题讨论】:

  • 我现在有类似的任务。这似乎是 openvpn server 的 GUI,这意味着您要控制自己的 opnvpn 服务器。是对的吗?如果是这样,你为什么要传递参数 -- config client.ovpn 给它?
  • 您可以通过在 github 上查看与 openvpn(openvpn-manager) 相关的一个很棒的项目来做到这一点。以下链接中的代码可以帮助您:github.com/Searching/openvpn-manager/blob/master/…

标签: winforms process openvpn


【解决方案1】:

我没有在 Windows 上尝试过,但您可以使用 OpenVPN Management interface 通过 signal 命令发送 SIGTERM 信号。当然,您需要在配置文件中包含管理界面配置条目。

更多信息在OpenVPN man page

您可能想看看OpenVPN-admin 的做事方式。它在 Windows 和 Linux 下工作,并使用 Mono 开发。

【讨论】:

【解决方案2】:

您正在向进程句柄发送消息 - 但是,这些是 window 消息,因此必须将它们发送到 window 句柄。

编辑
由于您已经掌握了流程,您可以尝试以下方法:

foreach (var p in Process.GetProcessesByName("openvpn"))
{
    p.CloseMainWindow();
}

[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hwnd, int msg, int wparam, int lparam);

foreach (var p in Process.GetProcessesByName("openvpn"))
{
    IntPtr hWnd = p.MainWindowHandle;
    // Send message to hWnd (mind SendMessage's changed signature)
}

【讨论】:

  • 谢谢托尔斯滕。你能指出我如何获得窗口句柄吗?那会使用 FindWindow() 吗? (我很少做 Win32 编程)
  • 编辑了我的答案,为您提供更多信息。
  • 我试过 p.CloseMainWindow();但它不起作用。在进一步的研究中,我意识到 OpenVPN 管理界面对于我想要实现的目标来说是一种更合适的方法。不过,感谢您提供更多信息,这有助于理清概念。
猜你喜欢
  • 1970-01-01
  • 2011-02-27
  • 2012-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多