Compare commits
4 Commits
00f72e1a64
...
e1118ccafe
| Author | SHA1 | Date | |
|---|---|---|---|
| e1118ccafe | |||
| ccbacd1180 | |||
| cf3ec30492 | |||
| 1d34953f25 |
@@ -36,6 +36,12 @@
|
|||||||
#include <locale>
|
#include <locale>
|
||||||
#include <codecvt>
|
#include <codecvt>
|
||||||
#include <wintun/wintun.h>
|
#include <wintun/wintun.h>
|
||||||
|
|
||||||
|
#include <iphlpapi.h>
|
||||||
|
#include <netioapi.h>
|
||||||
|
|
||||||
|
#pragma comment(lib, "iphlpapi.lib")
|
||||||
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ColumnLynx::Net {
|
namespace ColumnLynx::Net {
|
||||||
|
|||||||
@@ -433,41 +433,66 @@ namespace ColumnLynx::Net {
|
|||||||
uint16_t mtu)
|
uint16_t mtu)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
std::string ip = ipv4ToString(clientIP);
|
// Interface alias → LUID → Index
|
||||||
std::string gw = ipv4ToString(serverIP);
|
std::wstring ifAlias(mIfName.begin(), mIfName.end());
|
||||||
std::string mask;
|
|
||||||
|
|
||||||
// Convert prefixLen → subnet mask
|
NET_LUID luid;
|
||||||
uint32_t maskInt = (prefixLen == 0) ? 0 : (0xFFFFFFFF << (32 - prefixLen));
|
if (ConvertInterfaceAliasToLuid(ifAlias.c_str(), &luid) != NO_ERROR)
|
||||||
mask = ipv4ToString(maskInt);
|
return false;
|
||||||
|
|
||||||
// Calculate network address from IP and mask
|
NET_IFINDEX ifIndex;
|
||||||
uint32_t networkInt = (clientIP & maskInt);
|
if (ConvertInterfaceLuidToIndex(&luid, &ifIndex) != NO_ERROR)
|
||||||
std::string network = ipv4ToString(networkInt);
|
return false;
|
||||||
|
|
||||||
char cmd[512];
|
// ssign IPv4 address + prefix
|
||||||
|
MIB_UNICASTIPADDRESS_ROW addr;
|
||||||
|
InitializeUnicastIpAddressEntry(&addr);
|
||||||
|
|
||||||
// 1. Set the static IP + mask + gateway
|
addr.InterfaceIndex = ifIndex;
|
||||||
snprintf(cmd, sizeof(cmd),
|
addr.Address.si_family = AF_INET;
|
||||||
"netsh interface ip set address name=\"%s\" static %s %s %s",
|
addr.Address.Ipv4.sin_addr.s_addr = htonl(clientIP);
|
||||||
mIfName.c_str(), ip.c_str(), mask.c_str(), gw.c_str()
|
addr.OnLinkPrefixLength = prefixLen;
|
||||||
);
|
addr.DadState = IpDadStatePreferred;
|
||||||
system(cmd);
|
|
||||||
|
|
||||||
// 2. Set MTU (separate command)
|
if (CreateUnicastIpAddressEntry(&addr) != NO_ERROR)
|
||||||
snprintf(cmd, sizeof(cmd),
|
return false;
|
||||||
"netsh interface ipv4 set subinterface \"%s\" mtu=%u store=persistent",
|
|
||||||
mIfName.c_str(), mtu
|
|
||||||
);
|
|
||||||
system(cmd);
|
|
||||||
|
|
||||||
// 3. Add route for the VPN network to go through the TUN interface
|
// Set MTU
|
||||||
// This is critical: tells Windows to send packets destined for the server/network through the TUN interface
|
MIB_IFROW ifRow;
|
||||||
snprintf(cmd, sizeof(cmd),
|
ifRow.dwIndex = ifIndex;
|
||||||
"netsh routing ip add persistentroute dest=%s/%d name=\"%s\" nexthopcfg=%s",
|
|
||||||
network.c_str(), prefixLen, mIfName.c_str(), gw.c_str()
|
if (GetIfEntry(&ifRow) != NO_ERROR)
|
||||||
);
|
return false;
|
||||||
system(cmd);
|
|
||||||
|
ifRow.dwMtu = mtu;
|
||||||
|
|
||||||
|
if (SetIfEntry(&ifRow) != NO_ERROR)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Add persistent route for VPN network via this interface
|
||||||
|
uint32_t mask =
|
||||||
|
(prefixLen == 0) ? 0 : (0xFFFFFFFFu << (32 - prefixLen));
|
||||||
|
uint32_t network = clientIP & mask;
|
||||||
|
|
||||||
|
MIB_IPFORWARD_ROW2 route;
|
||||||
|
InitializeIpForwardEntry(&route);
|
||||||
|
|
||||||
|
route.InterfaceIndex = ifIndex;
|
||||||
|
route.DestinationPrefix.Prefix.si_family = AF_INET;
|
||||||
|
route.DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr = htonl(network);
|
||||||
|
route.DestinationPrefix.PrefixLength = prefixLen;
|
||||||
|
|
||||||
|
route.NextHop.si_family = AF_INET;
|
||||||
|
route.NextHop.Ipv4.sin_addr.s_addr = 0;
|
||||||
|
|
||||||
|
route.Metric = 1;
|
||||||
|
route.Protocol = static_cast<NL_ROUTE_PROTOCOL>(MIB_IPPROTO_NETMGMT);
|
||||||
|
route.ValidLifetime = 0xFFFFFFFF;
|
||||||
|
route.PreferredLifetime = 0xFFFFFFFF;
|
||||||
|
|
||||||
|
DWORD r = CreateIpForwardEntry2(&route);
|
||||||
|
if (r != NO_ERROR && r != ERROR_OBJECT_ALREADY_EXISTS)
|
||||||
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
|
|||||||
Reference in New Issue
Block a user