Simplify tun configuration
This commit is contained in:
parent
335133fa8f
commit
a7776ab7c4
10 changed files with 359 additions and 347 deletions
|
@ -37,18 +37,6 @@ void *IpToPeerMap::LookupV4(uint32 ip) {
|
||||||
return ipv4_.Lookup(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) {
|
void IpToPeerMap::RemoveV4(uint32 ip, int cidr) {
|
||||||
ipv4_.Delete(ip, cidr);
|
ipv4_.Delete(ip, cidr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,9 +50,6 @@ public:
|
||||||
void *LookupV4(uint32 ip);
|
void *LookupV4(uint32 ip);
|
||||||
void *LookupV6(const void *addr);
|
void *LookupV6(const void *addr);
|
||||||
|
|
||||||
void *LookupV4DefaultPeer();
|
|
||||||
void *LookupV6DefaultPeer();
|
|
||||||
|
|
||||||
void RemoveV4(uint32 ip, int cidr);
|
void RemoveV4(uint32 ip, int cidr);
|
||||||
void RemoveV6(const void *addr, int cidr);
|
void RemoveV6(const void *addr, int cidr);
|
||||||
private:
|
private:
|
||||||
|
|
31
netapi.h
31
netapi.h
|
@ -63,43 +63,26 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TunConfig {
|
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)
|
// no, yes(firewall), yes(route), yes(both), 255(default)
|
||||||
uint8 internet_blocking;
|
uint8 internet_blocking;
|
||||||
|
|
||||||
// Set this to configure a default route for ipv4
|
bool block_dns_on_adapters;
|
||||||
bool use_ipv4_default_route;
|
|
||||||
|
|
||||||
// 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
|
// Set mtu
|
||||||
int mtu;
|
int mtu;
|
||||||
|
|
||||||
// Set ipv6 address?
|
// The ipv6 and ipv4 addresses
|
||||||
uint8 ipv6_address[16];
|
std::vector<WgCidrAddr> addresses;
|
||||||
uint8 ipv6_cidr;
|
|
||||||
|
|
||||||
// Set this to configure DNS server for ipv4,ipv6
|
// Set this to configure DNS server
|
||||||
std::vector<IpAddr> ipv4_dns;
|
std::vector<IpAddr> 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];
|
|
||||||
|
|
||||||
// This holds all cidr addresses to add as additional routing entries
|
// 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
|
// This holds all the ips to exclude
|
||||||
std::vector<WgCidrAddr> excluded_ips;
|
std::vector<WgCidrAddr> excluded_routes;
|
||||||
|
|
||||||
// This holds the pre/post commands
|
// This holds the pre/post commands
|
||||||
PrePostCommands pre_post_commands;
|
PrePostCommands pre_post_commands;
|
||||||
|
|
|
@ -372,29 +372,6 @@ static uint32 CidrToNetmaskV4(int cidr) {
|
||||||
return cidr == 32 ? 0xffffffff : 0xffffffff << (32 - 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) {
|
void TunsafeBackendBsd::AddRoute(uint32 ip, uint32 cidr, uint32 gw, const char *dev) {
|
||||||
uint32 ip_be, gw_be;
|
uint32 ip_be, gw_be;
|
||||||
WriteBE32(&ip_be, ip);
|
WriteBE32(&ip_be, ip);
|
||||||
|
@ -451,6 +428,7 @@ static bool IsIpv6AddressSet(const void *p) {
|
||||||
// Called to initialize tun
|
// Called to initialize tun
|
||||||
bool TunsafeBackendBsd::Configure(const TunConfig &&config, TunConfigOut *out) override {
|
bool TunsafeBackendBsd::Configure(const TunConfig &&config, TunConfigOut *out) override {
|
||||||
char buf[kSizeOfAddress];
|
char buf[kSizeOfAddress];
|
||||||
|
char buf2[kSizeOfAddress];
|
||||||
|
|
||||||
if (!RunPrePostCommand(config.pre_post_commands.pre_up)) {
|
if (!RunPrePostCommand(config.pre_post_commands.pre_up)) {
|
||||||
RERROR("Pre command failed!");
|
RERROR("Pre command failed!");
|
||||||
|
@ -462,71 +440,73 @@ bool TunsafeBackendBsd::Configure(const TunConfig &&config, TunConfigOut *out) o
|
||||||
if (!InitializeTun(devname_))
|
if (!InitializeTun(devname_))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint32 netmask = CidrToNetmaskV4(config.cidr);
|
const WgCidrAddr *ipv4_addr = NULL;
|
||||||
uint32 default_route_v4 = ComputeIpv4DefaultRoute(config.ip, netmask);
|
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 defined(OS_LINUX)
|
||||||
if (config.ip) {
|
RunCommand("/sbin/ip address flush dev %s scope global", devname_);
|
||||||
char ip[4];
|
for(const WgCidrAddr &a : config.addresses)
|
||||||
WriteBE32(ip, config.ip);
|
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 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 link set dev %s mtu %d up", devname_, config.mtu);
|
RunCommand("/sbin/ip link set dev %s mtu %d up", devname_, config.mtu);
|
||||||
#else // !defined(OS_LINUX)
|
#else
|
||||||
if (config.ip) {
|
for(const WgCidrAddr &a : config.addresses) {
|
||||||
RunCommand("/sbin/ifconfig %s %A mtu %d %A netmask %A up", devname_, config.ip, config.mtu, config.ip, netmask);
|
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];
|
char default_iface[16];
|
||||||
if (!GetDefaultRoute(default_iface, sizeof(default_iface), &ipv4_default_gw)) {
|
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.");
|
RERROR("Unable to determine default interface.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AddRoute(config.default_route_endpoint_v4, 32, ipv4_default_gw, NULL);
|
AddRoute(ReadBE32(it->addr), it->cidr, ipv4_default_gw, NULL);
|
||||||
for (auto it = config.excluded_ips.begin(); it != config.excluded_ips.end(); ++it) {
|
} else if (it->size == 128) {
|
||||||
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");
|
RERROR("default_route_endpoint_v6 not supported");
|
||||||
}
|
return false;
|
||||||
AddRoute(AF_INET6, matchall_1_route + 1, 1, default_route_v6, devname_);
|
|
||||||
AddRoute(AF_INET6, matchall_1_route + 0, 1, default_route_v6, devname_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all the extra routes
|
// 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) {
|
if (it->size == 32) {
|
||||||
AddRoute(ReadBE32(it->addr), it->cidr, default_route_v4, devname_);
|
AddRoute(0x00000000, 1, ipv4_ip, devname_);
|
||||||
} else if (it->size == 128 && config.ipv6_cidr) {
|
AddRoute(0x80000000, 1, ipv4_ip, devname_);
|
||||||
AddRoute(AF_INET6, it->addr, it->cidr, default_route_v6, 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, 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() {
|
void TunsafeBackendBsd::CleanupRoutes() {
|
||||||
|
char buf[kSizeOfAddress];
|
||||||
|
|
||||||
RunPrePostCommand(pre_down_);
|
RunPrePostCommand(pre_down_);
|
||||||
|
|
||||||
for(auto it = cleanup_commands_.begin(); it != cleanup_commands_.end(); ++it) {
|
for(auto it = cleanup_commands_.begin(); it != cleanup_commands_.end(); ++it) {
|
||||||
if (!tun_interface_gone_ || strcmp(it->dev.c_str(), devname_) != 0)
|
if (!tun_interface_gone_ || strcmp(it->dev.c_str(), devname_) != 0)
|
||||||
DelRoute(*it);
|
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();
|
cleanup_commands_.clear();
|
||||||
|
addresses_to_remove_.clear();
|
||||||
|
|
||||||
RunPrePostCommand(post_down_);
|
RunPrePostCommand(post_down_);
|
||||||
|
|
||||||
|
@ -767,9 +764,13 @@ public:
|
||||||
|
|
||||||
virtual void OnConnected() override {
|
virtual void OnConnected() override {
|
||||||
if (!is_connected_) {
|
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];
|
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;
|
is_connected_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -831,3 +832,4 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,7 @@ protected:
|
||||||
WireguardProcessor *processor_;
|
WireguardProcessor *processor_;
|
||||||
std::vector<RouteInfo> cleanup_commands_;
|
std::vector<RouteInfo> cleanup_commands_;
|
||||||
std::vector<std::string> pre_down_, post_down_;
|
std::vector<std::string> pre_down_, post_down_;
|
||||||
|
std::vector<WgCidrAddr> addresses_to_remove_;
|
||||||
sigset_t orig_signal_mask_;
|
sigset_t orig_signal_mask_;
|
||||||
char devname_[16];
|
char devname_[16];
|
||||||
bool tun_interface_gone_;
|
bool tun_interface_gone_;
|
||||||
|
|
|
@ -310,7 +310,7 @@ struct RouteInfo {
|
||||||
uint8 found_null_routes;
|
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))
|
if (!(row->InterfaceLuid.Info.IfType == 24 && row->Protocol == MIB_IPPROTO_NETMGMT && row->DestinationPrefix.PrefixLength == 1))
|
||||||
return false;
|
return false;
|
||||||
if (row->NextHop.si_family == AF_INET) {
|
if (row->NextHop.si_family == AF_INET) {
|
||||||
|
@ -322,14 +322,25 @@ static inline bool IsRouteOriginatingFromNullRoute(MIB_IPFORWARD_ROW2 *row) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool IsRouteTheAddressOfTheServer(int family, MIB_IPFORWARD_ROW2 *row, uint8 *old_endpoint_to_delete) {
|
static bool IsDestinationRouteEqualTo(MIB_IPFORWARD_ROW2 *row, const WgCidrAddr *addr) {
|
||||||
if (!(row->Protocol == MIB_IPPROTO_NETMGMT && row->DestinationPrefix.Prefix.si_family == family))
|
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;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,17 +354,18 @@ static void DeleteRouteOrPrintErr(MIB_IPFORWARD_ROW2 *row) {
|
||||||
(void*)&row->DestinationPrefix.Prefix.Ipv6.sin6_addr, row->DestinationPrefix.PrefixLength));
|
(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;
|
MIB_IPFORWARD_TABLE2 *table = NULL;
|
||||||
|
|
||||||
assert(family == AF_INET || family == AF_INET6);
|
assert(family == AF_INET || family == AF_INET6);
|
||||||
|
|
||||||
|
ri->found_default_adapter = false;
|
||||||
|
ri->found_null_routes = 0;
|
||||||
|
|
||||||
if (GetIpForwardTable2(family, &table))
|
if (GetIpForwardTable2(family, &table))
|
||||||
return false;
|
return false;
|
||||||
DWORD rv = 0;
|
DWORD rv = 0;
|
||||||
DWORD gw_metric = 0xffffffff;
|
DWORD gw_metric = 0xffffffff;
|
||||||
ri->found_default_adapter = false;
|
|
||||||
ri->found_null_routes = 0;
|
|
||||||
for (unsigned i = 0; i < table->NumEntries; i++) {
|
for (unsigned i = 0; i < table->NumEntries; i++) {
|
||||||
MIB_IPFORWARD_ROW2 *row = &table->Table[i];
|
MIB_IPFORWARD_ROW2 *row = &table->Table[i];
|
||||||
if (InterfaceLuid && memcmp(&row->InterfaceLuid, InterfaceLuid, sizeof(NET_LUID)) == 0) {
|
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) {
|
if (old_endpoint_to_delete && ri->found_default_adapter) {
|
||||||
for (unsigned i = 0; i < table->NumEntries; i++) {
|
for (unsigned i = 0; i < table->NumEntries; i++) {
|
||||||
MIB_IPFORWARD_ROW2 *row = &table->Table[i];
|
MIB_IPFORWARD_ROW2 *row = &table->Table[i];
|
||||||
if (memcmp(&row->InterfaceLuid, &ri->default_adapter, sizeof(NET_LUID)) == 0) {
|
if (row->Protocol == MIB_IPPROTO_NETMGMT && memcmp(&row->InterfaceLuid, &ri->default_adapter, sizeof(NET_LUID)) == 0) {
|
||||||
if (IsRouteTheAddressOfTheServer(family, row, old_endpoint_to_delete))
|
if (IsDestinationRouteEqualToAny(row, *old_endpoint_to_delete))
|
||||||
DeleteRouteOrPrintErr(row);
|
DeleteRouteOrPrintErr(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1008,31 +1020,45 @@ static void AssignIpv6Address(const void *new_address, int new_cidr, WgCidrAddr
|
||||||
memcpy(target->addr, new_address, 16);
|
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.
|
// 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;
|
NETIO_STATUS Status;
|
||||||
PMIB_UNICASTIPADDRESS_TABLE table = NULL;
|
PMIB_UNICASTIPADDRESS_TABLE table = NULL;
|
||||||
|
|
||||||
if (old_address)
|
if (old_address)
|
||||||
memset(old_address, 0, sizeof(WgCidrAddr));
|
old_address->clear();
|
||||||
|
|
||||||
Status = GetUnicastIpAddressTable(AF_INET6, &table);
|
Status = GetUnicastIpAddressTable(AF_INET6, &table);
|
||||||
if (Status != 0) {
|
if (Status != 0) {
|
||||||
RERROR("GetUnicastAddressTable Failed. Error %d\n", Status);
|
RERROR("GetUnicastAddressTable Failed. Error %d\n", Status);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
uint64 matching_addr = 0;
|
||||||
bool found_row = false;
|
|
||||||
for (int i = 0; i < (int)table->NumEntries; i++) {
|
for (int i = 0; i < (int)table->NumEntries; i++) {
|
||||||
MIB_UNICASTIPADDRESS_ROW *row = &table->Table[i];
|
MIB_UNICASTIPADDRESS_ROW *row = &table->Table[i];
|
||||||
if (!memcmp(&row->InterfaceLuid, InterfaceLuid, sizeof(NET_LUID))) {
|
if (!memcmp(&row->InterfaceLuid, InterfaceLuid, sizeof(NET_LUID))) {
|
||||||
if (row->PrefixOrigin == 1 && row->SuffixOrigin == 1) {
|
if (row->PrefixOrigin == 1 && row->SuffixOrigin == 1) {
|
||||||
if (row->OnLinkPrefixLength == new_cidr && !memcmp(&row->Address.Ipv6.sin6_addr, new_address, 16)) {
|
if (old_address) {
|
||||||
found_row = true;
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (old_address != NULL)
|
|
||||||
AssignIpv6Address(&row->Address.Ipv6.sin6_addr, row->OnLinkPrefixLength, old_address);
|
|
||||||
Status = DeleteUnicastIpAddressEntry(row);
|
Status = DeleteUnicastIpAddressEntry(row);
|
||||||
if (Status)
|
if (Status)
|
||||||
RERROR("Error %d deleting IPv6 address: %s/%d", Status, PrintIPV6((uint8*)&row->Address.Ipv6.sin6_addr), row->OnLinkPrefixLength);
|
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);
|
FreeMibTable(table);
|
||||||
|
|
||||||
if (found_row) {
|
// Add all ipv6 addresses that were not already set.
|
||||||
RINFO("Using IPv6 address: %s/%d", PrintIPV6(new_address), new_cidr);
|
bool success = true;
|
||||||
return true;
|
int i = 0;
|
||||||
}
|
for (auto it = addresses.begin(); it != addresses.end(); ++it, i++) {
|
||||||
|
// skip it because of wrong type or already set?
|
||||||
if (!IsIpv6AddressSet(new_address))
|
if (it->size != 128 || i < 64 && (matching_addr & ((uint64)1 << i)))
|
||||||
return true;
|
continue;
|
||||||
|
|
||||||
if (old_address != NULL)
|
|
||||||
old_address->size = 128;
|
|
||||||
|
|
||||||
MIB_UNICASTIPADDRESS_ROW Row;
|
MIB_UNICASTIPADDRESS_ROW Row;
|
||||||
InitializeUnicastIpAddressEntry(&Row);
|
InitializeUnicastIpAddressEntry(&Row);
|
||||||
Row.OnLinkPrefixLength = new_cidr;
|
Row.OnLinkPrefixLength = it->cidr;
|
||||||
Row.Address.si_family = AF_INET6;
|
Row.Address.si_family = AF_INET6;
|
||||||
memcpy(&Row.Address.Ipv6.sin6_addr, new_address, 16);
|
memcpy(&Row.Address.Ipv6.sin6_addr, it->addr, 16);
|
||||||
Row.InterfaceLuid = *InterfaceLuid;
|
Row.InterfaceLuid = *InterfaceLuid;
|
||||||
Status = CreateUnicastIpAddressEntry(&Row);
|
Status = CreateUnicastIpAddressEntry(&Row);
|
||||||
if (Status != 0) {
|
if (Status != 0) {
|
||||||
RERROR("Error %d setting IPv6 address: %s/%d", Status, PrintIPV6(new_address), new_cidr);
|
RERROR("Error %d setting IPv6 address: %s/%d", Status, PrintIPV6(it->addr), it->cidr);
|
||||||
return false;
|
success = false;
|
||||||
|
} else {
|
||||||
|
RINFO("Added IPV6 Address: %s/%d", PrintIPV6(it->addr), it->cidr);
|
||||||
}
|
}
|
||||||
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) {
|
static bool SetIPV6DnsOnInterface(NET_LUID *InterfaceLuid, const IpAddr *new_address, size_t new_address_size) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
char ipv6[128];
|
char ipv6[128];
|
||||||
|
bool isfirst = true;
|
||||||
NET_IFINDEX InterfaceIndex;
|
NET_IFINDEX InterfaceIndex;
|
||||||
if (ConvertInterfaceLuidToIndex(InterfaceLuid, &InterfaceIndex))
|
if (ConvertInterfaceLuidToIndex(InterfaceLuid, &InterfaceIndex))
|
||||||
return false;
|
return false;
|
||||||
if (new_address_size) {
|
if (new_address_size) {
|
||||||
for (size_t i = 0; i < new_address_size; i++) {
|
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)))
|
if (!inet_ntop(AF_INET6, (void*)&new_address[i].sin6.sin6_addr, ipv6, sizeof(ipv6)))
|
||||||
return false;
|
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))
|
if (!RunNetsh(buf))
|
||||||
return false;
|
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]) {
|
TunWin32Adapter::TunWin32Adapter(DnsBlocker *dns_blocker, const char guid[ADAPTER_GUID_SIZE]) {
|
||||||
handle_ = NULL;
|
handle_ = NULL;
|
||||||
dns_blocker_ = dns_blocker;
|
dns_blocker_ = dns_blocker;
|
||||||
old_ipv6_address_.size = 0;
|
|
||||||
old_ipv6_metric_ = kMetricNone;
|
old_ipv6_metric_ = kMetricNone;
|
||||||
old_ipv4_metric_ = kMetricNone;
|
old_ipv4_metric_ = kMetricNone;
|
||||||
has_dns6_setting_ = false;
|
has_dns6_setting_ = false;
|
||||||
|
@ -1162,6 +1194,22 @@ bool TunWin32Adapter::OpenAdapter(TunsafeBackendWin32 *backend, DWORD open_flags
|
||||||
return (handle_ != NULL);
|
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) {
|
bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, TunInterface::TunConfigOut *out) {
|
||||||
DWORD len, err;
|
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);
|
pre_down_ = std::move(config.pre_post_commands.pre_down);
|
||||||
post_down_ = std::move(config.pre_post_commands.post_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
|
// Set TAP-Windows TUN subnet mode
|
||||||
if (1) {
|
if (1) {
|
||||||
uint32 v[3];
|
uint32 v[3];
|
||||||
v[0] = htonl(config.ip);
|
v[0] = htonl(ipv4_ip);
|
||||||
v[1] = htonl(config.ip & netmask);
|
v[1] = htonl(ipv4_ip & ipv4_netmask);
|
||||||
v[2] = htonl(netmask);
|
v[2] = htonl(ipv4_netmask);
|
||||||
if (!DeviceIoControl(handle_, TAP_IOCTL_CONFIG_TUN, v, sizeof(v), v, sizeof(v), &len, NULL)) {
|
if (!DeviceIoControl(handle_, TAP_IOCTL_CONFIG_TUN, v, sizeof(v), v, sizeof(v), &len, NULL)) {
|
||||||
RERROR("DeviceIoControl(TAP_IOCTL_CONFIG_TUN) failed");
|
RERROR("DeviceIoControl(TAP_IOCTL_CONFIG_TUN) failed");
|
||||||
return false;
|
return false;
|
||||||
|
@ -1192,9 +1254,9 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
|
||||||
// Set DHCP IP/netmask
|
// Set DHCP IP/netmask
|
||||||
{
|
{
|
||||||
uint32 v[4];
|
uint32 v[4];
|
||||||
v[0] = htonl(config.ip);
|
v[0] = htonl(ipv4_ip);
|
||||||
v[1] = htonl(netmask);
|
v[1] = htonl(ipv4_netmask);
|
||||||
v[2] = htonl((config.ip | ~netmask) - 1); // x.x.x.254
|
v[2] = htonl((ipv4_ip | ~ipv4_netmask) - 1); // x.x.x.254
|
||||||
v[3] = 31536000; // One year
|
v[3] = 31536000; // One year
|
||||||
if (!DeviceIoControl(handle_, TAP_IOCTL_CONFIG_DHCP_MASQ, v, sizeof(v), v, sizeof(v), &len, NULL)) {
|
if (!DeviceIoControl(handle_, TAP_IOCTL_CONFIG_DHCP_MASQ, v, sizeof(v), v, sizeof(v), &len, NULL)) {
|
||||||
RERROR("DeviceIoControl(TAP_IOCTL_CONFIG_DHCP_MASQ) failed");
|
RERROR("DeviceIoControl(TAP_IOCTL_CONFIG_DHCP_MASQ) failed");
|
||||||
|
@ -1202,15 +1264,21 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set DHCP config string
|
// Extract and set IPv4 DNS servers through DHCP
|
||||||
if (config.ipv4_dns.size()) {
|
{
|
||||||
enum { kMaxDnsServers = 4 };
|
enum { kMaxDnsServers = 4 };
|
||||||
uint8 dhcp_options[2 + kMaxDnsServers * 4]; // max 4 dns servers
|
uint8 dhcp_options[2 + kMaxDnsServers * 4]; // max 4 dns servers
|
||||||
size_t num_dns = std::min<size_t>(config.ipv4_dns.size(), kMaxDnsServers);
|
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[0] = 6;
|
||||||
dhcp_options[1] = (uint8)(num_dns * 4);
|
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);
|
DWORD dhcp_options_size = (DWORD)(num_dns * 4 + 2);
|
||||||
byte output[10];
|
byte output[10];
|
||||||
if (!DeviceIoControl(handle_, TAP_IOCTL_CONFIG_DHCP_SET_OPT,
|
if (!DeviceIoControl(handle_, TAP_IOCTL_CONFIG_DHCP_SET_OPT,
|
||||||
|
@ -1219,6 +1287,7 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Get device MAC address
|
// Get device MAC address
|
||||||
if (!DeviceIoControl(handle_, TAP_IOCTL_GET_MAC, mac_adress_, 6, mac_adress_, sizeof(mac_adress_), &len, NULL)) {
|
if (!DeviceIoControl(handle_, TAP_IOCTL_GET_MAC, mac_adress_, 6, mac_adress_, sizeof(mac_adress_), &len, NULL)) {
|
||||||
|
@ -1246,7 +1315,7 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
|
||||||
err = SetMtuOnNetworkAdapter(&interface_luid_, AF_INET, config.mtu);
|
err = SetMtuOnNetworkAdapter(&interface_luid_, AF_INET, config.mtu);
|
||||||
if (err)
|
if (err)
|
||||||
RERROR("SetMtuOnNetworkAdapter IPv4 failed: %d", err);
|
RERROR("SetMtuOnNetworkAdapter IPv4 failed: %d", err);
|
||||||
if (config.ipv6_cidr) {
|
if (ipv6_addr) {
|
||||||
err = SetMtuOnNetworkAdapter(&interface_luid_, AF_INET6, config.mtu);
|
err = SetMtuOnNetworkAdapter(&interface_luid_, AF_INET6, config.mtu);
|
||||||
if (err)
|
if (err)
|
||||||
RERROR("SetMtuOnNetworkAdapter IPv6 failed: %d", err);
|
RERROR("SetMtuOnNetworkAdapter IPv6 failed: %d", err);
|
||||||
|
@ -1254,18 +1323,22 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
|
||||||
}
|
}
|
||||||
|
|
||||||
has_dns6_setting_ = false;
|
has_dns6_setting_ = false;
|
||||||
if (config.ipv6_cidr) {
|
if (ipv6_addr) {
|
||||||
SetIPV6AddressOnInterface(&interface_luid_, config.ipv6_address, config.ipv6_cidr, &old_ipv6_address_);
|
SetIPV6AddressOnInterface(&interface_luid_, config.addresses, &old_ipv6_address_);
|
||||||
|
|
||||||
if (config.ipv6_dns.size()) {
|
// 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;
|
has_dns6_setting_ = true;
|
||||||
if (!SetIPV6DnsOnInterface(&interface_luid_, config.ipv6_dns.data(), config.ipv6_dns.size())) {
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (has_dns6_setting_ && !SetIPV6DnsOnInterface(&interface_luid_, config.dns.data(), config.dns.size())) {
|
||||||
RERROR("SetIPV6DnsOnInterface: failed");
|
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");
|
RINFO("Blocking standard DNS on all adapters");
|
||||||
dns_blocker_->BlockDnsExceptOnAdapter(interface_luid_, has_dns6_setting_);
|
dns_blocker_->BlockDnsExceptOnAdapter(interface_luid_, has_dns6_setting_);
|
||||||
|
|
||||||
|
@ -1273,7 +1346,7 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
|
||||||
if (err)
|
if (err)
|
||||||
RERROR("SetMetricOnNetworkAdapter IPv4 failed: %d", err);
|
RERROR("SetMetricOnNetworkAdapter IPv4 failed: %d", err);
|
||||||
|
|
||||||
if (config.ipv6_cidr) {
|
if (ipv6_addr) {
|
||||||
err = SetMetricOnNetworkAdapter(&interface_luid_, AF_INET6, 2, &old_ipv6_metric_);
|
err = SetMetricOnNetworkAdapter(&interface_luid_, AF_INET6, 2, &old_ipv6_metric_);
|
||||||
if (err)
|
if (err)
|
||||||
RERROR("SetMetricOnNetworkAdapter IPv6 failed: %d", err);
|
RERROR("SetMetricOnNetworkAdapter IPv6 failed: %d", err);
|
||||||
|
@ -1289,24 +1362,16 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
|
||||||
|
|
||||||
RouteInfo ri, ri6;
|
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.
|
// 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.");
|
RERROR("Unable to read old default gateway and delete old default routes.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.ipv6_cidr) {
|
|
||||||
// Delete any current /1 default routes and read some stuff from the routing table.
|
// 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)) {
|
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.");
|
RERROR("Unable to read old default gateway and delete old default routes for IPv6.");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
uint32 default_route_v4 = ComputeIpv4DefaultRoute(config.ip, netmask);
|
|
||||||
uint8 default_route_v6[16];
|
|
||||||
|
|
||||||
if (block_all_traffic_route) {
|
if (block_all_traffic_route) {
|
||||||
RINFO("Blocking all regular Internet traffic using routing rules");
|
RINFO("Blocking all regular Internet traffic using routing rules");
|
||||||
|
@ -1317,12 +1382,13 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
|
||||||
g_killswitch_curr |= kBlockInternet_Route;
|
g_killswitch_curr |= kBlockInternet_Route;
|
||||||
|
|
||||||
uint32 dst[4] = {0};
|
uint32 dst[4] = {0};
|
||||||
|
|
||||||
if (!AddMultipleCatchallRoutes(AF_INET, 1, (uint8*)&dst, localhost_luid, NULL)) {
|
if (!AddMultipleCatchallRoutes(AF_INET, 1, (uint8*)&dst, localhost_luid, NULL)) {
|
||||||
RERROR("Unable to add routes for route based blocking.");
|
RERROR("Unable to add routes for route based blocking.");
|
||||||
DeactivateKillSwitch(0);
|
DeactivateKillSwitch(0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (config.ipv6_cidr) {
|
|
||||||
if (!AddMultipleCatchallRoutes(AF_INET6, 1, (uint8*)&dst, localhost_luid, NULL)) {
|
if (!AddMultipleCatchallRoutes(AF_INET6, 1, (uint8*)&dst, localhost_luid, NULL)) {
|
||||||
RERROR("Unable to add IPv6 routes for route based blocking.");
|
RERROR("Unable to add IPv6 routes for route based blocking.");
|
||||||
DeactivateKillSwitch(0);
|
DeactivateKillSwitch(0);
|
||||||
|
@ -1330,13 +1396,11 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (ibs & kBlockInternet_Firewall) {
|
if (ibs & kBlockInternet_Firewall) {
|
||||||
RINFO("Blocking all regular Internet traffic using firewall rules");
|
RINFO("Blocking all regular Internet traffic using firewall rules");
|
||||||
g_killswitch_curr |= kBlockInternet_Firewall;
|
g_killswitch_curr |= kBlockInternet_Firewall;
|
||||||
|
if (!AddKillSwitchFirewall(interface_luid_, true, (ibs & kBlockInternet_AllowLocalNetworks) != 0)) {
|
||||||
if (!AddKillSwitchFirewall(interface_luid_, config.ipv6_cidr != 0, (ibs & kBlockInternet_AllowLocalNetworks) != 0)) {
|
|
||||||
RERROR("Unable to activate firewall based kill switch");
|
RERROR("Unable to activate firewall based kill switch");
|
||||||
DeactivateKillSwitch(0);
|
DeactivateKillSwitch(0);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1345,63 +1409,54 @@ bool TunWin32Adapter::ConfigureAdapter(const TunInterface::TunConfig &&config, T
|
||||||
|
|
||||||
DeactivateKillSwitch(ibs);
|
DeactivateKillSwitch(ibs);
|
||||||
|
|
||||||
// Configure default route?
|
uint8 default_route_v4[4];
|
||||||
if (config.use_ipv4_default_route) {
|
uint8 default_route_v6[16];
|
||||||
// Add a bypass route to the original gateway?
|
|
||||||
if (config.default_route_endpoint_v4 != 0) {
|
WriteBE32(default_route_v4, ComputeIpv4DefaultRoute(ipv4_ip, ipv4_netmask));
|
||||||
if (!ri.found_default_adapter) {
|
if (ipv6_addr)
|
||||||
RERROR("Unable to read old ipv4 default gateway");
|
ComputeIpv6DefaultRoute(ipv6_addr->addr, ipv6_addr->cidr, default_route_v6);
|
||||||
return false;
|
|
||||||
}
|
// Add all the routes that should go through the VPN
|
||||||
if (!AddRoute(AF_INET, &default_route_endpoint_v4, 32, ri.default_gw, &ri.default_adapter, &routes_to_undo_)) {
|
for (auto it = config.included_routes.begin(); it != config.included_routes.end(); ++it) {
|
||||||
RERROR("Unable to add ipv4 gateway bypass route.");
|
if (it->cidr == 0) {
|
||||||
return false;
|
// /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_))
|
||||||
// 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.");
|
RERROR("Unable to add new default ipv4 route.");
|
||||||
}
|
} else if (it->size == 128 && ipv6_addr) {
|
||||||
|
|
||||||
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_))
|
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.");
|
RERROR("Unable to add new default ipv6 route.");
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
// Avoid adding a route if it's a subset of the address
|
||||||
|
if (IsWgCidrAddrSubsetOfAny(*it, config.addresses))
|
||||||
|
continue;
|
||||||
|
|
||||||
// Add all the extra routes
|
|
||||||
for (auto it = config.extra_routes.begin(); it != config.extra_routes.end(); ++it) {
|
|
||||||
if (it->size == 32) {
|
if (it->size == 32) {
|
||||||
uint32 be = ToBE32(default_route_v4);
|
AddRoute(AF_INET, it->addr, it->cidr, default_route_v4, &interface_luid_, &routes_to_undo_);
|
||||||
AddRoute(AF_INET, it->addr, it->cidr, &be, &interface_luid_, &routes_to_undo_);
|
} else if (it->size == 128 && ipv6_addr) {
|
||||||
} else if (it->size == 128 && config.ipv6_cidr) {
|
|
||||||
AddRoute(AF_INET6, it->addr, it->cidr, default_route_v6, &interface_luid_, &routes_to_undo_);
|
AddRoute(AF_INET6, it->addr, it->cidr, default_route_v6, &interface_luid_, &routes_to_undo_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all the routes that should bypass vpn
|
// 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 (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_);
|
AddRoute(AF_INET, it->addr, it->cidr, ri.default_gw, &ri.default_adapter, &routes_to_undo_);
|
||||||
} else if (it->size == 128 && config.ipv6_cidr) {
|
} else if (!(warned & 1)) {
|
||||||
if (ri6.found_default_adapter)
|
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_);
|
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);
|
RERROR("FlushIpNetTable failed: 0x%X", err);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (config.ipv6_cidr) {
|
if (ipv6_addr != NULL) {
|
||||||
if ((err = FlushIpNetTable2(AF_INET6, InterfaceIndex)) != NO_ERROR) {
|
if ((err = FlushIpNetTable2(AF_INET6, InterfaceIndex)) != NO_ERROR) {
|
||||||
RERROR("FlushIpNetTable failed: 0x%X", err);
|
RERROR("FlushIpNetTable failed: 0x%X", err);
|
||||||
return false;
|
return false;
|
||||||
|
@ -1439,8 +1494,8 @@ void TunWin32Adapter::CloseAdapter(bool is_restart) {
|
||||||
TunAdaptersInUse::GetInstance()->Release(backend_);
|
TunAdaptersInUse::GetInstance()->Release(backend_);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old_ipv6_address_.size != 0)
|
if (old_ipv6_address_.size())
|
||||||
SetIPV6AddressOnInterface(&interface_luid_, old_ipv6_address_.addr, old_ipv6_address_.cidr, NULL);
|
SetIPV6AddressOnInterface(&interface_luid_, old_ipv6_address_, NULL);
|
||||||
if (old_ipv4_metric_ != kMetricNone)
|
if (old_ipv4_metric_ != kMetricNone)
|
||||||
SetMetricOnNetworkAdapter(&interface_luid_, AF_INET, old_ipv4_metric_, NULL);
|
SetMetricOnNetworkAdapter(&interface_luid_, AF_INET, old_ipv4_metric_, NULL);
|
||||||
if (old_ipv6_metric_ != kMetricNone)
|
if (old_ipv6_metric_ != kMetricNone)
|
||||||
|
@ -1449,7 +1504,7 @@ void TunWin32Adapter::CloseAdapter(bool is_restart) {
|
||||||
SetIPV6DnsOnInterface(&interface_luid_, NULL, 0);
|
SetIPV6DnsOnInterface(&interface_luid_, NULL, 0);
|
||||||
|
|
||||||
old_ipv4_metric_ = old_ipv6_metric_ = -1;
|
old_ipv4_metric_ = old_ipv6_metric_ = -1;
|
||||||
old_ipv6_address_.size = 0;
|
old_ipv6_address_.clear();
|
||||||
has_dns6_setting_ = false;
|
has_dns6_setting_ = false;
|
||||||
|
|
||||||
for (auto it = routes_to_undo_.begin(); it != routes_to_undo_.end(); ++it)
|
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() {
|
void TunsafeBackendWin32::OnConnected() {
|
||||||
if (status_ != TunsafeBackend::kStatusConnected) {
|
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) {
|
if (status_ != TunsafeBackend::kStatusReconnecting) {
|
||||||
char buf[kSizeOfAddress];
|
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);
|
SetStatus(TunsafeBackend::kStatusConnected);
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,7 +118,7 @@ private:
|
||||||
|
|
||||||
int old_ipv4_metric_, old_ipv6_metric_;
|
int old_ipv4_metric_, old_ipv6_metric_;
|
||||||
|
|
||||||
WgCidrAddr old_ipv6_address_;
|
std::vector<WgCidrAddr> old_ipv6_address_;
|
||||||
|
|
||||||
NET_LUID interface_luid_;
|
NET_LUID interface_luid_;
|
||||||
|
|
||||||
|
|
132
wireguard.cpp
132
wireguard.cpp
|
@ -23,8 +23,6 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
WireguardProcessor::WireguardProcessor(UdpInterface *udp, TunInterface *tun, ProcessorDelegate *procdel) {
|
WireguardProcessor::WireguardProcessor(UdpInterface *udp, TunInterface *tun, ProcessorDelegate *procdel) {
|
||||||
tun_addr_.size = 0;
|
|
||||||
tun6_addr_.size = 0;
|
|
||||||
udp_ = udp;
|
udp_ = udp;
|
||||||
tun_ = tun;
|
tun_ = tun;
|
||||||
procdel_ = procdel;
|
procdel_ = procdel;
|
||||||
|
@ -54,21 +52,16 @@ void WireguardProcessor::SetListenPort(int listen_port) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WireguardProcessor::AddDnsServer(const IpAddr &sin) {
|
void WireguardProcessor::AddDnsServer(const IpAddr &sin) {
|
||||||
std::vector<IpAddr> *target = (sin.sin.sin_family == AF_INET6) ? &dns6_addr_ : &dns_addr_;
|
dns_addr_.push_back(sin);
|
||||||
target->push_back(sin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WireguardProcessor::SetTunAddress(const WgCidrAddr &addr) {
|
bool WireguardProcessor::SetTunAddress(const WgCidrAddr &addr) {
|
||||||
WgCidrAddr *target = (addr.size == 128) ? &tun6_addr_ : &tun_addr_;
|
addresses_.push_back(addr);
|
||||||
if (target->size != 0)
|
|
||||||
return false;
|
|
||||||
*target = addr;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WireguardProcessor::ClearTunAddress() {
|
void WireguardProcessor::ClearTunAddress() {
|
||||||
tun_addr_.size = 0;
|
addresses_.clear();
|
||||||
tun6_addr_.size = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WireguardProcessor::AddExcludedIp(const WgCidrAddr &cidr_addr) {
|
void WireguardProcessor::AddExcludedIp(const WgCidrAddr &cidr_addr) {
|
||||||
|
@ -118,19 +111,32 @@ void WireguardProcessor::SetupCompressionHeader(WgPacketCompressionVer01 *c) {
|
||||||
c->ttl = 64;
|
c->ttl = 64;
|
||||||
#endif // defined(OS_WIN)
|
#endif // defined(OS_WIN)
|
||||||
WriteLE16(&c->version, EXT_PACKET_COMPRESSION_VER);
|
WriteLE16(&c->version, EXT_PACKET_COMPRESSION_VER);
|
||||||
memcpy(c->ipv4_addr, &tun_addr_.addr, 4);
|
|
||||||
if (tun6_addr_.size == 128)
|
for (auto it = addresses_.begin(); it != addresses_.end(); ++it) {
|
||||||
memcpy(c->ipv6_addr, &tun6_addr_.addr, 16);
|
if (it->size == 32) {
|
||||||
c->flags = ((tun_addr_.cidr >> 3) & 3);
|
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) {
|
static WgCidrAddr WgCidrAddrFromIpAddr(const IpAddr &addr) {
|
||||||
return memcmp(a, b, n >> 3) == 0 && ((n & 7) == 0 || !((a[n >> 3] ^ b[n >> 3]) & (0xff << (8 - (n & 7)))));
|
WgCidrAddr r = {0};
|
||||||
}
|
if (addr.sin.sin_family == AF_INET) {
|
||||||
|
r.size = r.cidr = 32;
|
||||||
static bool IsWgCidrAddrSubsetOf(const WgCidrAddr &inner, const WgCidrAddr &outer) {
|
memcpy(r.addr, &addr.sin.sin_addr, 4);
|
||||||
return inner.size == outer.size && inner.cidr >= outer.cidr &&
|
} else if (addr.sin.sin_family == AF_INET6) {
|
||||||
CheckFirstNbitsEquals(inner.addr, outer.addr, outer.cidr);
|
r.size = r.cidr = 128;
|
||||||
|
memcpy(r.addr, &addr.sin6.sin6_addr, 16);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WireguardProcessor::Start() {
|
bool WireguardProcessor::Start() {
|
||||||
|
@ -146,74 +152,52 @@ bool WireguardProcessor::ConfigureTun() {
|
||||||
assert(dev_.IsMainThread());
|
assert(dev_.IsMainThread());
|
||||||
|
|
||||||
TunInterface::TunConfig config = {0};
|
TunInterface::TunConfig config = {0};
|
||||||
if (tun_addr_.size == 32) {
|
uint32 ipv4_broadcast_addr = 0xffffffff;
|
||||||
if (tun_addr_.cidr >= 31) {
|
|
||||||
RERROR("TAP is not compatible CIDR /31 or /32. Changing to /24");
|
for (auto it = addresses_.begin(); it != addresses_.end(); ++it) {
|
||||||
tun_addr_.cidr = 24;
|
if (it->size == 32) {
|
||||||
|
if (it->cidr >= 31) {
|
||||||
|
RINFO("TAP is not compatible CIDR /31 or /32. Changing to /24");
|
||||||
|
it->cidr = 24;
|
||||||
}
|
}
|
||||||
config.ip = ReadBE32(tun_addr_.addr);
|
|
||||||
config.cidr = tun_addr_.cidr;
|
// Packets to this IP will not be sent out.
|
||||||
} else {
|
if (ipv4_broadcast_addr == 0xffffffff) {
|
||||||
RERROR("No IPv4 address configured");
|
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.mtu = mtu_;
|
||||||
config.pre_post_commands = pre_post_;
|
config.pre_post_commands = pre_post_;
|
||||||
config.excluded_ips = excluded_ips_;
|
config.excluded_routes = excluded_ips_;
|
||||||
|
|
||||||
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_) {
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// For each peer, add the extra routes to the extra routes table
|
// For each peer, add the extra routes to the extra routes table
|
||||||
for (WgPeer *peer = dev_.first_peer(); peer; peer = peer->next_peer_) {
|
for (WgPeer *peer = dev_.first_peer(); peer; peer = peer->next_peer_) {
|
||||||
for (auto it = peer->allowed_ips_.begin(); it != peer->allowed_ips_.end(); ++it) {
|
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
|
config.included_routes.push_back(*it);
|
||||||
if (IsWgCidrAddrSubsetOf(*it, tun_addr_) || IsWgCidrAddrSubsetOf(*it, tun6_addr_) || it->cidr == 0)
|
// If peer has the ::/0 or 0.0.0.0/0 address, disallow endpoint change.
|
||||||
continue;
|
if (it->cidr == 0)
|
||||||
// Don't add an entry if we have no ipv6 address configured
|
peer->allow_endpoint_change_ = false;
|
||||||
if (config.ipv6_cidr == 0 && it->size != 32)
|
|
||||||
continue;
|
|
||||||
config.extra_routes.push_back(*it);
|
|
||||||
}
|
}
|
||||||
|
// 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.block_dns_on_adapters = dns_blocking_;
|
||||||
(config.use_ipv6_default_route && dns6_addr_.size()));
|
|
||||||
config.internet_blocking = internet_blocking_;
|
config.internet_blocking = internet_blocking_;
|
||||||
|
config.dns = dns_addr_;
|
||||||
config.ipv4_dns = dns_addr_;
|
|
||||||
config.ipv6_dns = dns6_addr_;
|
|
||||||
|
|
||||||
TunInterface::TunConfigOut config_out;
|
TunInterface::TunConfigOut config_out;
|
||||||
if (!tun_->Configure(std::move(config), &config_out))
|
if (!tun_->Configure(std::move(config), &config_out))
|
||||||
|
|
|
@ -99,8 +99,7 @@ public:
|
||||||
|
|
||||||
WgDevice &dev() { return dev_; }
|
WgDevice &dev() { return dev_; }
|
||||||
TunInterface::PrePostCommands &prepost() { return pre_post_; }
|
TunInterface::PrePostCommands &prepost() { return pre_post_; }
|
||||||
const WgCidrAddr &tun_addr() { return tun_addr_; }
|
const std::vector<WgCidrAddr> &addr() { return addresses_; }
|
||||||
|
|
||||||
void RunAllMainThreadScheduled();
|
void RunAllMainThreadScheduled();
|
||||||
private:
|
private:
|
||||||
void DoWriteUdpPacket(Packet *packet);
|
void DoWriteUdpPacket(Packet *packet);
|
||||||
|
@ -138,12 +137,10 @@ private:
|
||||||
|
|
||||||
WgDevice dev_;
|
WgDevice dev_;
|
||||||
|
|
||||||
WgCidrAddr tun_addr_;
|
|
||||||
WgCidrAddr tun6_addr_;
|
|
||||||
|
|
||||||
WgProcessorStats stats_;
|
WgProcessorStats stats_;
|
||||||
|
|
||||||
std::vector<IpAddr> dns_addr_, dns6_addr_;
|
std::vector<WgCidrAddr> addresses_;
|
||||||
|
std::vector<IpAddr> dns_addr_;
|
||||||
|
|
||||||
TunInterface::PrePostCommands pre_post_;
|
TunInterface::PrePostCommands pre_post_;
|
||||||
|
|
||||||
|
|
|
@ -379,10 +379,8 @@ void WgConfig::HandleConfigurationProtocolGet(WireguardProcessor *proc, std::str
|
||||||
CmsgAppendHex(result, "private_key", proc->dev_.s_priv_, sizeof(proc->dev_.s_priv_));
|
CmsgAppendHex(result, "private_key", proc->dev_.s_priv_, sizeof(proc->dev_.s_priv_));
|
||||||
if (proc->listen_port_)
|
if (proc->listen_port_)
|
||||||
CmsgAppendFmt(result, "listen_port=%d", proc->listen_port_);
|
CmsgAppendFmt(result, "listen_port=%d", proc->listen_port_);
|
||||||
if (proc->tun_addr_.size == 32)
|
for(const WgCidrAddr &x : proc->addresses_)
|
||||||
CmsgAppendFmt(result, "address=%s", PrintWgCidrAddr(proc->tun_addr_, buf));
|
CmsgAppendFmt(result, "address=%s", PrintWgCidrAddr(x, buf));
|
||||||
if (proc->tun6_addr_.size == 128)
|
|
||||||
CmsgAppendFmt(result, "address=%s", PrintWgCidrAddr(proc->tun6_addr_, buf));
|
|
||||||
|
|
||||||
for (WgPeer *peer = proc->dev_.peers_; peer; peer = peer->next_peer_) {
|
for (WgPeer *peer = proc->dev_.peers_; peer; peer = peer->next_peer_) {
|
||||||
WG_SCOPED_LOCK(peer->lock_);
|
WG_SCOPED_LOCK(peer->lock_);
|
||||||
|
|
Loading…
Reference in a new issue