mirror of
https://github.com/OpenVPN/openvpn.git
synced 2024-09-20 12:02:28 +02:00
Refactor and move the block-outside-dns code to a new file (block_dns.[ch])
- Move the core of win_wfp_block_dns() to a new function - Remove globals and make it independent of the rest of the code This facilitates implementing support for block-outside-dns through the interactive service. Should not change any functionality. v2 changes: - In comments, correct DeleteBlockDNS() to delete_block_dns_filters v2a: added <winsock2.h> and <ws2ipdef.h> (Gert Doering) Signed-off-by: Selva Nair <selva.nair@gmail.com> Acked-by: Gert Doering <gert@greenie.muc.de> Message-Id: <1456457091-3872-1-git-send-email-selva.nair@gmail.com> URL: http://article.gmane.org/gmane.network.openvpn.devel/11264 Signed-off-by: Gert Doering <gert@greenie.muc.de>
This commit is contained in:
parent
71d89065ad
commit
6a33a34dee
@ -126,6 +126,6 @@ openvpn_LDADD = \
|
|||||||
$(OPTIONAL_SYSTEMD_LIBS) \
|
$(OPTIONAL_SYSTEMD_LIBS) \
|
||||||
$(OPTIONAL_DL_LIBS)
|
$(OPTIONAL_DL_LIBS)
|
||||||
if WIN32
|
if WIN32
|
||||||
openvpn_SOURCES += openvpn_win32_resources.rc
|
openvpn_SOURCES += openvpn_win32_resources.rc block_dns.c block_dns.h
|
||||||
openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4
|
openvpn_LDADD += -lgdi32 -lws2_32 -lwininet -lcrypt32 -liphlpapi -lwinmm -lfwpuclnt -lrpcrt4
|
||||||
endif
|
endif
|
||||||
|
267
src/openvpn/block_dns.c
Normal file
267
src/openvpn/block_dns.c
Normal file
@ -0,0 +1,267 @@
|
|||||||
|
/*
|
||||||
|
* OpenVPN -- An application to securely tunnel IP networks
|
||||||
|
* over a single TCP/UDP port, with support for SSL/TLS-based
|
||||||
|
* session authentication and key exchange,
|
||||||
|
* packet encryption, packet authentication, and
|
||||||
|
* packet compression.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
|
||||||
|
* 2015-2016 <iam@valdikss.org.ru>
|
||||||
|
* 2016 Selva Nair <selva.nair@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program (see the file COPYING included with this
|
||||||
|
* distribution); if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#include <fwpmu.h>
|
||||||
|
#include <initguid.h>
|
||||||
|
#include <fwpmtypes.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <ws2ipdef.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
#include "block_dns.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WFP-related defines and GUIDs not in mingw32
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FWPM_SESSION_FLAG_DYNAMIC
|
||||||
|
#define FWPM_SESSION_FLAG_DYNAMIC 0x00000001
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// c38d57d1-05a7-4c33-904f-7fbceee60e82
|
||||||
|
DEFINE_GUID(
|
||||||
|
FWPM_LAYER_ALE_AUTH_CONNECT_V4,
|
||||||
|
0xc38d57d1,
|
||||||
|
0x05a7,
|
||||||
|
0x4c33,
|
||||||
|
0x90, 0x4f, 0x7f, 0xbc, 0xee, 0xe6, 0x0e, 0x82
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4a72393b-319f-44bc-84c3-ba54dcb3b6b4
|
||||||
|
DEFINE_GUID(
|
||||||
|
FWPM_LAYER_ALE_AUTH_CONNECT_V6,
|
||||||
|
0x4a72393b,
|
||||||
|
0x319f,
|
||||||
|
0x44bc,
|
||||||
|
0x84, 0xc3, 0xba, 0x54, 0xdc, 0xb3, 0xb6, 0xb4
|
||||||
|
);
|
||||||
|
|
||||||
|
// d78e1e87-8644-4ea5-9437-d809ecefc971
|
||||||
|
DEFINE_GUID(
|
||||||
|
FWPM_CONDITION_ALE_APP_ID,
|
||||||
|
0xd78e1e87,
|
||||||
|
0x8644,
|
||||||
|
0x4ea5,
|
||||||
|
0x94, 0x37, 0xd8, 0x09, 0xec, 0xef, 0xc9, 0x71
|
||||||
|
);
|
||||||
|
|
||||||
|
// c35a604d-d22b-4e1a-91b4-68f674ee674b
|
||||||
|
DEFINE_GUID(
|
||||||
|
FWPM_CONDITION_IP_REMOTE_PORT,
|
||||||
|
0xc35a604d,
|
||||||
|
0xd22b,
|
||||||
|
0x4e1a,
|
||||||
|
0x91, 0xb4, 0x68, 0xf6, 0x74, 0xee, 0x67, 0x4b
|
||||||
|
);
|
||||||
|
|
||||||
|
// 4cd62a49-59c3-4969-b7f3-bda5d32890a4
|
||||||
|
DEFINE_GUID(
|
||||||
|
FWPM_CONDITION_IP_LOCAL_INTERFACE,
|
||||||
|
0x4cd62a49,
|
||||||
|
0x59c3,
|
||||||
|
0x4969,
|
||||||
|
0xb7, 0xf3, 0xbd, 0xa5, 0xd3, 0x28, 0x90, 0xa4
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default msg handler does nothing
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
default_msg_handler (DWORD err, const char *msg)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CHECK_ERROR(err, msg) \
|
||||||
|
if (err) { msg_handler (err, msg); goto out; }
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Block outgoing port 53 traffic except for
|
||||||
|
* (i) adapter with the specified index
|
||||||
|
* OR
|
||||||
|
* (ii) processes with the specified executable path
|
||||||
|
* The firewall filters added here are automatically removed when the process exits or
|
||||||
|
* on calling delete_block_dns_filters().
|
||||||
|
* Arguments:
|
||||||
|
* engine_handle : On successful return contains the handle for a newly opened fwp session
|
||||||
|
* in which the filters are added.
|
||||||
|
* May be closed by passing to delete_block_dns_filters to remove the filters.
|
||||||
|
* index : The index of adapter for which traffic is permitted.
|
||||||
|
* exe_path : Path of executable for which traffic is permitted.
|
||||||
|
* msg_handler : An optional callback function for error reporting.
|
||||||
|
* Returns 0 on success, a non-zero status code of the last failed action on failure.
|
||||||
|
*/
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
add_block_dns_filters (HANDLE *engine_handle,
|
||||||
|
int index,
|
||||||
|
const WCHAR *exe_path,
|
||||||
|
block_dns_msg_handler_t msg_handler
|
||||||
|
)
|
||||||
|
{
|
||||||
|
FWPM_SESSION0 session = {0};
|
||||||
|
FWPM_SUBLAYER0 SubLayer = {0};
|
||||||
|
NET_LUID tapluid;
|
||||||
|
UINT64 filterid;
|
||||||
|
FWP_BYTE_BLOB *openvpnblob = NULL;
|
||||||
|
FWPM_FILTER0 Filter = {0};
|
||||||
|
FWPM_FILTER_CONDITION0 Condition[2] = {0};
|
||||||
|
WCHAR *FIREWALL_NAME = L"OpenVPN";
|
||||||
|
DWORD err = 0;
|
||||||
|
|
||||||
|
if (!msg_handler)
|
||||||
|
msg_handler = default_msg_handler;
|
||||||
|
|
||||||
|
/* Add temporary filters which don't survive reboots or crashes. */
|
||||||
|
session.flags = FWPM_SESSION_FLAG_DYNAMIC;
|
||||||
|
|
||||||
|
*engine_handle = NULL;
|
||||||
|
|
||||||
|
err = FwpmEngineOpen0 (NULL, RPC_C_AUTHN_WINNT, NULL, &session, engine_handle);
|
||||||
|
CHECK_ERROR (err, "FwpEngineOpen: open fwp session failed");
|
||||||
|
|
||||||
|
err = UuidCreate (&SubLayer.subLayerKey);
|
||||||
|
CHECK_ERROR (err, "UuidCreate: create sublayer key failed");
|
||||||
|
|
||||||
|
/* Populate packet filter layer information. */
|
||||||
|
SubLayer.displayData.name = FIREWALL_NAME;
|
||||||
|
SubLayer.displayData.description = FIREWALL_NAME;
|
||||||
|
SubLayer.flags = 0;
|
||||||
|
SubLayer.weight = 0x100;
|
||||||
|
|
||||||
|
/* Add sublayer to the session */
|
||||||
|
err = FwpmSubLayerAdd0 (*engine_handle, &SubLayer, NULL);
|
||||||
|
CHECK_ERROR (err, "FwpmSubLayerAdd: add sublayer to session failed");
|
||||||
|
|
||||||
|
msg_handler (0, "Block_DNS: WFP engine opened");
|
||||||
|
|
||||||
|
err = ConvertInterfaceIndexToLuid (index, &tapluid);
|
||||||
|
CHECK_ERROR (err, "Convert interface index to luid failed");
|
||||||
|
|
||||||
|
err = FwpmGetAppIdFromFileName0 (exe_path, &openvpnblob);
|
||||||
|
CHECK_ERROR (err, "Get byte blob for openvpn executable name failed");
|
||||||
|
|
||||||
|
/* Prepare filter. */
|
||||||
|
Filter.subLayerKey = SubLayer.subLayerKey;
|
||||||
|
Filter.displayData.name = FIREWALL_NAME;
|
||||||
|
Filter.weight.type = FWP_UINT8;
|
||||||
|
Filter.weight.uint8 = 0xF;
|
||||||
|
Filter.filterCondition = Condition;
|
||||||
|
Filter.numFilterConditions = 2;
|
||||||
|
|
||||||
|
/* First filter. Permit IPv4 DNS queries from OpenVPN itself. */
|
||||||
|
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
||||||
|
Filter.action.type = FWP_ACTION_PERMIT;
|
||||||
|
|
||||||
|
Condition[0].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
|
||||||
|
Condition[0].matchType = FWP_MATCH_EQUAL;
|
||||||
|
Condition[0].conditionValue.type = FWP_UINT16;
|
||||||
|
Condition[0].conditionValue.uint16 = 53;
|
||||||
|
|
||||||
|
Condition[1].fieldKey = FWPM_CONDITION_ALE_APP_ID;
|
||||||
|
Condition[1].matchType = FWP_MATCH_EQUAL;
|
||||||
|
Condition[1].conditionValue.type = FWP_BYTE_BLOB_TYPE;
|
||||||
|
Condition[1].conditionValue.byteBlob = openvpnblob;
|
||||||
|
|
||||||
|
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||||
|
CHECK_ERROR (err, "Add filter to permit IPv4 port 53 traffic from OpenVPN failed");
|
||||||
|
|
||||||
|
/* Second filter. Permit IPv6 DNS queries from OpenVPN itself. */
|
||||||
|
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
||||||
|
|
||||||
|
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||||
|
CHECK_ERROR (err, "Add filter to permit IPv6 port 53 traffic from OpenVPN failed");
|
||||||
|
|
||||||
|
msg_handler (0, "Block_DNS: Added permit filters for exe_path");
|
||||||
|
|
||||||
|
/* Third filter. Block all IPv4 DNS queries. */
|
||||||
|
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
||||||
|
Filter.action.type = FWP_ACTION_BLOCK;
|
||||||
|
Filter.weight.type = FWP_EMPTY;
|
||||||
|
Filter.numFilterConditions = 1;
|
||||||
|
|
||||||
|
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||||
|
CHECK_ERROR (err, "Add filter to block IPv4 DNS traffic failed");
|
||||||
|
|
||||||
|
msg_handler (0, "Block_DNS: Added block filters for all");
|
||||||
|
|
||||||
|
/* Forth filter. Block all IPv6 DNS queries. */
|
||||||
|
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
||||||
|
|
||||||
|
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||||
|
CHECK_ERROR (err, "Add filter to block IPv6 DNS traffic failed");
|
||||||
|
|
||||||
|
/* Fifth filter. Permit IPv4 DNS queries from TAP. */
|
||||||
|
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
||||||
|
Filter.action.type = FWP_ACTION_PERMIT;
|
||||||
|
Filter.numFilterConditions = 2;
|
||||||
|
|
||||||
|
Condition[1].fieldKey = FWPM_CONDITION_IP_LOCAL_INTERFACE;
|
||||||
|
Condition[1].matchType = FWP_MATCH_EQUAL;
|
||||||
|
Condition[1].conditionValue.type = FWP_UINT64;
|
||||||
|
Condition[1].conditionValue.uint64 = &tapluid.Value;
|
||||||
|
|
||||||
|
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||||
|
CHECK_ERROR (err, "Add filter to permit IPv4 DNS traffic through TAP failed");
|
||||||
|
|
||||||
|
/* Sixth filter. Permit IPv6 DNS queries from TAP. */
|
||||||
|
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
||||||
|
|
||||||
|
err = FwpmFilterAdd0(*engine_handle, &Filter, NULL, &filterid);
|
||||||
|
CHECK_ERROR (err, "Add filter to permit IPv6 DNS traffic through TAP failed");
|
||||||
|
|
||||||
|
msg_handler (0, "Block_DNS: Added permit filters for TAP interface");
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
|
if (openvpnblob)
|
||||||
|
FwpmFreeMemory0 ((void **)&openvpnblob);
|
||||||
|
|
||||||
|
if (err && *engine_handle)
|
||||||
|
{
|
||||||
|
FwpmEngineClose0 (*engine_handle);
|
||||||
|
*engine_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
delete_block_dns_filters (HANDLE engine_handle)
|
||||||
|
{
|
||||||
|
DWORD err = 0;
|
||||||
|
/*
|
||||||
|
* For dynamic sessions closing the engine removes all filters added in the session
|
||||||
|
*/
|
||||||
|
if (engine_handle)
|
||||||
|
{
|
||||||
|
err = FwpmEngineClose0(engine_handle);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
40
src/openvpn/block_dns.h
Normal file
40
src/openvpn/block_dns.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* OpenVPN -- An application to securely tunnel IP networks
|
||||||
|
* over a single TCP/UDP port, with support for SSL/TLS-based
|
||||||
|
* session authentication and key exchange,
|
||||||
|
* packet encryption, packet authentication, and
|
||||||
|
* packet compression.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2016 Selva Nair <selva.nair@gmail.com>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2
|
||||||
|
* as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program (see the file COPYING included with this
|
||||||
|
* distribution); if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
#ifndef OPENVPN_BLOCK_DNS_H
|
||||||
|
#define OPENVPN_BLOCK_DNS_H
|
||||||
|
|
||||||
|
typedef void (*block_dns_msg_handler_t) (DWORD err, const char *msg);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
delete_block_dns_filters (HANDLE engine);
|
||||||
|
|
||||||
|
DWORD
|
||||||
|
add_block_dns_filters (HANDLE *engine, int iface_index, const WCHAR *exe_path,
|
||||||
|
block_dns_msg_handler_t msg_handler_callback);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif
|
@ -43,6 +43,7 @@
|
|||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
#include "win32.h"
|
#include "win32.h"
|
||||||
#include "misc.h"
|
#include "misc.h"
|
||||||
|
#include "openvpn-msg.h"
|
||||||
|
|
||||||
#include "memdbg.h"
|
#include "memdbg.h"
|
||||||
|
|
||||||
@ -52,70 +53,10 @@
|
|||||||
#include "compat-versionhelpers.h"
|
#include "compat-versionhelpers.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
#include "block_dns.h"
|
||||||
* WFP-related defines and GUIDs.
|
|
||||||
*/
|
|
||||||
#include <fwpmu.h>
|
|
||||||
#include <initguid.h>
|
|
||||||
#include <fwpmtypes.h>
|
|
||||||
#include <iphlpapi.h>
|
|
||||||
|
|
||||||
#ifndef FWPM_SESSION_FLAG_DYNAMIC
|
|
||||||
#define FWPM_SESSION_FLAG_DYNAMIC 0x00000001
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// c38d57d1-05a7-4c33-904f-7fbceee60e82
|
|
||||||
DEFINE_GUID(
|
|
||||||
FWPM_LAYER_ALE_AUTH_CONNECT_V4,
|
|
||||||
0xc38d57d1,
|
|
||||||
0x05a7,
|
|
||||||
0x4c33,
|
|
||||||
0x90, 0x4f, 0x7f, 0xbc, 0xee, 0xe6, 0x0e, 0x82
|
|
||||||
);
|
|
||||||
|
|
||||||
// 4a72393b-319f-44bc-84c3-ba54dcb3b6b4
|
|
||||||
DEFINE_GUID(
|
|
||||||
FWPM_LAYER_ALE_AUTH_CONNECT_V6,
|
|
||||||
0x4a72393b,
|
|
||||||
0x319f,
|
|
||||||
0x44bc,
|
|
||||||
0x84, 0xc3, 0xba, 0x54, 0xdc, 0xb3, 0xb6, 0xb4
|
|
||||||
);
|
|
||||||
|
|
||||||
// d78e1e87-8644-4ea5-9437-d809ecefc971
|
|
||||||
DEFINE_GUID(
|
|
||||||
FWPM_CONDITION_ALE_APP_ID,
|
|
||||||
0xd78e1e87,
|
|
||||||
0x8644,
|
|
||||||
0x4ea5,
|
|
||||||
0x94, 0x37, 0xd8, 0x09, 0xec, 0xef, 0xc9, 0x71
|
|
||||||
);
|
|
||||||
|
|
||||||
// c35a604d-d22b-4e1a-91b4-68f674ee674b
|
|
||||||
DEFINE_GUID(
|
|
||||||
FWPM_CONDITION_IP_REMOTE_PORT,
|
|
||||||
0xc35a604d,
|
|
||||||
0xd22b,
|
|
||||||
0x4e1a,
|
|
||||||
0x91, 0xb4, 0x68, 0xf6, 0x74, 0xee, 0x67, 0x4b
|
|
||||||
);
|
|
||||||
|
|
||||||
// 4cd62a49-59c3-4969-b7f3-bda5d32890a4
|
|
||||||
DEFINE_GUID(
|
|
||||||
FWPM_CONDITION_IP_LOCAL_INTERFACE,
|
|
||||||
0x4cd62a49,
|
|
||||||
0x59c3,
|
|
||||||
0x4969,
|
|
||||||
0xb7, 0xf3, 0xbd, 0xa5, 0xd3, 0x28, 0x90, 0xa4
|
|
||||||
);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* WFP firewall name.
|
* WFP handle
|
||||||
*/
|
|
||||||
WCHAR * FIREWALL_NAME = L"OpenVPN"; /* GLOBAL */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* WFP handle and GUID.
|
|
||||||
*/
|
*/
|
||||||
static HANDLE m_hEngineHandle = NULL; /* GLOBAL */
|
static HANDLE m_hEngineHandle = NULL; /* GLOBAL */
|
||||||
|
|
||||||
@ -1151,165 +1092,54 @@ win_get_tempdir()
|
|||||||
return tmpdir;
|
return tmpdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
static void
|
||||||
win_wfp_add_filter (HANDLE engineHandle,
|
block_dns_msg_handler (DWORD err, const char *msg)
|
||||||
const FWPM_FILTER0 *filter,
|
|
||||||
PSECURITY_DESCRIPTOR sd,
|
|
||||||
UINT64 *id)
|
|
||||||
{
|
{
|
||||||
if (FwpmFilterAdd0(engineHandle, filter, sd, id) != ERROR_SUCCESS)
|
struct gc_arena gc = gc_new ();
|
||||||
|
|
||||||
|
if (err == 0)
|
||||||
{
|
{
|
||||||
msg (M_NONFATAL, "Can't add WFP filter");
|
msg (M_INFO, "%s", msg);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
else
|
||||||
|
{
|
||||||
|
msg (M_WARN, "Error in add_block_dns_filters(): %s : %s [status=%lu]",
|
||||||
|
msg, strerror_win32 (err, &gc), err);
|
||||||
|
}
|
||||||
|
|
||||||
|
gc_free (&gc);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
win_wfp_block_dns (const NET_IFINDEX index)
|
win_wfp_block_dns (const NET_IFINDEX index)
|
||||||
{
|
{
|
||||||
FWPM_SESSION0 session = {0};
|
|
||||||
FWPM_SUBLAYER0 SubLayer = {0};
|
|
||||||
NET_LUID tapluid;
|
|
||||||
UINT64 filterid;
|
|
||||||
WCHAR openvpnpath[MAX_PATH];
|
WCHAR openvpnpath[MAX_PATH];
|
||||||
FWP_BYTE_BLOB *openvpnblob = NULL;
|
bool ret = false;
|
||||||
FWPM_FILTER0 Filter = {0};
|
DWORD status;
|
||||||
FWPM_FILTER_CONDITION0 Condition[2] = {0};
|
|
||||||
|
|
||||||
/* Add temporary filters which don't survive reboots or crashes. */
|
status = GetModuleFileNameW (NULL, openvpnpath, sizeof(openvpnpath));
|
||||||
session.flags = FWPM_SESSION_FLAG_DYNAMIC;
|
if (status == 0 || status == sizeof(openvpnpath))
|
||||||
|
|
||||||
dmsg (D_LOW, "Opening WFP engine");
|
|
||||||
|
|
||||||
if (FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &m_hEngineHandle) != ERROR_SUCCESS)
|
|
||||||
{
|
{
|
||||||
msg (M_NONFATAL, "Can't open WFP engine");
|
msg (M_WARN|M_ERRNO, "block_dns: cannot get executable path");
|
||||||
return false;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UuidCreate(&SubLayer.subLayerKey) != NO_ERROR)
|
status = add_block_dns_filters (&m_hEngineHandle, index, openvpnpath,
|
||||||
return false;
|
block_dns_msg_handler);
|
||||||
|
ret = (status == 0);
|
||||||
|
|
||||||
/* Populate packet filter layer information. */
|
out:
|
||||||
SubLayer.displayData.name = FIREWALL_NAME;
|
|
||||||
SubLayer.displayData.description = FIREWALL_NAME;
|
|
||||||
SubLayer.flags = 0;
|
|
||||||
SubLayer.weight = 0x100;
|
|
||||||
|
|
||||||
/* Add packet filter to our interface. */
|
return ret;
|
||||||
dmsg (D_LOW, "Adding WFP sublayer");
|
|
||||||
if (FwpmSubLayerAdd0(m_hEngineHandle, &SubLayer, NULL) != ERROR_SUCCESS)
|
|
||||||
{
|
|
||||||
msg (M_NONFATAL, "Can't add WFP sublayer");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
dmsg (D_LOW, "Blocking DNS using WFP");
|
|
||||||
if (ConvertInterfaceIndexToLuid(index, &tapluid) != NO_ERROR)
|
|
||||||
{
|
|
||||||
msg (M_NONFATAL, "Can't convert interface index to LUID");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
dmsg (D_LOW, "Tap Luid: %I64d", tapluid.Value);
|
|
||||||
|
|
||||||
/* Get OpenVPN path. */
|
|
||||||
GetModuleFileNameW(NULL, openvpnpath, MAX_PATH);
|
|
||||||
|
|
||||||
if (FwpmGetAppIdFromFileName0(openvpnpath, &openvpnblob) != ERROR_SUCCESS)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Prepare filter. */
|
|
||||||
Filter.subLayerKey = SubLayer.subLayerKey;
|
|
||||||
Filter.displayData.name = FIREWALL_NAME;
|
|
||||||
Filter.weight.type = FWP_UINT8;
|
|
||||||
Filter.weight.uint8 = 0xF;
|
|
||||||
Filter.filterCondition = Condition;
|
|
||||||
Filter.numFilterConditions = 2;
|
|
||||||
|
|
||||||
/* First filter. Permit IPv4 DNS queries from OpenVPN itself. */
|
|
||||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
|
||||||
Filter.action.type = FWP_ACTION_PERMIT;
|
|
||||||
|
|
||||||
Condition[0].fieldKey = FWPM_CONDITION_IP_REMOTE_PORT;
|
|
||||||
Condition[0].matchType = FWP_MATCH_EQUAL;
|
|
||||||
Condition[0].conditionValue.type = FWP_UINT16;
|
|
||||||
Condition[0].conditionValue.uint16 = 53;
|
|
||||||
|
|
||||||
Condition[1].fieldKey = FWPM_CONDITION_ALE_APP_ID;
|
|
||||||
Condition[1].matchType = FWP_MATCH_EQUAL;
|
|
||||||
Condition[1].conditionValue.type = FWP_BYTE_BLOB_TYPE;
|
|
||||||
Condition[1].conditionValue.byteBlob = openvpnblob;
|
|
||||||
|
|
||||||
/* Add filter condition to our interface. */
|
|
||||||
if (!win_wfp_add_filter(m_hEngineHandle, &Filter, NULL, &filterid))
|
|
||||||
goto err;
|
|
||||||
dmsg (D_LOW, "Filter (Permit OpenVPN IPv4 DNS) added with ID=%I64d", filterid);
|
|
||||||
|
|
||||||
/* Second filter. Permit IPv6 DNS queries from OpenVPN itself. */
|
|
||||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
|
||||||
|
|
||||||
/* Add filter condition to our interface. */
|
|
||||||
if (!win_wfp_add_filter(m_hEngineHandle, &Filter, NULL, &filterid))
|
|
||||||
goto err;
|
|
||||||
dmsg (D_LOW, "Filter (Permit OpenVPN IPv6 DNS) added with ID=%I64d", filterid);
|
|
||||||
|
|
||||||
/* Third filter. Block all IPv4 DNS queries. */
|
|
||||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
|
||||||
Filter.action.type = FWP_ACTION_BLOCK;
|
|
||||||
Filter.weight.type = FWP_EMPTY;
|
|
||||||
Filter.numFilterConditions = 1;
|
|
||||||
|
|
||||||
if (!win_wfp_add_filter(m_hEngineHandle, &Filter, NULL, &filterid))
|
|
||||||
goto err;
|
|
||||||
dmsg (D_LOW, "Filter (Block IPv4 DNS) added with ID=%I64d", filterid);
|
|
||||||
|
|
||||||
/* Forth filter. Block all IPv6 DNS queries. */
|
|
||||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
|
||||||
|
|
||||||
if (!win_wfp_add_filter(m_hEngineHandle, &Filter, NULL, &filterid))
|
|
||||||
goto err;
|
|
||||||
dmsg (D_LOW, "Filter (Block IPv6 DNS) added with ID=%I64d", filterid);
|
|
||||||
|
|
||||||
/* Fifth filter. Permit IPv4 DNS queries from TAP. */
|
|
||||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V4;
|
|
||||||
Filter.action.type = FWP_ACTION_PERMIT;
|
|
||||||
Filter.numFilterConditions = 2;
|
|
||||||
|
|
||||||
Condition[1].fieldKey = FWPM_CONDITION_IP_LOCAL_INTERFACE;
|
|
||||||
Condition[1].matchType = FWP_MATCH_EQUAL;
|
|
||||||
Condition[1].conditionValue.type = FWP_UINT64;
|
|
||||||
Condition[1].conditionValue.uint64 = &tapluid.Value;
|
|
||||||
|
|
||||||
/* Add filter condition to our interface. */
|
|
||||||
if (!win_wfp_add_filter(m_hEngineHandle, &Filter, NULL, &filterid))
|
|
||||||
goto err;
|
|
||||||
dmsg (D_LOW, "Filter (Permit IPv4 DNS queries from TAP) added with ID=%I64d", filterid);
|
|
||||||
|
|
||||||
/* Sixth filter. Permit IPv6 DNS queries from TAP. */
|
|
||||||
Filter.layerKey = FWPM_LAYER_ALE_AUTH_CONNECT_V6;
|
|
||||||
|
|
||||||
/* Add filter condition to our interface. */
|
|
||||||
if (!win_wfp_add_filter(m_hEngineHandle, &Filter, NULL, &filterid))
|
|
||||||
goto err;
|
|
||||||
dmsg (D_LOW, "Filter (Permit IPv6 DNS queries from TAP) added with ID=%I64d", filterid);
|
|
||||||
|
|
||||||
FwpmFreeMemory0((void **)&openvpnblob);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
err:
|
|
||||||
FwpmFreeMemory0((void **)&openvpnblob);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
win_wfp_uninit()
|
win_wfp_uninit()
|
||||||
{
|
{
|
||||||
dmsg (D_LOW, "Uninitializing WFP");
|
dmsg (D_LOW, "Uninitializing WFP");
|
||||||
if (m_hEngineHandle) {
|
|
||||||
FwpmEngineClose0(m_hEngineHandle);
|
delete_block_dns_filters (m_hEngineHandle);
|
||||||
m_hEngineHandle = NULL;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user