1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-11-26 19:39:53 +03:00

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.
This commit is contained in:
Davide Beatrici 2018-08-15 02:39:33 +02:00
parent 88424e2522
commit 2692bb6b8e
4 changed files with 20 additions and 163 deletions

View File

@ -223,13 +223,13 @@ void IPCAsyncThreadProc(THREAD *thread, void *param)
Zero(&cao, sizeof(cao)); Zero(&cao, sizeof(cao));
// Get an IP address from the DHCP server in the case of L3 mode // Get an IP address from the DHCP server in the case of L3 mode
Debug("IPCDhcpAllocateIPEx() start...\n"); Debug("IPCDhcpAllocateIP() start...\n");
if (IPCDhcpAllocateIPEx(a->Ipc, &cao, a->TubeForDisconnect, a->Param.IsOpenVPN)) if (IPCDhcpAllocateIP(a->Ipc, &cao, a->TubeForDisconnect))
{ {
UINT t; UINT t;
IP ip, subnet, gw; IP ip, subnet, gw;
Debug("IPCDhcpAllocateIPEx() Ok.\n"); Debug("IPCDhcpAllocateIP() Ok.\n");
// Calculate the DHCP update interval // Calculate the DHCP update interval
t = cao.LeaseTime; t = cao.LeaseTime;
@ -260,7 +260,7 @@ void IPCAsyncThreadProc(THREAD *thread, void *param)
} }
else else
{ {
Debug("IPCDhcpAllocateIPEx() Error.\n"); Debug("IPCDhcpAllocateIP() Error.\n");
a->DhcpAllocFailed = true; 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 // Make a request for IP addresses using DHCP
bool IPCDhcpAllocateIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube) 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; DHCP_OPTION_LIST req;
DHCPV4_DATA *d, *d2; DHCPV4_DATA *d, *d2;
UINT tran_id = Rand32(); UINT tran_id = Rand32();
bool ok; 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 // Validate arguments
if (ipc == NULL || opt == NULL) if (ipc == NULL || opt == NULL)
{ {
return false; return false;
} }
release_list = NewListFast(NULL);
Zero(&current_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 // Send a DHCP Discover
Zero(&req, sizeof(req)); Zero(&req, sizeof(req));
req.RequestedIp = request_ip; req.RequestedIp = 0;
req.Opcode = DHCP_DISCOVER; req.Opcode = DHCP_DISCOVER;
StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname); StrCpy(req.Hostname, sizeof(req.Hostname), ipc->ClientHostname);
IPCDhcpSetConditionalUserClass(ipc, &req); 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); d = IPCSendDhcpRequest(ipc, NULL, tran_id, &req, DHCP_OFFER, IPC_DHCP_TIMEOUT, discon_poll_tube);
if (d == NULL) if (d == NULL)
{ {
goto LABEL_CLEANUP; return false;
} }
// Analyze the DHCP Offer // Analyze the DHCP Offer
@ -860,75 +841,7 @@ LABEL_RETRY_FOR_OPENVPN:
if (ok == false) if (ok == false)
{ {
FreeDHCPv4Data(d); FreeDHCPv4Data(d);
goto LABEL_CLEANUP; return false;
}
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(&current_scanning_ip, sizeof(IP)))
{
UINTToIP(&current_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(&current_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;
}
} }
// Send a DHCP Request // Send a DHCP Request
@ -943,7 +856,7 @@ LABEL_RETRY_FOR_OPENVPN:
if (d2 == NULL) if (d2 == NULL)
{ {
FreeDHCPv4Data(d); FreeDHCPv4Data(d);
goto LABEL_CLEANUP; return false;
} }
// Analyze the DHCP Ack // Analyze the DHCP Ack
@ -973,7 +886,7 @@ LABEL_RETRY_FOR_OPENVPN:
{ {
FreeDHCPv4Data(d); FreeDHCPv4Data(d);
FreeDHCPv4Data(d2); FreeDHCPv4Data(d2);
goto LABEL_CLEANUP; return false;
} }
Copy(opt, d2->ParsedOptionList, sizeof(DHCP_OPTION_LIST)); Copy(opt, d2->ParsedOptionList, sizeof(DHCP_OPTION_LIST));
@ -981,34 +894,7 @@ LABEL_RETRY_FOR_OPENVPN:
FreeDHCPv4Data(d); FreeDHCPv4Data(d);
FreeDHCPv4Data(d2); FreeDHCPv4Data(d2);
ret = true; return 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;
} }
// Send out a DHCP request, and wait for a corresponding response // Send out a DHCP request, and wait for a corresponding response

View File

