Beispiel #1
0
// NAT-T server IP address acquisition thread
void NatT_GetIpThread(THREAD *thread, void *param)
{
	UDP_ACCEL *a;
	char hostname[MAX_SIZE];
	static IP dummy_ip = {0};
	UINT num_retry = 0;
	// Validate arguments
	if (thread == NULL || param == NULL)
	{
		return;
	}

	a = (UDP_ACCEL *)param;

	if (IsZeroIP(&dummy_ip))
	{
		SetIP(&dummy_ip, 11, Rand8(), Rand8(), Rand8());
	}

	RUDPGetRegisterHostNameByIP(hostname, sizeof(hostname), &dummy_ip);

	while (a->NatT_Halt == false)
	{
		IP ip;
		UINT wait_time = UDP_NAT_T_GET_IP_INTERVAL;

		// Get the IP address
		bool ret = GetIP4Ex(&ip, hostname, 0, &a->NatT_Halt);

		if (ret && (IsZeroIp(&ip) == false))
		{
			char tmp[128];

			// Success to get
			Lock(a->NatT_Lock);
			{
				Copy(&a->NatT_IP, &ip, sizeof(IP));
			}
			Unlock(a->NatT_Lock);

			IPToStr(tmp, sizeof(tmp), &ip);
			Debug("NAT-T IP Address Resolved: %s = %s\n", hostname, tmp);

			a->NatT_IP_Changed = true;

			break;
		}

		// Fail to get
		num_retry++;

		wait_time = (UINT)(MIN((UINT64)UDP_NAT_T_GET_IP_INTERVAL * (UINT64)num_retry, (UINT64)UDP_NAT_T_GET_IP_INTERVAL_MAX));

		Wait(a->NatT_HaltEvent, wait_time);
	}
}
Beispiel #2
0
// Update the IP address list of the host
void IPsecWin7UpdateHostIPAddressList(IPSEC_WIN7 *w)
{
	LIST *o;
	UINT i;
	BUF *buf;
	UINT retsize;
	// Validate arguments
	if (w == NULL)
	{
		return;
	}

	o = GetHostIPAddressList();
	if (o == NULL)
	{
		return;
	}

	buf = NewBuf();

	for (i = 0;i < LIST_NUM(o);i++)
	{
		IP *ip = LIST_DATA(o, i);
		WFP_LOCAL_IP a;

		Zero(&a, sizeof(a));

		// Exclude any IPs or localhost IP
		if (IsZeroIP(ip) == false && IsLocalHostIP(ip) == false)
		{
			if (IsIP4(ip))
			{
				a.IpVersion = 4;
				Copy(a.IpAddress.IPv4Address, ip->addr, 4);
			}
			else
			{
				a.IpVersion = 6;
				Copy(a.IpAddress.IPv6Address, ip->ipv6_addr, 16);
			}

			WriteBuf(buf, &a, sizeof(WFP_LOCAL_IP));
		}
	}

	if (WriteFile(w->hDriverFile, buf->Buf, buf->Size, &retsize, NULL) == false)
	{
		Debug("WriteFile to the driver failed. %u\n", GetLastError());
	}

	FreeHostIPAddressList(o);

	FreeBuf(buf);
}
Beispiel #3
0
// Start tracking of the routing table
void RouteTrackingStart(SESSION *s)
{
	VLAN *v;
	ROUTE_TRACKING *t;
	UINT if_id = 0;
	ROUTE_ENTRY *e;
	ROUTE_ENTRY *dns = NULL;
	ROUTE_ENTRY *route_to_real_server_global = NULL;
	char tmp[64];
	UINT exclude_if_id = 0;
	bool already_exists = false;
	bool already_exists_by_other_account = false;
	IP eight;
	// Validate arguments
	if (s == NULL)
	{
		return;
	}

	v = (VLAN *)s->PacketAdapter->Param;
	if (v->RouteState != NULL)
	{
		return;
	}

	// Get the interface ID of the virtual LAN card
	if_id = GetInstanceId(v->InstanceName);
	Debug("[InstanceId of %s] = 0x%x\n", v->InstanceName, if_id);

	if (MsIsVista())
	{
		// The routing table by the virtual LAN card body should be
		// excluded explicitly in Windows Vista
		exclude_if_id = if_id;
	}

	// Get the route to the server
	e = GetBestRouteEntryEx(&s->ServerIP, exclude_if_id);
	if (e == NULL)
	{
		// Acquisition failure
		Debug("Failed to get GetBestRouteEntry().\n");
		return;
	}
	IPToStr(tmp, sizeof(tmp), &e->GatewayIP);
	Debug("GetBestRouteEntry() Succeed. [Gateway: %s]\n", tmp);

	// Add a route
	if (MsIsVista())
	{
		e->Metric = e->OldIfMetric;
	}
	if (AddRouteEntryEx(e, &already_exists) == false)
	{
		FreeRouteEntry(e);
		e = NULL;
	}
	Debug("already_exists: %u\n", already_exists);

	if (already_exists)
	{
		if (s->Cedar->Client != NULL && s->Account != NULL)
		{
			UINT i;
			ACCOUNT *a;
			for (i = 0;i < LIST_NUM(s->Cedar->Client->AccountList);i++)
			{
				a = LIST_DATA(s->Cedar->Client->AccountList, i);
				Lock(a->lock);
				{
					SESSION *sess = a->ClientSession;
					if (sess != NULL && sess != s)
					{
						VLAN *v = sess->PacketAdapter->Param;
						if (v != NULL)
						{
							ROUTE_TRACKING *tr = v->RouteState;
							if (tr != NULL && e != NULL)
							{
								if (Cmp(tr->RouteToServer, e, sizeof(ROUTE_ENTRY)) == 0)
								{
									already_exists_by_other_account = true;
								}
							}
						}
					}
				}
				Unlock(a->lock);
			}
		}

		if (already_exists_by_other_account)
		{
			Debug("already_exists_by_other_account = %u\n", already_exists_by_other_account);
			already_exists = false;
		}
	}

	// Get the routing table to the DNS server
	// (If the DNS server is this PC itself, there's no need to get)
	if (IsZeroIP(&s->DefaultDns) == false)
	{
		if (IsMyIPAddress(&s->DefaultDns) == false)
		{
			dns = GetBestRouteEntryEx(&s->DefaultDns, exclude_if_id);
			if (dns == NULL)
			{
				// Getting failure
				Debug("Failed to get GetBestRouteEntry DNS.\n");
			}
			else
			{
				// Add a route
				if (MsIsVista())
				{
					dns->Metric = dns->OldIfMetric;

					if (AddRouteEntry(dns) == false)
					{
						FreeRouteEntry(dns);
						dns = NULL;
					}
				}
			}
		}
	}

	if (s->IsAzureSession && IsZeroIP(&s->AzureRealServerGlobalIp) == false)
	{
		// Add also a static route to the real server in the case of via VPN Azure
		if (IsMyIPAddress(&s->AzureRealServerGlobalIp) == false)
		{
			route_to_real_server_global = GetBestRouteEntryEx(&s->AzureRealServerGlobalIp, exclude_if_id);

			if (route_to_real_server_global != NULL)
			{
				if (MsIsVista())
				{
					route_to_real_server_global->Metric = route_to_real_server_global->OldIfMetric;
				}

				if (AddRouteEntry(route_to_real_server_global) == false)
				{
					FreeRouteEntry(route_to_real_server_global);
					route_to_real_server_global = NULL;
				}
			}
		}
	}

	// Initialize
	if (s->Cedar->Client != NULL && s->Account != NULL)
	{
		Lock(s->Account->lock);
	}

	t = ZeroMalloc(sizeof(ROUTE_TRACKING));
	v->RouteState = t;

	t->RouteToServerAlreadyExists = already_exists;
	t->RouteToServer = e;
	t->RouteToDefaultDns = dns;
	t->RouteToRealServerGlobal = route_to_real_server_global;
	t->VLanInterfaceId = if_id;
	t->NextTrackingTime = 0;
	t->DeletedDefaultGateway = NewQueue();
	t->OldDefaultGatewayMetric = 0x7fffffff;

	if (s->Cedar->Client != NULL && s->Account != NULL)
	{
		Unlock(s->Account->lock);
	}

	// Get the route to 8.8.8.8
	SetIP(&eight, 8, 8, 8, 8);
	t->RouteToEight = GetBestRouteEntryEx(&eight, exclude_if_id);

	// Get the current default DNS server to detect network changes
	GetDefaultDns(&t->OldDnsServer);

	// Get as soon as releasing the IP address in the case of using DHCP
	if (IsNt())
	{
		char tmp[MAX_SIZE];
		MS_ADAPTER *a;

		Format(tmp, sizeof(tmp), VLAN_ADAPTER_NAME_TAG, v->InstanceName);
		a = MsGetAdapter(tmp);

		if (a != NULL)
		{
			if (a->UseDhcp)
			{
				bool ret = Win32ReleaseAddressByGuidEx(a->Guid, 100);
				Debug("*** Win32ReleaseAddressByGuidEx = %u\n", ret);

				ret = Win32RenewAddressByGuidEx(a->Guid, 100);
				Debug("*** Win32RenewAddressByGuidEx = %u\n", ret);
			}

			MsFreeAdapter(a);
		}
	}
	else
	{
		// For Win9x
		Win32RenewDhcp9x(if_id);
	}

	// Clear the DNS cache
	Win32FlushDnsCache();

	// Detect a change in the routing table (for only supported OS)
	t->RouteChange = NewRouteChange();
	Debug("t->RouteChange = 0x%p\n", t->RouteChange);
}
Beispiel #4
0
// Create a new UDP acceleration function
UDP_ACCEL *NewUdpAccel(CEDAR *cedar, IP *ip, bool client_mode, bool random_port, bool no_nat_t)
{
	UDP_ACCEL *a;
	SOCK *s;
	UINT max_udp_size;
	bool is_in_cedar_port_list = false;

	if (IsZeroIP(ip))
	{
		ip = NULL;
	}

	if (client_mode || random_port)
	{
		// Use a appropriate vacant port number in the case of using random port or client mode
		s = NewUDPEx3(0, ip);
	}
	else
	{
		// Specify in the range in the case of server mode
		UINT i;
		s = NULL;

		LockList(cedar->UdpPortList);
		{
			for (i = UDP_SERVER_PORT_LOWER;i <= UDP_SERVER_PORT_HIGHER;i++)
			{
				if (IsIntInList(cedar->UdpPortList, i) == false)
				{
					s = NewUDPEx3(i, ip);

					if (s != NULL)
					{
						is_in_cedar_port_list = true;
						break;
					}
				}
			}

			if (s == NULL)
			{
				// Leave the port selection to the OS because the available port is not found within the range
				s = NewUDPEx3(0, ip);
			}

			if (s != NULL && is_in_cedar_port_list)
			{
				AddIntDistinct(cedar->UdpPortList, i);
			}
		}
		UnlockList(cedar->UdpPortList);
	}

	if (s == NULL)
	{
		return NULL;
	}

	a = ZeroMalloc(sizeof(UDP_ACCEL));

	a->Cedar = cedar;
	AddRef(a->Cedar->ref);

	a->NoNatT = no_nat_t;


	a->NatT_TranId = Rand64();

	a->CreatedTick = Tick64();

	a->IsInCedarPortList = is_in_cedar_port_list;

	a->ClientMode = client_mode;

	a->Now = Tick64();
	a->UdpSock = s;
	Rand(a->MyKey, sizeof(a->MyKey));
	Rand(a->YourKey, sizeof(a->YourKey));

	Copy(&a->MyIp, ip, sizeof(IP));
	a->MyPort = s->LocalPort;

	a->IsIPv6 = IsIP6(ip);

	if (a->IsIPv6)
	{
		a->NoNatT = true;
	}

	a->RecvBlockQueue = NewQueue();

	Rand(a->NextIv, sizeof(a->NextIv));

	do
	{
		a->MyCookie = Rand32();
	}
	while (a->MyCookie == 0);

	do
	{
		a->YourCookie = Rand32();
	}
	while (a->MyCookie == 0 || a->MyCookie == a->YourCookie);

	// Calculate the maximum transmittable UDP packet size
	max_udp_size = MTU_FOR_PPPOE;

	if (a->IsIPv6 == false)
	{
		// IPv4
		max_udp_size -= 20;
	}
	else
	{
		// IPv6
		max_udp_size -= 40;
	}

	// UDP
	max_udp_size -= 8;

	a->MaxUdpPacketSize = max_udp_size;

	Debug("Udp Accel My Port = %u\n", a->MyPort);

	// Initialize the NAT-T server IP address acquisition thread
	a->NatT_Lock = NewLock();
	a->NatT_HaltEvent = NewEvent();

	if (a->NoNatT == false)
	{
		a->NatT_GetIpThread = NewThread(NatT_GetIpThread, a);
	}

	return a;
}
Beispiel #5
0
// Send
void UdpAccelSend(UDP_ACCEL *a, UCHAR *data, UINT data_size, bool compressed, UINT max_size, bool high_priority)
{
	UCHAR tmp[UDP_ACCELERATION_TMP_BUF_SIZE];
	UCHAR *buf;
	UINT size;
	UCHAR key[UDP_ACCELERATION_PACKET_KEY_SIZE];
	UINT64 ui64;
	USHORT us;
	UCHAR c;
	UINT current_size;
	UINT ui32;
	bool fatal_error = false;
	UINT r;
	// Validate arguments
	if (a == NULL || (data_size != 0 && data == NULL))
	{
		return;
	}
	if (max_size == 0)
	{
		max_size = INFINITE;
	}

	buf = tmp;
	size = 0;

	// IV
	if (a->PlainTextMode == false)
	{
		// IV
		Copy(buf, a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE);

		buf += UDP_ACCELERATION_PACKET_IV_SIZE;
		size += UDP_ACCELERATION_PACKET_IV_SIZE;

		// Calculate the key
		UdpAccelCalcKey(key, a->MyKey, a->NextIv);

		if (false)
		{
			char tmp1[256];
			char tmp2[256];
			char tmp3[256];
			BinToStr(tmp1, sizeof(tmp1), a->MyKey, sizeof(a->MyKey));
			BinToStr(tmp2, sizeof(tmp2), a->NextIv, UDP_ACCELERATION_PACKET_IV_SIZE);
			BinToStr(tmp3, sizeof(tmp3), key, sizeof(key));
			Debug("My Key  : %s\n"
				  "IV      : %s\n"
				  "Comm Key: %s\n",
				  tmp1, tmp2, tmp3);
		}
	}

	// Cookie
	ui32 = Endian32(a->YourCookie);
	Copy(buf, &ui32, sizeof(UINT));
	buf += sizeof(UINT);
	size += sizeof(UINT);

	// My Tick
	ui64 = Endian64(a->Now == 0 ? 1ULL : a->Now);
	Copy(buf, &ui64, sizeof(UINT64));
	buf += sizeof(UINT64);
	size += sizeof(UINT64);

	// Your Tick
	ui64 = Endian64(a->LastRecvYourTick);
	Copy(buf, &ui64, sizeof(UINT64));
	buf += sizeof(UINT64);
	size += sizeof(UINT64);

	// Size
	us = Endian16(data_size);
	Copy(buf, &us, sizeof(USHORT));
	buf += sizeof(USHORT);
	size += sizeof(USHORT);

	// Compress Flag
	c = (compressed ? 1 : 0);
	Copy(buf, &c, sizeof(UCHAR));
	buf += sizeof(UCHAR);
	size += sizeof(UCHAR);

	// Data
	if (data_size >= 1)
	{
		Copy(buf, data, data_size);
		buf += data_size;
		size += data_size;
	}

	if (a->PlainTextMode == false)
	{
		static UCHAR zero[UDP_ACCELERATION_PACKET_IV_SIZE] = {0};
		CRYPT *c;

		current_size = UDP_ACCELERATION_PACKET_IV_SIZE + sizeof(UINT) + sizeof(UINT64) * 2 +
			sizeof(USHORT) + sizeof(UCHAR) + data_size + UDP_ACCELERATION_PACKET_IV_SIZE;

		if (current_size < max_size)
		{
			// Padding
			UCHAR pad[UDP_ACCELERATION_MAX_PADDING_SIZE];
			UINT pad_size = MIN(max_size - current_size, UDP_ACCELERATION_MAX_PADDING_SIZE);
			pad_size = rand() % pad_size;

			Zero(pad, sizeof(pad));
			Copy(buf, pad, pad_size);
			buf += pad_size;
			size += pad_size;
		}

		// Verify
		Copy(buf, zero, UDP_ACCELERATION_PACKET_IV_SIZE);
		buf += UDP_ACCELERATION_PACKET_IV_SIZE;
		size += UDP_ACCELERATION_PACKET_IV_SIZE;

		// Encryption
		c = NewCrypt(key, UDP_ACCELERATION_PACKET_KEY_SIZE);
		Encrypt(c, tmp + UDP_ACCELERATION_PACKET_IV_SIZE, tmp + UDP_ACCELERATION_PACKET_IV_SIZE, size - UDP_ACCELERATION_PACKET_IV_SIZE);
		FreeCrypt(c);

		// Next Iv
		Copy(a->NextIv, buf - UDP_ACCELERATION_PACKET_IV_SIZE, UDP_ACCELERATION_PACKET_IV_SIZE);
	}

	// Send
	SetSockHighPriority(a->UdpSock, high_priority);

	r = SendTo(a->UdpSock, &a->YourIp, a->YourPort, tmp, size);
	if (r == 0 && a->UdpSock->IgnoreSendErr == false)
	{
		fatal_error = true;
		Debug("Error: SendTo: %r %u %u\n", &a->YourIp, a->YourPort, size);
		WHERE;
	}

	if (data_size == 0)
	{
		if (UdpAccelIsSendReady(a, true) == false)
		{
			if ((a->YourPortByNatTServer != 0) && (a->YourPort != a->YourPortByNatTServer))
			{
				r = SendTo(a->UdpSock, &a->YourIp, a->YourPortByNatTServer, tmp, size);
				if (r == 0 && a->UdpSock->IgnoreSendErr == false)
				{
					fatal_error = true;
					WHERE;
				}
			}
		}
	}

	if (data_size == 0)
	{
		if (IsZeroIP(&a->YourIp2) == false && CmpIpAddr(&a->YourIp, &a->YourIp2) != 0)
		{
			if (UdpAccelIsSendReady(a, true) == false)
			{
				// When the KeepAlive, if the opponent may be behind a NAT,
				// send the packet to the IP address of outside of the NAT
				r = SendTo(a->UdpSock, &a->YourIp2, a->YourPort, tmp, size);
				if (r == 0 && a->UdpSock->IgnoreSendErr == false)
				{
					fatal_error = true;
					WHERE;
				}

				if ((a->YourPortByNatTServer != 0) && (a->YourPort != a->YourPortByNatTServer))
				{
					r = SendTo(a->UdpSock, &a->YourIp2, a->YourPortByNatTServer, tmp, size);
					if (r == 0 && a->UdpSock->IgnoreSendErr == false)
					{
						fatal_error = true;
						WHERE;
					}
				}
			}
		}
	}

	if (fatal_error)
	{
		a->FatalError = true;
		WHERE;
	}

	//Debug("UDP Send: %u\n", size);
}