Simplify tun configuration

This commit is contained in:
Ludvig Strigeus 2018-10-23 00:48:20 +02:00
parent 335133fa8f
commit a7776ab7c4
10 changed files with 359 additions and 347 deletions

View file

@ -37,18 +37,6 @@ void *IpToPeerMap::LookupV4(uint32 ip) {
return ipv4_.Lookup(ip);
}
void *IpToPeerMap::LookupV4DefaultPeer() {
return ipv4_.LookupExact(0, 0);
}
void *IpToPeerMap::LookupV6DefaultPeer() {
for (auto it = ipv6_.begin(); it != ipv6_.end(); ++it) {
if (it->cidr_len == 0)
return it->peer;
}
return NULL;
}
void IpToPeerMap::RemoveV4(uint32 ip, int cidr) {
ipv4_.Delete(ip, cidr);
}

View file

@ -50,9 +50,6 @@ public:
void *LookupV4(uint32 ip);
void *LookupV6(const void *addr);
void *LookupV4DefaultPeer();
void *LookupV6DefaultPeer();
void RemoveV4(uint32 ip, int cidr);
void RemoveV6(const void *addr, int cidr);
private:

View file

@ -63,43 +63,26 @@ public:
};
struct TunConfig {
// IP address and netmask of the tun device
in_addr_t ip;
uint8 cidr;
bool block_dns_on_adapters;
// no, yes(firewall), yes(route), yes(both), 255(default)
uint8 internet_blocking;
// Set this to configure a default route for ipv4
bool use_ipv4_default_route;
bool block_dns_on_adapters;
// Set this to configure a default route for ipv6
bool use_ipv6_default_route;
// This holds the address of the vpn endpoint, so those get routed to the old iface.
uint32 default_route_endpoint_v4;
// Set mtu
int mtu;
// Set ipv6 address?
uint8 ipv6_address[16];
uint8 ipv6_cidr;
// The ipv6 and ipv4 addresses
std::vector<WgCidrAddr> addresses;
// Set this to configure DNS server for ipv4,ipv6
std::vector<IpAddr> ipv4_dns;
std::vector<IpAddr> ipv6_dns;
// This holds the address of the vpn endpoint, so those get routed to the old iface.
uint8 default_route_endpoint_v6[16];
// Set this to configure DNS server
std::vector<IpAddr> dns;
// This holds all cidr addresses to add as additional routing entries
std::vector<WgCidrAddr> extra_routes;
std::vector<WgCidrAddr> included_routes;
// This holds all the ips to exclude
std::vector<WgCidrAddr> excluded_ips;
std::vector<WgCidrAddr> excluded_routes;
// This holds the pre/post commands
PrePostCommands pre_post_commands;

View file

@ -372,29 +372,6 @@ static uint32 CidrToNetmaskV4(int cidr) {
return cidr == 32 ? 0xffffffff : 0xffffffff << (32 - cidr);
}
static uint32 ComputeIpv4DefaultRoute(uint32 ip, uint32 netmask) {
uint32 default_route_v4 = (ip & netmask) | 1;
if (default_route_v4 == ip)
default_route_v4++;
return default_route_v4;
}
static void ComputeIpv6DefaultRoute(const uint8 *ipv6_address, uint8 ipv6_cidr, uint8 *default_route_v6) {
memcpy(default_route_v6, ipv6_address, 16);
// clear the last bits of the ipv6 address to match the cidr.
size_t n = (ipv6_cidr + 7) >> 3;
memset(&default_route_v6[n], 0, 16 - n);
if (n == 0)
return;
// adjust the final byte
default_route_v6[n - 1] &= ~(0xff >> (ipv6_cidr & 7));
// set the very last byte to something
default_route_v6[15] |= 1;
// ensure it doesn't collide
if (memcmp(default_route_v6, ipv6_address, 16) == 0)
default_route_v6[15] ^= 3;
}
void TunsafeBackendBsd::AddRoute(uint32 ip, uint32 cidr, uint32 gw, const char *dev) {
uint32 ip_be, gw_be;
WriteBE32(&ip_be, ip);
@ -411,7 +388,7 @@ static void AddOrRemoveRoute(const RouteInfo &cd, bool remove) {
#if defined(OS_LINUX)
const char *cmd = remove ? "del" : "add";
const char *proto = (cd.family == AF_INET) ? NULL : "-6";
if (cd.dev.empty()) {
if (cd.dev.empty()) {
RunCommand("/sbin/ip %s route %s %s via %s", proto, cmd, buf1, buf2);
} else {
RunCommand("/sbin/ip %s route %s %s dev %s", proto, cmd, buf1, cd.dev.c_str());
@ -451,6 +428,7 @@ static bool IsIpv6AddressSet(const void *p) {
// Called to initialize tun
bool TunsafeBackendBsd::Configure(const TunConfig &&config, TunConfigOut *out) override {
char buf[kSizeOfAddress];
char buf2[kSizeOfAddress];
if (!RunPrePostCommand(config.pre_post_commands.pre_up)) {
RERROR("Pre command failed!");
@ -461,72 +439,74 @@ bool TunsafeBackendBsd::Configure(const TunConfig &&config, TunConfigOut *out) o
if (!InitializeTun(devname_))
return false;
uint32 netmask = CidrToNetmaskV4(config.cidr);
uint32 default_route_v4 = ComputeIpv4DefaultRoute(config.ip, netmask);
const WgCidrAddr *ipv4_addr = NULL;
const WgCidrAddr *ipv6_addr = NULL;
for (auto it = config.addresses.begin(); it != config.addresses.end(); ++it) {
if (it->size == 32 && ipv4_addr == NULL)
ipv4_addr = &*it;
else if (it->size == 128 && ipv6_addr == NULL)
ipv6_addr = &*it;
}
if (ipv4_addr == NULL) {
RERROR("The TUN adapter requires an IPv4 address");
return false;
}
uint32 ipv4_netmask = CidrToNetmaskV4(ipv4_addr->cidr);
uint32 ipv4_ip = ReadBE32(ipv4_addr->addr);
addresses_to_remove_ = config.addresses;
#if defined(OS_LINUX)
if (config.ip) {
char ip[4];
WriteBE32(ip, config.ip);
RunCommand("/sbin/ip address add dev %s %s", devname_, print_ip_prefix(buf, AF_INET, ip, config.cidr));
}
if (config.ipv6_cidr) {
RunCommand("/sbin/ip address add dev %s %s", devname_, print_ip_prefix(buf, AF_INET6, config.ipv6_address, config.ipv6_cidr));
}
RunCommand("/sbin/ip address flush dev %s scope global", devname_);
for(const WgCidrAddr &a : config.addresses)
RunCommand("/sbin/ip address add dev %s %s", devname_, print_ip_prefix(buf, a.size == 32 ? AF_INET : AF_INET6, a.addr, a.cidr));
RunCommand("/sbin/ip link set dev %s mtu %d up", devname_, config.mtu);
#else // !defined(OS_LINUX)
if (config.ip) {
RunCommand("/sbin/ifconfig %s %A mtu %d %A netmask %A up", devname_, config.ip, config.mtu, config.ip, netmask);
#else
for(const WgCidrAddr &a : config.addresses) {
if (a.size == 32) {
RunCommand("/sbin/ifconfig %s inet %s %s add", devname_, print_ip_prefix(buf, AF_INET, a.addr, a.cidr), print_ip_prefix(buf2, AF_INET, a.addr, -1));
} else {
RunCommand("/sbin/ifconfig %s inet6 %s add", devname_, print_ip_prefix(buf, AF_INET6, a.addr, a.cidr));
}
}
if (config.ipv6_cidr) {
RunCommand("/sbin/ifconfig %s inet6 add %s", devname_, print_ip_prefix(buf, AF_INET6, config.ipv6_address, config.ipv6_cidr));
}
#endif // !defined(OS_LINUX)
RunCommand("/sbin/ifconfig %s mtu %d up", devname_, config.mtu);
#endif
if (config.ip) {
AddRoute(config.ip & netmask, config.cidr, config.ip, devname_);
}
if (config.use_ipv4_default_route) {
if (config.default_route_endpoint_v4) {
uint32 ipv4_default_gw;
char default_iface[16];
if (!GetDefaultRoute(default_iface, sizeof(default_iface), &ipv4_default_gw)) {
char default_iface[16];
uint32 ipv4_default_gw;
bool found_ipv4_route = GetDefaultRoute(default_iface, sizeof(default_iface), &ipv4_default_gw);
for (auto it = config.excluded_routes.begin(); it != config.excluded_routes.end(); ++it) {
if (it->size == 32) {
if (!found_ipv4_route) {
RERROR("Unable to determine default interface.");
return false;
}
AddRoute(config.default_route_endpoint_v4, 32, ipv4_default_gw, NULL);
for (auto it = config.excluded_ips.begin(); it != config.excluded_ips.end(); ++it) {
if (it->size == 32)
AddRoute(ReadBE32(it->addr), it->cidr, ipv4_default_gw, default_iface);
}
}
AddRoute(0x00000000, 1, default_route_v4, devname_);
AddRoute(0x80000000, 1, default_route_v4, devname_);
}
uint8 default_route_v6[16];
if (config.ipv6_cidr) {
static const uint8 matchall_1_route[17] = {0x80, 0, 0, 0};
ComputeIpv6DefaultRoute(config.ipv6_address, config.ipv6_cidr, default_route_v6);
if (config.use_ipv6_default_route) {
if (IsIpv6AddressSet(config.default_route_endpoint_v6)) {
RERROR("default_route_endpoint_v6 not supported");
}
AddRoute(AF_INET6, matchall_1_route + 1, 1, default_route_v6, devname_);
AddRoute(AF_INET6, matchall_1_route + 0, 1, default_route_v6, devname_);
AddRoute(ReadBE32(it->addr), it->cidr, ipv4_default_gw, NULL);
} else if (it->size == 128) {
RERROR("default_route_endpoint_v6 not supported");
return false;
}
}
// Add all the extra routes
for (auto it = config.extra_routes.begin(); it != config.extra_routes.end(); ++it) {
for (auto it = config.included_routes.begin(); it != config.included_routes.end(); ++it) {
if (it->cidr == 0) {
if (it->size == 32) {
AddRoute(0x00000000, 1, ipv4_ip, devname_);
AddRoute(0x80000000, 1, ipv4_ip, devname_);
} else if (it->size == 128 && ipv6_addr) {
static const uint8 matchall_1_route[17] = {0x80, 0, 0, 0};
AddRoute(AF_INET6, matchall_1_route + 1, 1, ipv6_addr->addr, devname_);
AddRoute(AF_INET6, matchall_1_route + 0, 1, ipv6_addr->addr, devname_);
}
continue;
}
if (it->size == 32) {
AddRoute(ReadBE32(it->addr), it->cidr, default_route_v4, devname_);
} else if (it->size == 128 && config.ipv6_cidr) {
AddRoute(AF_INET6, it->addr, it->cidr, default_route_v6, devname_);
AddRoute(ReadBE32(it->addr), it->cidr, ipv4_ip, devname_);
} else if (it->size == 128 && ipv6_addr) {
AddRoute(AF_INET6, it->addr, it->cidr, ipv6_addr->addr, devname_);
}
}
@ -539,13 +519,30 @@ bool TunsafeBackendBsd::Configure(const TunConfig &&config, TunConfigOut *out) o
}
void TunsafeBackendBsd::CleanupRoutes() {
char buf[kSizeOfAddress];
RunPrePostCommand(pre_down_);
for(auto it = cleanup_commands_.begin(); it != cleanup_commands_.end(); ++it) {
if (!tun_interface_gone_ || strcmp(it->dev.c_str(), devname_) != 0)
DelRoute(*it);
}
#if defined(OS_LINUX)
for(const WgCidrAddr &a : addresses_to_remove_)
RunCommand("/sbin/ip address del dev %s %s", devname_, print_ip_prefix(buf, a.size == 32 ? AF_INET : AF_INET6, a.addr, a.cidr));
#else
for(const WgCidrAddr &a : addresses_to_remove_) {
if (a.size == 32) {
RunCommand("/sbin/ifconfig %s inet %s -alias", devname_, print_ip_prefix(buf, AF_INET, a.addr, -1));
} else {
RunCommand("/sbin/ifconfig %s inet6 %s -alias", devname_, print_ip_prefix(buf, AF_INET6, a.addr, -1));
}
}
#endif
cleanup_commands_.clear();
addresses_to_remove_.clear();
RunPrePostCommand(post_down_);
@ -767,9 +764,13 @@ public:
virtual void OnConnected() override {
if (!is_connected_) {
uint32 ipv4_ip = ReadBE32(wg_processor_->tun_addr().addr);
const WgCidrAddr *ipv4_addr = NULL;
for (const WgCidrAddr &x : wg_processor_->addr()) {
if (x.size == 32) { ipv4_addr = &x; break; }
}
uint32 ipv4_ip = ipv4_addr ? ReadBE32(ipv4_addr->addr) : 0;
char buf[kSizeOfAddress];
RINFO("Connection established. IP %s", print_ip(buf, ipv4_ip));
RINFO("Connection established. IP %s", ipv4_ip ? print_ip(buf, ipv4_ip) : "(none)");
is_connected_ = true;
}
}
@ -831,3 +832,4 @@ int main(int argc, char **argv) {
return 0;
}

View file

@ -80,6 +80,7 @@ protected:
WireguardProcessor *processor_;
std::vector<RouteInfo> cleanup_commands_;
std::vector<std::string> pre_down_, post_down_;
std::vector<WgCidrAddr> addresses_to_remove_;
sigset_t orig_signal_mask_;
char devname_[16];
bool tun_interface_gone_;

View file

@ -310,7 +310,7 @@ struct RouteInfo {
uint8 found_null_routes;
};
static inline bool IsRouteOriginatingFromNullRoute(MIB_IPFORWARD_ROW2 *row) {
static bool IsRouteOriginatingFromNullRoute(MIB_IPFORWARD_ROW2 *row) {
if (!(row->InterfaceLuid.Info.IfType == 24 && row->Protocol == MIB_IPPROTO_NETMGMT && row->DestinationPrefix.PrefixLength == 1))
return false;
if (row->NextHop.si_family == AF_INET) {
@ -322,14 +322,25 @@ static inline bool IsRouteOriginatingFromNullRoute(MIB_IPFORWARD_ROW2 *row) {
return false;
}
static inline bool IsRouteTheAddressOfTheServer(int family, MIB_IPFORWARD_ROW2 *row, uint8 *old_endpoint_to_delete) {
if (!(row->Protocol == MIB_IPPROTO_NETMGMT && row->DestinationPrefix.Prefix.si_family == family))
static bool IsDestinationRouteEqualTo(MIB_IPFORWARD_ROW2 *row, const WgCidrAddr *addr) {
if (addr->size == 32) {
return row->DestinationPrefix.Prefix.si_family == AF_INET &&
row->DestinationPrefix.PrefixLength == addr->cidr &&
memcmp(&row->DestinationPrefix.Prefix.Ipv4.sin_addr, addr->addr, 4) == 0;
} else if (addr->size == 128) {
return row->DestinationPrefix.Prefix.si_family == AF_INET6 &&
row->DestinationPrefix.PrefixLength == addr->cidr &&
memcmp(&row->DestinationPrefix.Prefix.Ipv6.sin6_addr, addr->addr, 16) == 0;
} else {
return false;
if (family == AF_INET) {
return (row->DestinationPrefix.PrefixLength == 32 && memcmp(&row->DestinationPrefix.Prefix.Ipv4.sin_addr, old_endpoint_to_delete, 4) == 0);
} else if (family == AF_INET6) {
return (row->DestinationPrefix.PrefixLength == 128 && memcmp(&row->DestinationPrefix.Prefix.Ipv6.sin6_addr, old_endpoint_to_delete, 16) == 0);
}
}
static bool IsDestinationRouteEqualToAny(MIB_IPFORWARD_ROW2 *row, const std::vector<WgCidrAddr> &addr) {
for (const WgCidrAddr &x : addr)
if (IsDestinationRouteEqualTo(row, &x))
return true;
return false;
}
@ -343,17 +354,18 @@ static void DeleteRouteOrPrintErr(MIB_IPFORWARD_ROW2 *row) {
(void*)&row->DestinationPrefix.Prefix.Ipv6.sin6_addr, row->DestinationPrefix.PrefixLength));
}
static bool GetDefaultRouteAndDeleteOldRoutes(int family, const NET_LUID *InterfaceLuid, bool keep_null_routes, uint8 *old_endpoint_to_delete, RouteInfo *ri) {
static bool GetDefaultRouteAndDeleteOldRoutes(int family, const NET_LUID *InterfaceLuid, bool keep_null_routes, const std::vector<WgCidrAddr> *old_endpoint_to_delete, RouteInfo *ri) {
MIB_IPFORWARD_TABLE2 *table = NULL;
assert(family == AF_INET || family == AF_INET6);
ri->found_default_adapter = false;
ri->found_null_routes = 0;
if (GetIpForwardTable2(family, &table))
return false;
DWORD rv = 0;
DWORD gw_metric = 0xffffffff;
ri->found_default_adapter = false;
ri->found_null_routes = 0;
for (unsigned i = 0; i < table->NumEntries; i++) {
MIB_IPFORWARD_ROW2 *row = &table->Table[i];
if (InterfaceLuid && memcmp(&row->InterfaceLuid, InterfaceLuid, sizeof(NET_LUID)) == 0) {
@ -378,8 +390,8 @@ static bool GetDefaultRouteAndDeleteOldRoutes(int family, const NET_LUID *Interf
if (old_endpoint_to_delete && ri->found_default_adapter) {
for (unsigned i = 0; i < table->NumEntries; i++) {
MIB_IPFORWARD_ROW2 *row = &table->Table[i];
if (memcmp(&row->InterfaceLuid, &ri->default_adapter, sizeof(NET_LUID)) == 0) {
if (IsRouteTheAddressOfTheServer(family, row, old_endpoint_to_delete))
if (row->Protocol == MIB_IPPROTO_NETMGMT && memcmp(&row->InterfaceLuid, &ri->default_adapter, sizeof(NET_LUID)) == 0) {
if (IsDestinationRouteEqualToAny(row, *old_endpoint_to_delete))
DeleteRouteOrPrintErr(row);
}
}
@ -1008,31 +1020,45 @@ static void AssignIpv6Address(const void *new_address, int new_cidr, WgCidrAddr
memcpy(target->addr, new_address, 16);
}
static int IsIpv6AddressInList(const std::vector<WgCidrAddr> &addresses, const void *ipv6_addr, int cidr) {
int i = 0;
for (auto it = addresses.begin(); it != addresses.end(); ++it, i++) {
if (it->size == 128 && it->cidr == cidr && memcmp(it->addr, ipv6_addr, 16) == 0)
return i;
}
return -1;
}
// Set new_cidr to 0 to clear it.
static bool SetIPV6AddressOnInterface(NET_LUID *InterfaceLuid, const uint8 new_address[16], int new_cidr, WgCidrAddr *old_address) {
static bool SetIPV6AddressOnInterface(NET_LUID *InterfaceLuid, const std::vector<WgCidrAddr> &addresses, std::vector<WgCidrAddr> *old_address) {
NETIO_STATUS Status;
PMIB_UNICASTIPADDRESS_TABLE table = NULL;
if (old_address)
memset(old_address, 0, sizeof(WgCidrAddr));
old_address->clear();
Status = GetUnicastIpAddressTable(AF_INET6, &table);
if (Status != 0) {
RERROR("GetUnicastAddressTable Failed. Error %d\n", Status);
return false;
}
bool found_row = false;
uint64 matching_addr = 0;
for (int i = 0; i < (int)table->NumEntries; i++) {
MIB_UNICASTIPADDRESS_ROW *row = &table->Table[i];
if (!memcmp(&row->InterfaceLuid, InterfaceLuid, sizeof(NET_LUID))) {
if (row->PrefixOrigin == 1 && row->SuffixOrigin == 1) {
if (row->OnLinkPrefixLength == new_cidr && !memcmp(&row->Address.Ipv6.sin6_addr, new_address, 16)) {
found_row = true;
if (old_address) {
WgCidrAddr tmp;
AssignIpv6Address(&row->Address.Ipv6.sin6_addr, row->OnLinkPrefixLength, &tmp);
old_address->push_back(tmp);
}
int idx = IsIpv6AddressInList(addresses, &row->Address.Ipv6.sin6_addr, row->OnLinkPrefixLength);
if (idx >= 0 && idx < 64) {
matching_addr |= (uint64)1 << idx;
RINFO("Using IPv6 address: %s/%d", PrintIPV6((uint8*)&row->Address.Ipv6.sin6_addr), row->OnLinkPrefixLength);
continue;
}
if (old_address != NULL)
AssignIpv6Address(&row->Address.Ipv6.sin6_addr, row->OnLinkPrefixLength, old_address);
Status = DeleteUnicastIpAddressEntry(row);
if (Status)
RERROR("Error %d deleting IPv6 address: %s/%d", Status, PrintIPV6((uint8*)&row->Address.Ipv6.sin6_addr), row->OnLinkPrefixLength);
@ -1043,43 +1069,50 @@ static bool SetIPV6AddressOnInterface(NET_LUID *InterfaceLuid, const uint8 new_a
}
FreeMibTable(table);
if (found_row) {
RINFO("Using IPv6 address: %s/%d", PrintIPV6(new_address), new_cidr);
return true;
// Add all ipv6 addresses that were not already set.
bool success = true;
int i = 0;
for (auto it = addresses.begin(); it != addresses.end(); ++it, i++) {
// skip it because of wrong type or already set?
if (it->size != 128 || i < 64 && (matching_addr & ((uint64)1 << i)))
continue;
MIB_UNICASTIPADDRESS_ROW Row;
InitializeUnicastIpAddressEntry(&Row);
Row.OnLinkPrefixLength = it->cidr;
Row.Address.si_family = AF_INET6;
memcpy(&Row.Address.Ipv6.sin6_addr, it->addr, 16);
Row.InterfaceLuid = *InterfaceLuid;
Status = CreateUnicastIpAddressEntry(&Row);
if (Status != 0) {
RERROR("Error %d setting IPv6 address: %s/%d", Status, PrintIPV6(it->addr), it->cidr);
success = false;
} else {
RINFO("Added IPV6 Address: %s/%d", PrintIPV6(it->addr), it->cidr);
}
}
if (!IsIpv6AddressSet(new_address))
return true;
if (old_address != NULL)
old_address->size = 128;
MIB_UNICASTIPADDRESS_ROW Row;
InitializeUnicastIpAddressEntry(&Row);
Row.OnLinkPrefixLength = new_cidr;
Row.Address.si_family = AF_INET6;
memcpy(&Row.Address.Ipv6.sin6_addr, new_address, 16);
Row.InterfaceLuid = *InterfaceLuid;
Status = CreateUnicastIpAddressEntry(&Row);
if (Status != 0) {
RERROR("Error %d setting IPv6 address: %s/%d", Status, PrintIPV6(new_address), new_cidr);
return false;
}
RINFO("Set IPV6 Address to: %s/%d", PrintIPV6(new_address), new_cidr);
return true;
return success;
}
static bool SetIPV6DnsOnInterface(NET_LUID *InterfaceLuid, const IpAddr *new_address, size_t new_address_size) {
char buf[128];
char ipv6[128];
bool isfirst = true;
NET_IFINDEX InterfaceIndex;
if (ConvertInterfaceLuidToIndex(InterfaceLuid, &InterfaceIndex))
return false;
if (new_address_size) {
for (size_t i = 0; i < new_address_size; i++) {
if (new_address[i].sin.sin_family != AF_INET6)
continue;
if (!inet_ntop(AF_INET6, (void*)&new_address[i].sin6.sin6_addr, ipv6, sizeof(ipv6)))
return false;
snprintf(buf, sizeof(buf), "netsh interface ipv6 %s dns name=%d static %s validate=no", (i == 0) ? "set" : "add", InterfaceIndex, ipv6);
if (isfirst) {
isfirst = false;
snprintf(buf, sizeof(buf), "netsh interface ipv6 set dnsservers name=%d static %s validate=no", InterfaceIndex, ipv6);
} else {
snprintf(buf, sizeof(buf), "netsh interface ipv6 add dnsservers name=%d %s validate=no", InterfaceIndex, ipv6);
}
if (!RunNetsh(buf))
return false;
}
@ -1127,7 +1160,6 @@ static bool AddMultipleCatchallRoutes(int inet, int bits, const uint8 *target, c
TunWin32Adapter::TunWin32Adapter(DnsBlocker *dns_blocker, const char guid[ADAPTER_GUID_SIZE]) {
handle_ = NULL;
dns_blocker_ = dns_blocker;
old_ipv6_address_.size = 0;
old_ipv6_metric_ = kMetricNone;
old_ipv4_metric_ = kMetricNone;
has_dns6_setting_ = false;
@ -1162,6 +1194,22 @@ bool TunWin32Adapter::OpenAdapter(TunsafeBackendWin32 *backend, DWORD open_flags
return (handle_ != NULL);
}
static inline bool CheckFirstNbitsEquals(const byte *a, const byte *b, size_t n) {
return memcmp(a, b, n >> 3) == 0 && ((n & 7) == 0 || !((a[n >> 3] ^ b[n >> 3]) & (0xff << (8 - (n & 7)))));
}
static bool IsWgCidrAddrSubsetOf(const WgCidrAddr &inner, const WgCidrAddr &outer) {
return inner.size == outer.size && inner.cidr >= outer.cidr &&
CheckFirstNbitsEquals(inner.addr, outer.addr, outer.cidr);
}
static bool IsWgCidrAddrSubsetOfAny(const WgCidrAddr &inner, const std::vector<WgCidrAddr> &addr) {
for (auto &a : addr)
if (IsWgCidrAddrSubsetOf(inner, a))
return true;
return false;
}
bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, TunInterface::TunConfigOut *out) {
DWORD len, err;
@ -1175,14 +1223,28 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
pre_down_ = std::move(config.pre_post_commands.pre_down);
post_down_ = std::move(config.pre_post_commands.post_down);
uint32 netmask = CidrToNetmaskV4(config.cidr);
const WgCidrAddr *ipv4_addr = NULL;
const WgCidrAddr *ipv6_addr = NULL;
for (auto it = config.addresses.begin(); it != config.addresses.end(); ++it) {
if (it->size == 32 && ipv4_addr == NULL)
ipv4_addr = &*it;
else if (it->size == 128 && ipv6_addr == NULL)
ipv6_addr = &*it;
}
if (ipv4_addr == NULL) {
RERROR("The TUN adapter on Windows requires an IPv4 address");
return false;
}
uint32 ipv4_netmask = CidrToNetmaskV4(ipv4_addr->cidr);
uint32 ipv4_ip = ReadBE32(ipv4_addr->addr);
// Set TAP-Windows TUN subnet mode
if (1) {
uint32 v[3];
v[0] = htonl(config.ip);
v[1] = htonl(config.ip & netmask);
v[2] = htonl(netmask);
v[0] = htonl(ipv4_ip);
v[1] = htonl(ipv4_ip & ipv4_netmask);
v[2] = htonl(ipv4_netmask);
if (!DeviceIoControl(handle_, TAP_IOCTL_CONFIG_TUN, v, sizeof(v), v, sizeof(v), &len, NULL)) {
RERROR("DeviceIoControl(TAP_IOCTL_CONFIG_TUN) failed");
return false;
@ -1192,9 +1254,9 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
// Set DHCP IP/netmask
{
uint32 v[4];
v[0] = htonl(config.ip);
v[1] = htonl(netmask);
v[2] = htonl((config.ip | ~netmask) - 1); // x.x.x.254
v[0] = htonl(ipv4_ip);
v[1] = htonl(ipv4_netmask);
v[2] = htonl((ipv4_ip | ~ipv4_netmask) - 1); // x.x.x.254
v[3] = 31536000; // One year
if (!DeviceIoControl(handle_, TAP_IOCTL_CONFIG_DHCP_MASQ, v, sizeof(v), v, sizeof(v), &len, NULL)) {
RERROR("DeviceIoControl(TAP_IOCTL_CONFIG_DHCP_MASQ) failed");
@ -1202,21 +1264,28 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
}
}
// Set DHCP config string
if (config.ipv4_dns.size()) {
// Extract and set IPv4 DNS servers through DHCP
{
enum { kMaxDnsServers = 4 };
uint8 dhcp_options[2 + kMaxDnsServers * 4]; // max 4 dns servers
size_t num_dns = std::min<size_t>(config.ipv4_dns.size(), kMaxDnsServers);
dhcp_options[0] = 6;
dhcp_options[1] = (uint8)(num_dns * 4);
for(size_t i = 0; i < num_dns; i++)
memcpy(&dhcp_options[2 + i * 4], &config.ipv4_dns[i].sin.sin_addr, num_dns * 4);
DWORD dhcp_options_size = (DWORD)(num_dns * 4 + 2);
byte output[10];
if (!DeviceIoControl(handle_, TAP_IOCTL_CONFIG_DHCP_SET_OPT,
uint32 num_dns = 0;
for (auto it = config.dns.begin(); it != config.dns.end(); ++it) {
if (it->sin.sin_family != AF_INET)
continue;
memcpy(&dhcp_options[2 + num_dns * 4], &it->sin.sin_addr, 4);
if (++num_dns == kMaxDnsServers)
break;
}
if (num_dns != 0) {
dhcp_options[0] = 6;
dhcp_options[1] = (uint8)(num_dns * 4);
DWORD dhcp_options_size = (DWORD)(num_dns * 4 + 2);
byte output[10];
if (!DeviceIoControl(handle_, TAP_IOCTL_CONFIG_DHCP_SET_OPT,
(void*)dhcp_options, dhcp_options_size, output, sizeof(output), &len, NULL)) {
RERROR("DeviceIoControl(TAP_IOCTL_CONFIG_DHCP_SET_OPT) failed");
return false;
RERROR("DeviceIoControl(TAP_IOCTL_CONFIG_DHCP_SET_OPT) failed");
return false;
}
}
}
@ -1246,7 +1315,7 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
err = SetMtuOnNetworkAdapter(&interface_luid_, AF_INET, config.mtu);
if (err)
RERROR("SetMtuOnNetworkAdapter IPv4 failed: %d", err);
if (config.ipv6_cidr) {
if (ipv6_addr) {
err = SetMtuOnNetworkAdapter(&interface_luid_, AF_INET6, config.mtu);
if (err)
RERROR("SetMtuOnNetworkAdapter IPv6 failed: %d", err);
@ -1254,18 +1323,22 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
}
has_dns6_setting_ = false;
if (config.ipv6_cidr) {
SetIPV6AddressOnInterface(&interface_luid_, config.ipv6_address, config.ipv6_cidr, &old_ipv6_address_);
if (ipv6_addr) {
SetIPV6AddressOnInterface(&interface_luid_, config.addresses, &old_ipv6_address_);
if (config.ipv6_dns.size()) {
has_dns6_setting_ = true;
if (!SetIPV6DnsOnInterface(&interface_luid_, config.ipv6_dns.data(), config.ipv6_dns.size())) {
RERROR("SetIPV6DnsOnInterface: failed");
// Check if we have at least one ipv6 setting
for (auto it = config.dns.begin(); it != config.dns.end(); ++it) {
if (it->sin.sin_family == AF_INET6) {
has_dns6_setting_ = true;
break;
}
}
if (has_dns6_setting_ && !SetIPV6DnsOnInterface(&interface_luid_, config.dns.data(), config.dns.size())) {
RERROR("SetIPV6DnsOnInterface: failed");
}
}
if ((config.ipv4_dns.size() || has_dns6_setting_) && config.block_dns_on_adapters) {
if (config.dns.size() && config.block_dns_on_adapters) {
RINFO("Blocking standard DNS on all adapters");
dns_blocker_->BlockDnsExceptOnAdapter(interface_luid_, has_dns6_setting_);
@ -1273,7 +1346,7 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
if (err)
RERROR("SetMetricOnNetworkAdapter IPv4 failed: %d", err);
if (config.ipv6_cidr) {
if (ipv6_addr) {
err = SetMetricOnNetworkAdapter(&interface_luid_, AF_INET6, 2, &old_ipv6_metric_);
if (err)
RERROR("SetMetricOnNetworkAdapter IPv6 failed: %d", err);
@ -1289,25 +1362,17 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
RouteInfo ri, ri6;
uint32 default_route_endpoint_v4 = ToBE32(config.default_route_endpoint_v4);
// Delete any current /1 default routes and read some stuff from the routing table.
if (!GetDefaultRouteAndDeleteOldRoutes(AF_INET, &interface_luid_, block_all_traffic_route, config.use_ipv4_default_route ? (uint8*)&default_route_endpoint_v4 : NULL, &ri)) {
if (!GetDefaultRouteAndDeleteOldRoutes(AF_INET, &interface_luid_, block_all_traffic_route, &config.excluded_routes, &ri)) {
RERROR("Unable to read old default gateway and delete old default routes.");
return false;
}
if (config.ipv6_cidr) {
// Delete any current /1 default routes and read some stuff from the routing table.
if (!GetDefaultRouteAndDeleteOldRoutes(AF_INET6, &interface_luid_, block_all_traffic_route, config.use_ipv6_default_route ? (uint8*)config.default_route_endpoint_v6 : NULL, &ri6)) {
RERROR("Unable to read old default gateway and delete old default routes for IPv6.");
return false;
}
// Delete any current /1 default routes and read some stuff from the routing table.
if (!GetDefaultRouteAndDeleteOldRoutes(AF_INET6, &interface_luid_, block_all_traffic_route, &config.excluded_routes, &ri6)) {
RERROR("Unable to read old default gateway and delete old default routes for IPv6.");
}
uint32 default_route_v4 = ComputeIpv4DefaultRoute(config.ip, netmask);
uint8 default_route_v6[16];
if (block_all_traffic_route) {
RINFO("Blocking all regular Internet traffic using routing rules");
NET_LUID localhost_luid;
@ -1317,17 +1382,17 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
g_killswitch_curr |= kBlockInternet_Route;
uint32 dst[4] = {0};
if (!AddMultipleCatchallRoutes(AF_INET, 1, (uint8*)&dst, localhost_luid, NULL)) {
RERROR("Unable to add routes for route based blocking.");
DeactivateKillSwitch(0);
return false;
}
if (config.ipv6_cidr) {
if (!AddMultipleCatchallRoutes(AF_INET6, 1, (uint8*)&dst, localhost_luid, NULL)) {
RERROR("Unable to add IPv6 routes for route based blocking.");
DeactivateKillSwitch(0);
return false;
}
if (!AddMultipleCatchallRoutes(AF_INET6, 1, (uint8*)&dst, localhost_luid, NULL)) {
RERROR("Unable to add IPv6 routes for route based blocking.");
DeactivateKillSwitch(0);
return false;
}
}
}
@ -1335,8 +1400,7 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
if (ibs & kBlockInternet_Firewall) {
RINFO("Blocking all regular Internet traffic using firewall rules");
g_killswitch_curr |= kBlockInternet_Firewall;
if (!AddKillSwitchFirewall(interface_luid_, config.ipv6_cidr != 0, (ibs & kBlockInternet_AllowLocalNetworks) != 0)) {
if (!AddKillSwitchFirewall(interface_luid_, true, (ibs & kBlockInternet_AllowLocalNetworks) != 0)) {
RERROR("Unable to activate firewall based kill switch");
DeactivateKillSwitch(0);
return false;
@ -1345,63 +1409,54 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
DeactivateKillSwitch(ibs);
// Configure default route?
if (config.use_ipv4_default_route) {
// Add a bypass route to the original gateway?
if (config.default_route_endpoint_v4 != 0) {
if (!ri.found_default_adapter) {
RERROR("Unable to read old ipv4 default gateway");
return false;
}
if (!AddRoute(AF_INET, &default_route_endpoint_v4, 32, ri.default_gw, &ri.default_adapter, &routes_to_undo_)) {
RERROR("Unable to add ipv4 gateway bypass route.");
return false;
uint8 default_route_v4[4];
uint8 default_route_v6[16];
WriteBE32(default_route_v4, ComputeIpv4DefaultRoute(ipv4_ip, ipv4_netmask));
if (ipv6_addr)
ComputeIpv6DefaultRoute(ipv6_addr->addr, ipv6_addr->cidr, default_route_v6);
// Add all the routes that should go through the VPN
for (auto it = config.included_routes.begin(); it != config.included_routes.end(); ++it) {
if (it->cidr == 0) {
// /0 gets changed to two /1 routes, to avoid overwriting the system's default route
if (it->size == 32) {
if (!AddMultipleCatchallRoutes(AF_INET, block_all_traffic_route ? 2 : 1, default_route_v4, interface_luid_, &routes_to_undo_))
RERROR("Unable to add new default ipv4 route.");
} else if (it->size == 128 && ipv6_addr) {
if (!AddMultipleCatchallRoutes(AF_INET6, block_all_traffic_route ? 2 : 1, default_route_v6, interface_luid_, &routes_to_undo_))
RERROR("Unable to add new default ipv6 route.");
}
continue;
}
// Either add 4 routes or 2 routes, depending on if we use route blocking.
uint32 be = ToBE32(default_route_v4);
if (!AddMultipleCatchallRoutes(AF_INET, block_all_traffic_route ? 2 : 1, (uint8*)&be, interface_luid_, &routes_to_undo_))
RERROR("Unable to add new default ipv4 route.");
}
// Avoid adding a route if it's a subset of the address
if (IsWgCidrAddrSubsetOfAny(*it, config.addresses))
continue;
if (config.ipv6_cidr) {
ComputeIpv6DefaultRoute(config.ipv6_address, config.ipv6_cidr, default_route_v6);
// Configure default route?
if (config.use_ipv6_default_route) {
if (IsIpv6AddressSet(config.default_route_endpoint_v6)) {
if (!ri6.found_default_adapter) {
RERROR("Unable to read old ipv6 default gateway");
return false;
}
if (!AddRoute(AF_INET6, config.default_route_endpoint_v6, 128, ri.default_gw, &ri6.default_adapter, &routes_to_undo_)) {
RERROR("Unable to add ipv6 gateway bypass route.");
return false;
}
}
if (!AddMultipleCatchallRoutes(AF_INET6, block_all_traffic_route ? 2 : 1, default_route_v6, interface_luid_, &routes_to_undo_))
RERROR("Unable to add new default ipv6 route.");
}
}
// Add all the extra routes
for (auto it = config.extra_routes.begin(); it != config.extra_routes.end(); ++it) {
if (it->size == 32) {
uint32 be = ToBE32(default_route_v4);
AddRoute(AF_INET, it->addr, it->cidr, &be, &interface_luid_, &routes_to_undo_);
} else if (it->size == 128 && config.ipv6_cidr) {
AddRoute(AF_INET, it->addr, it->cidr, default_route_v4, &interface_luid_, &routes_to_undo_);
} else if (it->size == 128 && ipv6_addr) {
AddRoute(AF_INET6, it->addr, it->cidr, default_route_v6, &interface_luid_, &routes_to_undo_);
}
}
// Add all the routes that should bypass vpn
for (auto it = config.excluded_ips.begin(); it != config.excluded_ips.end(); ++it) {
int warned = 0;
for (auto it = config.excluded_routes.begin(); it != config.excluded_routes.end(); ++it) {
if (it->size == 32) {
if (ri.found_default_adapter)
if (ri.found_default_adapter) {
AddRoute(AF_INET, it->addr, it->cidr, ri.default_gw, &ri.default_adapter, &routes_to_undo_);
} else if (it->size == 128 && config.ipv6_cidr) {
if (ri6.found_default_adapter)
} else if (!(warned & 1)) {
warned |= 1;
RERROR("Unable to read old ipv4 default gateway");
}
} else if (it->size == 128) {
if (ri6.found_default_adapter) {
AddRoute(AF_INET6, it->addr, it->cidr, ri6.default_gw, &ri6.default_adapter, &routes_to_undo_);
} else if (!(warned & 2)) {
warned |= 2;
RERROR("Unable to read old ipv6 default gateway");
}
}
}
@ -1414,7 +1469,7 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
RERROR("FlushIpNetTable failed: 0x%X", err);
return false;
}
if (config.ipv6_cidr) {
if (ipv6_addr != NULL) {
if ((err = FlushIpNetTable2(AF_INET6, InterfaceIndex)) != NO_ERROR) {
RERROR("FlushIpNetTable failed: 0x%X", err);
return false;
@ -1439,8 +1494,8 @@ void TunWin32Adapter::CloseAdapter(bool is_restart) {
TunAdaptersInUse::GetInstance()->Release(backend_);
}
if (old_ipv6_address_.size != 0)
SetIPV6AddressOnInterface(&interface_luid_, old_ipv6_address_.addr, old_ipv6_address_.cidr, NULL);
if (old_ipv6_address_.size())
SetIPV6AddressOnInterface(&interface_luid_, old_ipv6_address_, NULL);
if (old_ipv4_metric_ != kMetricNone)
SetMetricOnNetworkAdapter(&interface_luid_, AF_INET, old_ipv4_metric_, NULL);
if (old_ipv6_metric_ != kMetricNone)
@ -1449,7 +1504,7 @@ void TunWin32Adapter::CloseAdapter(bool is_restart) {
SetIPV6DnsOnInterface(&interface_luid_, NULL, 0);
old_ipv4_metric_ = old_ipv6_metric_ = -1;
old_ipv6_address_.size = 0;
old_ipv6_address_.clear();
has_dns6_setting_ = false;
for (auto it = routes_to_undo_.begin(); it != routes_to_undo_.end(); ++it)
@ -2245,10 +2300,17 @@ void TunsafeBackendWin32::SendConfigurationProtocolPacket(uint32 identifier, con
void TunsafeBackendWin32::OnConnected() {
if (status_ != TunsafeBackend::kStatusConnected) {
ipv4_ip_ = ReadBE32(wg_processor_->tun_addr().addr);
const WgCidrAddr *ipv4_addr = NULL;
for (const WgCidrAddr &x : wg_processor_->addr()) {
if (x.size == 32) {
ipv4_addr = &x;
break;
}
}
ipv4_ip_ = ipv4_addr ? ReadBE32(ipv4_addr->addr) : 0;
if (status_ != TunsafeBackend::kStatusReconnecting) {
char buf[kSizeOfAddress];
RINFO("Connection established. IP %s", print_ip_prefix(buf, AF_INET, wg_processor_->tun_addr().addr, -1));
RINFO("Connection established. IP %s", ipv4_addr ? print_ip_prefix(buf, AF_INET, ipv4_addr->addr, -1) : "(none)");
}
SetStatus(TunsafeBackend::kStatusConnected);
}

View file

@ -118,7 +118,7 @@ private:
int old_ipv4_metric_, old_ipv6_metric_;
WgCidrAddr old_ipv6_address_;
std::vector<WgCidrAddr> old_ipv6_address_;
NET_LUID interface_luid_;

View file

@ -23,8 +23,6 @@ enum {
};
WireguardProcessor::WireguardProcessor(UdpInterface *udp, TunInterface *tun, ProcessorDelegate *procdel) {
tun_addr_.size = 0;
tun6_addr_.size = 0;
udp_ = udp;
tun_ = tun;
procdel_ = procdel;
@ -54,21 +52,16 @@ void WireguardProcessor::SetListenPort(int listen_port) {
}
void WireguardProcessor::AddDnsServer(const IpAddr &sin) {
std::vector<IpAddr> *target = (sin.sin.sin_family == AF_INET6) ? &dns6_addr_ : &dns_addr_;
target->push_back(sin);
dns_addr_.push_back(sin);
}
bool WireguardProcessor::SetTunAddress(const WgCidrAddr &addr) {
WgCidrAddr *target = (addr.size == 128) ? &tun6_addr_ : &tun_addr_;
if (target->size != 0)
return false;
*target = addr;
addresses_.push_back(addr);
return true;
}
void WireguardProcessor::ClearTunAddress() {
tun_addr_.size = 0;
tun6_addr_.size = 0;
addresses_.clear();
}
void WireguardProcessor::AddExcludedIp(const WgCidrAddr &cidr_addr) {
@ -118,19 +111,32 @@ void WireguardProcessor::SetupCompressionHeader(WgPacketCompressionVer01 *c) {
c->ttl = 64;
#endif // defined(OS_WIN)
WriteLE16(&c->version, EXT_PACKET_COMPRESSION_VER);
memcpy(c->ipv4_addr, &tun_addr_.addr, 4);
if (tun6_addr_.size == 128)
memcpy(c->ipv6_addr, &tun6_addr_.addr, 16);
c->flags = ((tun_addr_.cidr >> 3) & 3);
for (auto it = addresses_.begin(); it != addresses_.end(); ++it) {
if (it->size == 32) {
memcpy(c->ipv4_addr, it->addr, 4);
c->flags = ((it->cidr >> 3) & 3);
break;
}
}
for (auto it = addresses_.begin(); it != addresses_.end(); ++it) {
if (it->size == 128) {
memcpy(c->ipv6_addr, it->addr, 16);
break;
}
}
}
static inline bool CheckFirstNbitsEquals(const byte *a, const byte *b, size_t n) {
return memcmp(a, b, n >> 3) == 0 && ((n & 7) == 0 || !((a[n >> 3] ^ b[n >> 3]) & (0xff << (8 - (n & 7)))));
}
static bool IsWgCidrAddrSubsetOf(const WgCidrAddr &inner, const WgCidrAddr &outer) {
return inner.size == outer.size && inner.cidr >= outer.cidr &&
CheckFirstNbitsEquals(inner.addr, outer.addr, outer.cidr);
static WgCidrAddr WgCidrAddrFromIpAddr(const IpAddr &addr) {
WgCidrAddr r = {0};
if (addr.sin.sin_family == AF_INET) {
r.size = r.cidr = 32;
memcpy(r.addr, &addr.sin.sin_addr, 4);
} else if (addr.sin.sin_family == AF_INET6) {
r.size = r.cidr = 128;
memcpy(r.addr, &addr.sin6.sin6_addr, 16);
}
return r;
}
bool WireguardProcessor::Start() {
@ -146,74 +152,52 @@ bool WireguardProcessor::ConfigureTun() {
assert(dev_.IsMainThread());
TunInterface::TunConfig config = {0};
if (tun_addr_.size == 32) {
if (tun_addr_.cidr >= 31) {
RERROR("TAP is not compatible CIDR /31 or /32. Changing to /24");
tun_addr_.cidr = 24;
}
config.ip = ReadBE32(tun_addr_.addr);
config.cidr = tun_addr_.cidr;
} else {
RERROR("No IPv4 address configured");
}
uint32 ipv4_broadcast_addr = 0xffffffff;
config.mtu = mtu_;
config.pre_post_commands = pre_post_;
config.excluded_ips = excluded_ips_;
for (auto it = addresses_.begin(); it != addresses_.end(); ++it) {
if (it->size == 32) {
if (it->cidr >= 31) {
RINFO("TAP is not compatible CIDR /31 or /32. Changing to /24");
it->cidr = 24;
}
uint32 netmask = tun_addr_.cidr == 32 ? 0xffffffff : 0xffffffff << (32 - tun_addr_.cidr);
uint32 ipv4_broadcast_addr = (netmask == 0xffffffff) ? 0xffffffff : config.ip | ~netmask;
if (tun6_addr_.size == 128) {
if (tun6_addr_.cidr > 126) {
RERROR("IPv6 /127 or /128 not supported. Changing to 120");
tun6_addr_.cidr = 120;
}
config.ipv6_cidr = tun6_addr_.cidr;
memcpy(&config.ipv6_address, tun6_addr_.addr, 16);
}
if (add_routes_mode_) {
WgPeer *peer = (WgPeer *)dev_.ip_to_peer_map().LookupV4DefaultPeer();
if (peer != NULL && peer->endpoint_.sin.sin_family != 0) {
config.default_route_endpoint_v4 = (peer->endpoint_.sin.sin_family == AF_INET) ? ReadBE32(&peer->endpoint_.sin.sin_addr) : 0;
// Set the default route to something
config.use_ipv4_default_route = true;
peer->allow_endpoint_change_ = false;
}
// Also configure ipv6 gw?
if (config.ipv6_cidr != 0) {
peer = (WgPeer*)dev_.ip_to_peer_map().LookupV6DefaultPeer();
if (peer != NULL && peer->endpoint_.sin.sin_family != 0) {
if (peer->endpoint_.sin.sin_family == AF_INET6)
memcpy(&config.default_route_endpoint_v6, &peer->endpoint_.sin6.sin6_addr, 16);
config.use_ipv6_default_route = true;
peer->allow_endpoint_change_ = false;
// Packets to this IP will not be sent out.
if (ipv4_broadcast_addr == 0xffffffff) {
uint32 netmask = it->cidr == 32 ? 0xffffffff : 0xffffffff << (32 - it->cidr);
ipv4_broadcast_addr = (netmask == 0xffffffff) ? 0xffffffff : ReadBE32(it->addr) | ~netmask;
}
} else if (it->size == 128) {
if (it->cidr > 126) {
RERROR("IPv6 /127 or /128 not supported. Changing to 120");
it->cidr = 120;
}
}
config.addresses.push_back(*it);
}
config.mtu = mtu_;
config.pre_post_commands = pre_post_;
config.excluded_routes = excluded_ips_;
if (add_routes_mode_) {
// For each peer, add the extra routes to the extra routes table
for (WgPeer *peer = dev_.first_peer(); peer; peer = peer->next_peer_) {
for (auto it = peer->allowed_ips_.begin(); it != peer->allowed_ips_.end(); ++it) {
// Don't add an entry if it's identical to my address or it's a default route
if (IsWgCidrAddrSubsetOf(*it, tun_addr_) || IsWgCidrAddrSubsetOf(*it, tun6_addr_) || it->cidr == 0)
continue;
// Don't add an entry if we have no ipv6 address configured
if (config.ipv6_cidr == 0 && it->size != 32)
continue;
config.extra_routes.push_back(*it);
config.included_routes.push_back(*it);
// If peer has the ::/0 or 0.0.0.0/0 address, disallow endpoint change.
if (it->cidr == 0)
peer->allow_endpoint_change_ = false;
}
// Add the peer's endpoint to the route exclusion list.
WgCidrAddr endpoint_addr = WgCidrAddrFromIpAddr(peer->endpoint_);
if (endpoint_addr.size != 0)
config.excluded_routes.push_back(endpoint_addr);
}
}
config.block_dns_on_adapters = dns_blocking_ && ((config.use_ipv4_default_route && dns_addr_.size()) ||
(config.use_ipv6_default_route && dns6_addr_.size()));
config.block_dns_on_adapters = dns_blocking_;
config.internet_blocking = internet_blocking_;
config.ipv4_dns = dns_addr_;
config.ipv6_dns = dns6_addr_;
config.dns = dns_addr_;
TunInterface::TunConfigOut config_out;
if (!tun_->Configure(std::move(config), &config_out))

View file

@ -99,8 +99,7 @@ public:
WgDevice &dev() { return dev_; }
TunInterface::PrePostCommands &prepost() { return pre_post_; }
const WgCidrAddr &tun_addr() { return tun_addr_; }
const std::vector<WgCidrAddr> &addr() { return addresses_; }
void RunAllMainThreadScheduled();
private:
void DoWriteUdpPacket(Packet *packet);
@ -138,12 +137,10 @@ private:
WgDevice dev_;
WgCidrAddr tun_addr_;
WgCidrAddr tun6_addr_;
WgProcessorStats stats_;
std::vector<IpAddr> dns_addr_, dns6_addr_;
std::vector<WgCidrAddr> addresses_;
std::vector<IpAddr> dns_addr_;
TunInterface::PrePostCommands pre_post_;

View file

@ -379,10 +379,8 @@ void WgConfig::HandleConfigurationProtocolGet(WireguardProcessor *proc, std::str
CmsgAppendHex(result, "private_key", proc->dev_.s_priv_, sizeof(proc->dev_.s_priv_));
if (proc->listen_port_)
CmsgAppendFmt(result, "listen_port=%d", proc->listen_port_);
if (proc->tun_addr_.size == 32)
CmsgAppendFmt(result, "address=%s", PrintWgCidrAddr(proc->tun_addr_, buf));
if (proc->tun6_addr_.size == 128)
CmsgAppendFmt(result, "address=%s", PrintWgCidrAddr(proc->tun6_addr_, buf));
for(const WgCidrAddr &x : proc->addresses_)
CmsgAppendFmt(result, "address=%s", PrintWgCidrAddr(x, buf));
for (WgPeer *peer = proc->dev_.peers_; peer; peer = peer->next_peer_) {
WG_SCOPED_LOCK(peer->lock_);