@ -118,7 +118,6 @@
#define IPC_ARP_LIFETIME (3 * 60 * 1000) #define IPC_ARP_LIFETIME (3 * 60 * 1000)
#define IPC_ARP_GIVEUPTIME (1 * 1000) #define IPC_ARP_GIVEUPTIME (1 * 1000)
#define IPC_DHCP_TIMEOUT (5 * 1000) #define IPC_DHCP_TIMEOUT (5 * 1000)
#define IPC_DHCP_TIMEOUT_TOTAL_GIVEUP (20 * 1000)
#define IPC_DHCP_MIN_LEASE 5 #define IPC_DHCP_MIN_LEASE 5
#define IPC_DHCP_DEFAULT_LEASE 3600 #define IPC_DHCP_DEFAULT_LEASE 3600
@ -164,7 +163,6 @@ struct IPC_PARAM
bool BridgeMode; bool BridgeMode;
UINT Mss; UINT Mss;
bool IsL3Mode; bool IsL3Mode;
bool IsOpenVPN;
X *ClientCertificate; 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 *IPCBuildDhcpRequest(IPC *ipc, IP *dest_ip, UINT tran_id, DHCP_OPTION_LIST *opt);
BUF *IPCBuildDhcpRequestOptions(IPC *ipc, 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 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); bool IPCDhcpRequestInformIP(IPC *ipc, DHCP_OPTION_LIST *opt, TUBE *discon_poll_tube, IP *client_ip);
void IPCDhcpRenewIP(IPC *ipc, IP *dhcp_server); void IPCDhcpRenewIP(IPC *ipc, IP *dhcp_server);
void IPCDhcpFreeIP(IPC *ipc, IP *dhcp_server); void IPCDhcpFreeIP(IPC *ipc, IP *dhcp_server);

View File

@ -720,8 +720,6 @@ void OvsBeginIPCAsyncConnectionIfEmpty(OPENVPN_SERVER *s, OPENVPN_SESSION *se, O
p.ClientCertificate = c->ClientCert.X; p.ClientCertificate = c->ClientCert.X;
} }
p.IsOpenVPN = true;
// Calculate the MSS // Calculate the MSS
p.Mss = OvsCalcTcpMss(s, se, c); p.Mss = OvsCalcTcpMss(s, se, c);
Debug("MSS=%u\n", p.Mss); 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 // if the L3 mode to the option character string
DHCP_OPTION_LIST *cao = &se->IpcAsync->L3ClientAddressOption; DHCP_OPTION_LIST *cao = &se->IpcAsync->L3ClientAddressOption;
char ip_client[64]; 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_subnet_mask[64];
char ip_dns1[64]; char ip_dns1[64];
char ip_dns2[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), IPToStr32(ip_client, sizeof(ip_client),
cao->ClientAddress); 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), IPToStr32(ip_subnet_mask, sizeof(ip_subnet_mask),
cao->SubnetMask); cao->SubnetMask);
Format(l3_options, sizeof(l3_options),
",topology subnet");
StrCat(option_str, sizeof(option_str), l3_options);
Format(l3_options, sizeof(l3_options), Format(l3_options, sizeof(l3_options),
",ifconfig %s %s", ",ifconfig %s %s",
// ",ifconfig %s %s,route %s %s %s 1", ip_client,
ip_client, ip_tunnel_endpoint, ip_network, ip_subnet_mask, ip_subnet_mask);
ip_tunnel_endpoint);
StrCat(option_str, sizeof(option_str), l3_options); StrCat(option_str, sizeof(option_str), l3_options);
// Domain name // Domain name
@ -2083,11 +2070,13 @@ void OvsRecvPacket(OPENVPN_SERVER *s, LIST *recv_packet_list, UINT protocol)
// Default gateway // Default gateway
if (cao->Gateway != 0) if (cao->Gateway != 0)
{ {
char ip_str[64];
IPToStr32(ip_str, sizeof(ip_str), cao->Gateway);
Format(l3_options, sizeof(l3_options), 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); 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 else
{ {
@ -2542,20 +2531,6 @@ int OvsCompareSessionList(void *p1, void *p2)
return 0; 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 // Create a new OpenVPN server
OPENVPN_SERVER *NewOpenVpnServer(CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOCK_EVENT *sock_event) OPENVPN_SERVER *NewOpenVpnServer(CEDAR *cedar, INTERRUPT_MANAGER *interrupt, SOCK_EVENT *sock_event)
{ {

View File

@ -364,7 +364,6 @@ void OvsFreeList(LIST *o);
bool OvsHasEntry(LIST *o, char *key); bool OvsHasEntry(LIST *o, char *key);
UINT OvsPeekStringFromFifo(FIFO *f, char *str, UINT str_size); UINT OvsPeekStringFromFifo(FIFO *f, char *str, UINT str_size);
void OvsBeginIPCAsyncConnectionIfEmpty(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c); 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); UINT OvsCalcTcpMss(OPENVPN_SERVER *s, OPENVPN_SESSION *se, OPENVPN_CHANNEL *c);
CIPHER *OvsGetCipher(char *name); CIPHER *OvsGetCipher(char *name);