From 2692bb6b8e0efb21f2067fd003d285b061be6935 Mon Sep 17 00:00:00 2001 From: Davide Beatrici Date: Wed, 15 Aug 2018 02:39:33 +0200 Subject: [PATCH] Interop_OpenVPN: set "subnet" topology and remove workaround for "net30" topology on Win32 The workaround was required for the "net30" topology because: "There is a problem in your selection of --ifconfig endpoints [local=192.168.30.10, remote=192.168.30.1]. The local and remote VPN endpoints must exist within the same 255.255.255.252 subnet. This is a limitation of --dev tun when used with the TAP-WIN32 driver. Try 'openvpn --show-valid-subnets' option for more info." See https://community.openvpn.net/openvpn/wiki/Topology for detailed info. --- src/Cedar/IPsec_IPC.c | 134 +++--------------------------------- src/Cedar/IPsec_IPC.h | 3 - src/Cedar/Interop_OpenVPN.c | 45 +++--------- src/Cedar/Interop_OpenVPN.h | 1 - 4 files changed, 20 insertions(+), 163 deletions(-) diff --git a/src/Cedar/IPsec_IPC.c b/src/Cedar/IPsec_IPC.c index a37d5666..e855181d 100644 --- a/src/Cedar/IPsec_IPC.c +++ b/src/Cedar/IPsec_IPC.c @@ -223,13 +223,13 @@ void IPCAsyncThreadProc(THREAD *thread, void *param) Zero(&cao, sizeof(cao)); // Get an IP address from the DHCP server in the case of L3 mode - Debug("IPCDhcpAllocateIPEx() start...\n"); - if (IPCDhcpAllocateIPEx(a->Ipc, &cao, a->TubeForDisconnect, a->Param.IsOpenVPN)) + Debug("IPCDhcpAllocateIP() start...\n"); + if (IPCDhcpAllocateIP(a->Ipc, &cao, a->TubeForDisconnect)) { UINT t; IP ip, subnet, gw; - Debug("IPCDhcpAllocateIPEx() Ok.\n"); + Debug("IPCDhcpAllocateIP() Ok.\n"); // Calculate the DHCP update interval t = cao.LeaseTime; @@ -260,7 +260,7 @@ void IPCAsyncThreadProc(THREAD *thread, void *param) } else { - Debug("IPCDhcpAllocateIPEx() Error.\n"); + Debug("IPCDhcpAllocateIP() Error.\n"); a->DhcpAllocFailed = true; @@ -791,39 +791,20 @@ bool IPCDhcpRequestInformIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_t // Make a request for IP addresses using DHCP bool IPCDhcpAllocateIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube) -{ - return IPCDhcpAllocateIPEx(ipc, opt, discon_poll_tube, false); -} -bool IPCDhcpAllocateIPEx(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube, bool openvpn_compatible) { DHCP_OPTION_LIST req; DHCPV4_DATA *d, *d2; UINT tran_id = Rand32(); bool ok; - UINT request_ip = 0; - IP current_scanning_ip; - UCHAR current_scanning_addr8; - UCHAR begin_scanning_addr8; - UINT64 giveup = Tick64() + (UINT64)IPC_DHCP_TIMEOUT_TOTAL_GIVEUP; - LIST *release_list; - bool ret = false; // Validate arguments if (ipc == NULL || opt == NULL) { return false; } - release_list = NewListFast(NULL); - - Zero(¤t_scanning_ip, sizeof(current_scanning_ip)); - current_scanning_addr8 = 0; - begin_scanning_addr8 = 0; - -LABEL_RETRY_FOR_OPENVPN: - tran_id = Rand32(); // Send a DHCP Discover Zero(&req, sizeof(req)); - req.RequestedIp = request_ip; + req.RequestedIp = 0; req.Opcode = DHCP_DISCOVER; StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname); IPCDhcpSetConditionalUserClass(ipc, &req); @@ -831,7 +812,7 @@ LABEL_RETRY_FOR_OPENVPN: d = IPCSendDhcpRequest(ipc, NULL, tran_id, &req, DHCP_OFFER, IPC_DHCP_TIMEOUT, discon_poll_tube); if (d == NULL) { - goto LABEL_CLEANUP; + return false; } // Analyze the DHCP Offer @@ -860,75 +841,7 @@ LABEL_RETRY_FOR_OPENVPN: if (ok == false) { FreeDHCPv4Data(d); - goto LABEL_CLEANUP; - } - - if (openvpn_compatible) - { - UINT ip = d->ParsedOptionList->ClientAddress; - - if (OvsIsCompatibleL3IP(ip) == false) - { - char tmp[64]; - - DHCP_OPTION_LIST req; - IPC_DHCP_RELEASE_QUEUE *q; - - // If the offered IP address is not used, place the address - // in release memo list to release at the end of this function - Zero(&req, sizeof(req)); - req.Opcode = DHCP_RELEASE; - req.ServerAddress = d->ParsedOptionList->ServerAddress; - - q = ZeroMalloc(sizeof(IPC_DHCP_RELEASE_QUEUE)); - Copy(&q->Req, &req, sizeof(DHCP_OPTION_LIST)); - q->TranId = tran_id; - Copy(q->MacAddress, ipc->MacAddress, 6); - - Add(release_list, q); - - FreeDHCPv4Data(d); - - if (Tick64() >= giveup) - { - goto LABEL_CLEANUP; - } - - if (IsZero(¤t_scanning_ip, sizeof(IP))) - { - UINTToIP(¤t_scanning_ip, ip); - current_scanning_addr8 = current_scanning_ip.addr[3]; - - if ((current_scanning_addr8 % 4) != 1) - { - current_scanning_addr8 = (UCHAR)(((((UINT)current_scanning_addr8 - 1) / 4) + 1) * 4 + 1); - } - - begin_scanning_addr8 = current_scanning_addr8; - } - else - { - current_scanning_addr8 += 4; - - if (current_scanning_addr8 == begin_scanning_addr8) - { - goto LABEL_CLEANUP; - } - } - - current_scanning_ip.addr[3] = current_scanning_addr8; - - request_ip = IPToUINT(¤t_scanning_ip); - - IPToStr32(tmp, sizeof(tmp), request_ip); - - // Generate another MAC address - ipc->MacAddress[5]++; - - Debug("Trying Allocating IP for OpenVPN: %s\n", tmp); - - goto LABEL_RETRY_FOR_OPENVPN; - } + return false; } // Send a DHCP Request @@ -943,7 +856,7 @@ LABEL_RETRY_FOR_OPENVPN: if (d2 == NULL) { FreeDHCPv4Data(d); - goto LABEL_CLEANUP; + return false; } // Analyze the DHCP Ack @@ -973,7 +886,7 @@ LABEL_RETRY_FOR_OPENVPN: { FreeDHCPv4Data(d); FreeDHCPv4Data(d2); - goto LABEL_CLEANUP; + return false; } Copy(opt, d2->ParsedOptionList, sizeof(DHCP_OPTION_LIST)); @@ -981,34 +894,7 @@ LABEL_RETRY_FOR_OPENVPN: FreeDHCPv4Data(d); FreeDHCPv4Data(d2); - ret = true; - -LABEL_CLEANUP: - if (release_list != NULL) - { - // Release the IP address that was acquired from the DHCP server to no avail on the way - UINT i; - UCHAR mac_backup[6]; - - Copy(mac_backup, ipc->MacAddress, 6); - - for (i = 0;i < LIST_NUM(release_list);i++) - { - IPC_DHCP_RELEASE_QUEUE *q = LIST_DATA(release_list, i); - - Copy(ipc->MacAddress, q->MacAddress, 6); - FreeDHCPv4Data(IPCSendDhcpRequest(ipc, NULL, q->TranId, &q->Req, 0, 0, NULL)); - - IPCProcessInterrupts(ipc); - - Free(q); - } - - Copy(ipc->MacAddress, mac_backup, 6); - - ReleaseList(release_list); - } - return ret; + return true; } // Send out a DHCP request, and wait for a corresponding response diff --git a/src/Cedar/IPsec_IPC.h b/src/Cedar/IPsec_IPC.h index a4854e65..84dcface 100644 --- a/src/Cedar/IPsec_IPC.h +++ b/src/Cedar/IPsec_IPC.h @@ -118,7 +118,6 @@ #define IPC_ARP_LIFETIME (3 * 60 * 1000) #define IPC_ARP_GIVEUPTIME (1 * 1000) #define IPC_DHCP_TIMEOUT (5 * 1000) -#define IPC_DHCP_TIMEOUT_TOTAL_GIVEUP (20 * 1000) #define IPC_DHCP_MIN_LEASE 5 #define IPC_DHCP_DEFAULT_LEASE 3600 @@ -164,7 +163,6 @@ struct IPC_PARAM bool BridgeMode; UINT Mss; bool IsL3Mode; - bool IsOpenVPN; X *ClientCertificate; }; @@ -256,7 +254,6 @@ DHCPV4_DATA *IPCSendDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION BUF *IPCBuildDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt); BUF *IPCBuildDhcpRequestOptions(IPC *ipc, DHCP_OPTION_LIST *opt); bool IPCDhcpAllocateIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube); -bool IPCDhcpAllocateIPEx(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube, bool openvpn_compatible); bool IPCDhcpRequestInformIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube, IP *client_ip); void IPCDhcpRenewIP(IPC *ipc, IP *dhcp_server); void IPCDhcpFreeIP(IPC *ipc, IP *dhcp_server); diff --git a/src/Cedar/Interop_OpenVPN.c b/src/Cedar/Interop_OpenVPN.c index 82db618c..854e1ba0 100644 --- a/src/Cedar/Interop_OpenVPN.c +++ b/src/Cedar/Interop_OpenVPN.c @@ -720,8 +720,6 @@ void OvsBeginIPCAsyncConnectionIfEmpty(OPENVPN_SERVER *s, OPENVPN_SESSION *se, O p.ClientCertificate = c->ClientCert.X; } - p.IsOpenVPN = true; - // Calculate the MSS p.Mss = OvsCalcTcpMss(s, se, c); Debug("MSS=%u\n", p.Mss); @@ -1984,9 +1982,6 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol) // if the L3 mode to the option character string DHCP_OPTION_LIST *cao = &se->IpcAsync->L3ClientAddressOption; char ip_client[64]; - char ip_tunnel_endpoint[64]; - UINT ip_tunnel_endpoint_32; - char ip_network[64]; char ip_subnet_mask[64]; char ip_dns1[64]; char ip_dns2[64]; @@ -2003,25 +1998,17 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol) IPToStr32(ip_client, sizeof(ip_client), cao->ClientAddress); - // Generate a virtual gateway address to be passed to the OpenVPN - ip_tunnel_endpoint_32 = Endian32(cao->ClientAddress); - ip_tunnel_endpoint_32++; - ip_tunnel_endpoint_32 = Endian32(ip_tunnel_endpoint_32); - IPToStr32(ip_tunnel_endpoint, sizeof(ip_tunnel_endpoint), ip_tunnel_endpoint_32); - - // Create a subnet information for the LAN - IPToStr32(ip_network, sizeof(ip_network), - GetNetworkAddress(cao->ClientAddress, - cao->SubnetMask)); - IPToStr32(ip_subnet_mask, sizeof(ip_subnet_mask), cao->SubnetMask); + Format(l3_options, sizeof(l3_options), + ",topology subnet"); + StrCat(option_str, sizeof(option_str), l3_options); + Format(l3_options, sizeof(l3_options), ",ifconfig %s %s", -// ",ifconfig %s %s,route %s %s %s 1", - ip_client, ip_tunnel_endpoint, ip_network, ip_subnet_mask, - ip_tunnel_endpoint); + ip_client, + ip_subnet_mask); StrCat(option_str, sizeof(option_str), l3_options); // Domain name @@ -2083,11 +2070,13 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol) // Default gateway if (cao->Gateway != 0) { + char ip_str[64]; + IPToStr32(ip_str, sizeof(ip_str), cao->Gateway); Format(l3_options, sizeof(l3_options), - ",route-gateway %s,redirect-gateway def1", ip_tunnel_endpoint); + ",route-gateway %s,redirect-gateway def1", ip_str); StrCat(option_str, sizeof(option_str), l3_options); - IPToStr32(ip_defgw, sizeof(ip_defgw), cao->Gateway); + StrCpy(ip_defgw, sizeof(ip_defgw), ip_str); } else { @@ -2542,20 +2531,6 @@ int OvsCompareSessionList(void *p1, void *p2) return 0; } -// Identify whether the IP address is compatible to the tun device of OpenVPN -bool OvsIsCompatibleL3IP(UINT ip) -{ - IP p; - - UINTToIP(&p, ip); - if ((p.addr[3] % 4) == 1) - { - return true; - } - - return false; -} - // Create a new OpenVPN server OPENVPN_SERVER *NewOpenVpnServer(CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOCK_EVENT *sock_event) { diff --git a/src/Cedar/Interop_OpenVPN.h b/src/Cedar/Interop_OpenVPN.h index 8e3c84d8..9899c0a0 100644 --- a/src/Cedar/Interop_OpenVPN.h +++ b/src/Cedar/Interop_OpenVPN.h @@ -364,7 +364,6 @@ void OvsFreeList(LIST *o); bool OvsHasEntry(LIST *o, char *key); UINT OvsPeekStringFromFifo(FIFO *f, char *str, UINT str_size); void OvsBeginIPCAsyncConnectionIfEmpty(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c); -bool OvsIsCompatibleL3IP(UINT ip); UINT OvsCalcTcpMss(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c); CIPHER *OvsGetCipher(char *name);