Como faço para desconectar programaticamente uma conexão OpenVPN?
Pergunta
Estou criando um aplicativo WinForms para iniciar e interromper uma conexão OpenVPN no Windows. Estou tentando alcançar a mesma funcionalidade que o OpenVPN GUI para Windows (http://openvpn.se/) fornece, mas usando minha própria interface do usuário baseada em .NET.
Estou iniciando a conexão usando a seguinte abordagem:
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();
Isso chama o OpenVPN.exe e a conexão é estabelecida com sucesso.
No entanto, sou incapaz de determinar uma maneira de encerrar a conexão depois de estabelecida. Eu tentei usar process.kill ()
foreach (var p in Process.GetProcessesByName("openvpn"))
{
p.Kill();
}
Isso mata o processo, mas não restaura o estado de roteamento inicial. Efetivamente, não posso acessar a rede até desativar/ativar manualmente meu cartão LAN.
Saída de 'OpenVPN--Show-Net' antes que a conexão VPN seja estabelecida:
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
'OpenVPN-Show-Net' após a conexão VPN ser fechada usando o processo.kill ():
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 =
Eu também tentei enviar o processo WM_CLOSE / WM_QUIT / WM_ENDMESSAGE
mensagens, mas elas não produziram nenhum resultado.
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);
}
Mais informações sobre a solução apropriada: Veja as instruções na seção intitulada Usando a interface de gerenciamento dentro Controlando um processo em execução OpenVPN.
Mais informações sobre o uso Telnet de c#.
Solução
Eu não tentei isso no Windows, mas você pode usar o Interface de gerenciamento OpenVPN Para enviar um SIGTERM
sinal com o signal
comando. Você precisará incluir as entradas de configuração da interface de gerenciamento em seu arquivo de configuração, é claro.
Mais informações no Página do OpenVPN Man
Você pode querer olhar para o caminho OpenVPN-Admin está fazendo as coisas. Está funcionando com Windows e Linux e desenvolvido com o Mono.
Outras dicas
Você está enviando mensagens para o controle do processo - estes, no entanto, são janela mensagens, é por isso que elas devem ser enviadas para um janela lidar com.
EDITAR
Como você já conseguiu o processo, você pode tentar o seguinte:
foreach (var p in Process.GetProcessesByName("openvpn"))
{
p.CloseMainWindow();
}
ou
[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)
}