diff --git a/netapi.h b/netapi.h index 268ce69..8fee819 100644 --- a/netapi.h +++ b/netapi.h @@ -38,12 +38,26 @@ struct QueuedItem { #define Packet_NEXT(p) (*(Packet**)&(p)->queue_next) +// Protocol types used in the Endpoint thing +enum { + // The standard wireguard protocol + kPacketProtocolUdp = 1, + + // Wireguard UDP framed inside of TCP + kPacketProtocolTcp = 2, + + // This is OR:ed with the value in case it's an incoming connection + // and it's not possible to connect back to it, e.g. incoming tcp + kPacketProtocolIncomingConnection = 0x80, +}; + struct Packet : QueuedItem { int sin_size; unsigned int size; byte *data; uint8 userdata; + uint8 protocol; // which protocol is this packet for/from IpAddr addr; // Optionally set to target/source of the packet byte data_pre[4]; diff --git a/tunsafe_win32.cpp b/tunsafe_win32.cpp index 1199e46..02d21ec 100644 --- a/tunsafe_win32.cpp +++ b/tunsafe_win32.cpp @@ -1540,11 +1540,18 @@ static const char *GetAdvancedInfoValue(char buffer[256], int i) { char ip[kSizeOfAddress]; if (ps->endpoint.sin.sin_family == 0) return ""; + char *p = buffer; + + if (ps->endpoint_protocol == kPacketProtocolTcp) { + memcpy(p, "tcp://", 6); + p += 6; + } + PrintIpAddr(ps->endpoint, ip); if (ps->endpoint.sin.sin_family == AF_INET6) { - snprintf(buffer, 256, "[%s]:%d", ip, htons(ps->endpoint.sin.sin_port)); + snprintf(p, 256-16, "[%s]:%d", ip, htons(ps->endpoint.sin.sin_port)); } else { - snprintf(buffer, 256, "%s:%d", ip, htons(ps->endpoint.sin.sin_port)); + snprintf(p, 256-16, "%s:%d", ip, htons(ps->endpoint.sin.sin_port)); } return buffer; } diff --git a/wireguard.cpp b/wireguard.cpp index d565dfe..1947dd1 100644 --- a/wireguard.cpp +++ b/wireguard.cpp @@ -93,8 +93,10 @@ const WgProcessorStats &WireguardProcessor::GetStats() { // todo: only supports one peer but i want this in the ui for now. stats_.endpoint.sin.sin_family = 0; WgPeer *peer = dev_.first_peer(); - if (peer) + if (peer) { stats_.endpoint = peer->endpoint_; + stats_.endpoint_protocol = peer->endpoint_protocol_; + } return stats_; } @@ -426,6 +428,7 @@ void WireguardProcessor::WriteAndEncryptPacketToUdp_WillUnlock(WgPeer *peer, Pac keypair->send_key_state == WgKeypair::KEY_WANT_REFRESH); keypair->send_ctr = send_ctr + 1; packet->addr = peer->endpoint_; + packet->protocol = peer->endpoint_protocol_; if (size == 0) { peer->OnKeepaliveSent(); @@ -641,6 +644,7 @@ void WireguardProcessor::SendHandshakeInitiation(WgPeer *peer) { procdel_->OnConnectionRetry(attempts); peer->OnHandshakeInitSent(); packet->addr = peer->endpoint_; + packet->protocol = peer->endpoint_protocol_; peer->tx_bytes_ += packet->size; WG_RELEASE_LOCK(peer->mutex_); DoWriteUdpPacket(packet); @@ -723,7 +727,7 @@ static uint32 CompareIpAddr(const IpAddr *a, const IpAddr *b) { void WgPeer::CopyEndpointToPeer_Locked(WgKeypair *keypair, const IpAddr *addr) { // Remember how to send packets to this peer if (keypair->peer->allow_endpoint_change_ && - CompareIpAddr(&keypair->peer->endpoint_, addr)) { + CompareIpAddr(&keypair->peer->endpoint_, addr) && addr->sin.sin_family != 0) { #if WITH_SHORT_HEADERS // When the endpoint changes, forget about using the short key. keypair->broadcast_short_key = 0; @@ -1032,7 +1036,7 @@ void WireguardProcessor::HandleHandshakeResponsePacket(Packet *packet) { if (peer) { stats_.handshakes_out_success++; WG_SCOPED_LOCK(peer->mutex_); - if (peer->allow_endpoint_change_) + if (peer->allow_endpoint_change_ && packet->addr.sin.sin_family != 0) peer->endpoint_ = packet->addr; peer->OnHandshakeAuthComplete(); peer->OnHandshakeFullyComplete(); diff --git a/wireguard.h b/wireguard.h index b0b3fa4..70ccddb 100644 --- a/wireguard.h +++ b/wireguard.h @@ -43,6 +43,8 @@ struct WgProcessorStats { // Address of the endpoint IpAddr endpoint; + + uint8 endpoint_protocol; }; class ProcessorDelegate { diff --git a/wireguard_config.cpp b/wireguard_config.cpp index b20cba3..007517a 100644 --- a/wireguard_config.cpp +++ b/wireguard_config.cpp @@ -212,9 +212,14 @@ bool WgFileParser::ParseFlag(const char *group, const char *key, char *value) { return false; } } else if (strcmp(key, "Endpoint") == 0) { + int proto = kPacketProtocolUdp; + if (strncmp(value, "tcp://", 6) == 0) { + value += 6; + proto = kPacketProtocolTcp; + } if (!ParseSockaddrInWithPort(value, &sin, dns_resolver_)) return false; - peer_->SetEndpoint(sin); + peer_->SetEndpoint(proto, sin); } else if (strcmp(key, "PersistentKeepalive") == 0) { if (!peer_->SetPersistentKeepalive(atoi(value))) return false; @@ -470,7 +475,7 @@ bool WgConfig::HandleConfigurationProtocolMessage(WireguardProcessor *proc, cons peer->SetPresharedKey(buf32); } else if (strcmp(key, "endpoint") == 0) { if (!ParseSockaddrInWithPort(value, &sin, NULL)) goto getout_fail; - peer->SetEndpoint(sin); + peer->SetEndpoint(kPacketProtocolUdp, sin); } else if (strcmp(key, "persistent_keepalive_interval") == 0) { if (!peer->SetPersistentKeepalive(atoi(value))) goto getout_fail; diff --git a/wireguard_proto.cpp b/wireguard_proto.cpp index c2bc048..fc5efb3 100644 --- a/wireguard_proto.cpp +++ b/wireguard_proto.cpp @@ -348,6 +348,7 @@ WgPeer::WgPeer(WgDevice *dev) { assert(dev->IsMainThread()); dev_ = dev; endpoint_.sin.sin_family = 0; + endpoint_protocol_ = 0; next_peer_ = NULL; curr_keypair_ = next_keypair_ = prev_keypair_ = NULL; expect_cookie_reply_ = false; @@ -1265,7 +1266,8 @@ void WgPeer::CheckAndUpdateTimeOfNextKeyEvent(uint64 now) { time_of_next_key_event_ = next_time; } -void WgPeer::SetEndpoint(const IpAddr &sin) { +void WgPeer::SetEndpoint(int endpoint_proto, const IpAddr &sin) { + endpoint_protocol_ = endpoint_proto; endpoint_ = sin; } diff --git a/wireguard_proto.h b/wireguard_proto.h index c046813..bd16142 100644 --- a/wireguard_proto.h +++ b/wireguard_proto.h @@ -456,7 +456,7 @@ public: void SetPublicKey(const WgPublicKey &spub); void SetPresharedKey(const uint8 preshared_key[WG_SYMMETRIC_KEY_LEN]); bool SetPersistentKeepalive(int persistent_keepalive_secs); - void SetEndpoint(const IpAddr &sin); + void SetEndpoint(int endpoint_proto, const IpAddr &sin); void SetAllowMulticast(bool allow); void SetFeature(int feature, uint8 value); @@ -492,6 +492,9 @@ public: bool IsPeerLocked() { return WG_IF_LOCKS_ENABLED_ELSE(mutex_.IsLocked(), true); } const IpAddr &endpoint() const { return endpoint_; } + uint8 endpoint_protocol() const { return endpoint_protocol_; } + WgPeer *next_peer() { return next_peer_; } + private: static WgKeypair *CreateNewKeypair(bool is_initiator, const uint8 key[WG_HASH_LEN], uint32 send_key_id, const uint8 *extfield, size_t extfield_size); void WriteMacToPacket(const uint8 *data, MessageMacs *mac); @@ -526,9 +529,6 @@ private: // Holds the entry into the key id table during handshake - mt only. uint32 local_key_id_during_hs_; - // Address of peer - IpAddr endpoint_; - enum { kMainThreadScheduled_ScheduleHandshake = 1, }; @@ -564,13 +564,19 @@ private: // Number of handshakes made so far, when this gets too high we stop connecting. uint8 handshake_attempts_; + // What's the protocol of the currently configured endpoint + uint8 endpoint_protocol_; + // Which features are enabled for this peer? uint8 features_[WG_FEATURES_COUNT]; // Queue of packets that will get sent once handshake finishes uint8 num_queued_packets_; Packet *first_queued_packet_, **last_queued_packet_ptr_; - + + // Address of peer + IpAddr endpoint_; + // For statistics uint64 last_handshake_init_timestamp_; uint64 last_complete_handskake_timestamp_;