Add endpoint_protocol field

This commit is contained in:
Ludvig Strigeus 2018-11-16 15:07:52 +01:00
parent 7b6ebc0ed8
commit ddb48a5aff
7 changed files with 53 additions and 13 deletions

View file

@ -38,12 +38,26 @@ struct QueuedItem {
#define Packet_NEXT(p) (*(Packet**)&(p)->queue_next) #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 { struct Packet : QueuedItem {
int sin_size; int sin_size;
unsigned int size; unsigned int size;
byte *data; byte *data;
uint8 userdata; uint8 userdata;
uint8 protocol; // which protocol is this packet for/from
IpAddr addr; // Optionally set to target/source of the packet IpAddr addr; // Optionally set to target/source of the packet
byte data_pre[4]; byte data_pre[4];

View file

@ -1540,11 +1540,18 @@ static const char *GetAdvancedInfoValue(char buffer[256], int i) {
char ip[kSizeOfAddress]; char ip[kSizeOfAddress];
if (ps->endpoint.sin.sin_family == 0) if (ps->endpoint.sin.sin_family == 0)
return ""; return "";
char *p = buffer;
if (ps->endpoint_protocol == kPacketProtocolTcp) {
memcpy(p, "tcp://", 6);
p += 6;
}
PrintIpAddr(ps->endpoint, ip); PrintIpAddr(ps->endpoint, ip);
if (ps->endpoint.sin.sin_family == AF_INET6) { 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 { } 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; return buffer;
} }

View file

@ -93,8 +93,10 @@ const WgProcessorStats &WireguardProcessor::GetStats() {
// todo: only supports one peer but i want this in the ui for now. // todo: only supports one peer but i want this in the ui for now.
stats_.endpoint.sin.sin_family = 0; stats_.endpoint.sin.sin_family = 0;
WgPeer *peer = dev_.first_peer(); WgPeer *peer = dev_.first_peer();
if (peer) if (peer) {
stats_.endpoint = peer->endpoint_; stats_.endpoint = peer->endpoint_;
stats_.endpoint_protocol = peer->endpoint_protocol_;
}
return stats_; return stats_;
} }
@ -426,6 +428,7 @@ void WireguardProcessor::WriteAndEncryptPacketToUdp_WillUnlock(WgPeer *peer, Pac
keypair->send_key_state == WgKeypair::KEY_WANT_REFRESH); keypair->send_key_state == WgKeypair::KEY_WANT_REFRESH);
keypair->send_ctr = send_ctr + 1; keypair->send_ctr = send_ctr + 1;
packet->addr = peer->endpoint_; packet->addr = peer->endpoint_;
packet->protocol = peer->endpoint_protocol_;
if (size == 0) { if (size == 0) {
peer->OnKeepaliveSent(); peer->OnKeepaliveSent();
@ -641,6 +644,7 @@ void WireguardProcessor::SendHandshakeInitiation(WgPeer *peer) {
procdel_->OnConnectionRetry(attempts); procdel_->OnConnectionRetry(attempts);
peer->OnHandshakeInitSent(); peer->OnHandshakeInitSent();
packet->addr = peer->endpoint_; packet->addr = peer->endpoint_;
packet->protocol = peer->endpoint_protocol_;
peer->tx_bytes_ += packet->size; peer->tx_bytes_ += packet->size;
WG_RELEASE_LOCK(peer->mutex_); WG_RELEASE_LOCK(peer->mutex_);
DoWriteUdpPacket(packet); DoWriteUdpPacket(packet);
@ -723,7 +727,7 @@ static uint32 CompareIpAddr(const IpAddr *a, const IpAddr *b) {
void WgPeer::CopyEndpointToPeer_Locked(WgKeypair *keypair, const IpAddr *addr) { void WgPeer::CopyEndpointToPeer_Locked(WgKeypair *keypair, const IpAddr *addr) {
// Remember how to send packets to this peer // Remember how to send packets to this peer
if (keypair->peer->allow_endpoint_change_ && 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 #if WITH_SHORT_HEADERS
// When the endpoint changes, forget about using the short key. // When the endpoint changes, forget about using the short key.
keypair->broadcast_short_key = 0; keypair->broadcast_short_key = 0;
@ -1032,7 +1036,7 @@ void WireguardProcessor::HandleHandshakeResponsePacket(Packet *packet) {
if (peer) { if (peer) {
stats_.handshakes_out_success++; stats_.handshakes_out_success++;
WG_SCOPED_LOCK(peer->mutex_); 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->endpoint_ = packet->addr;
peer->OnHandshakeAuthComplete(); peer->OnHandshakeAuthComplete();
peer->OnHandshakeFullyComplete(); peer->OnHandshakeFullyComplete();

View file

@ -43,6 +43,8 @@ struct WgProcessorStats {
// Address of the endpoint // Address of the endpoint
IpAddr endpoint; IpAddr endpoint;
uint8 endpoint_protocol;
}; };
class ProcessorDelegate { class ProcessorDelegate {

View file

@ -212,9 +212,14 @@ bool WgFileParser::ParseFlag(const char *group, const char *key, char *value) {
return false; return false;
} }
} else if (strcmp(key, "Endpoint") == 0) { } 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_)) if (!ParseSockaddrInWithPort(value, &sin, dns_resolver_))
return false; return false;
peer_->SetEndpoint(sin); peer_->SetEndpoint(proto, sin);
} else if (strcmp(key, "PersistentKeepalive") == 0) { } else if (strcmp(key, "PersistentKeepalive") == 0) {
if (!peer_->SetPersistentKeepalive(atoi(value))) if (!peer_->SetPersistentKeepalive(atoi(value)))
return false; return false;
@ -470,7 +475,7 @@ bool WgConfig::HandleConfigurationProtocolMessage(WireguardProcessor *proc, cons
peer->SetPresharedKey(buf32); peer->SetPresharedKey(buf32);
} else if (strcmp(key, "endpoint") == 0) { } else if (strcmp(key, "endpoint") == 0) {
if (!ParseSockaddrInWithPort(value, &sin, NULL)) goto getout_fail; if (!ParseSockaddrInWithPort(value, &sin, NULL)) goto getout_fail;
peer->SetEndpoint(sin); peer->SetEndpoint(kPacketProtocolUdp, sin);
} else if (strcmp(key, "persistent_keepalive_interval") == 0) { } else if (strcmp(key, "persistent_keepalive_interval") == 0) {
if (!peer->SetPersistentKeepalive(atoi(value))) if (!peer->SetPersistentKeepalive(atoi(value)))
goto getout_fail; goto getout_fail;

View file

@ -348,6 +348,7 @@ WgPeer::WgPeer(WgDevice *dev) {
assert(dev->IsMainThread()); assert(dev->IsMainThread());
dev_ = dev; dev_ = dev;
endpoint_.sin.sin_family = 0; endpoint_.sin.sin_family = 0;
endpoint_protocol_ = 0;
next_peer_ = NULL; next_peer_ = NULL;
curr_keypair_ = next_keypair_ = prev_keypair_ = NULL; curr_keypair_ = next_keypair_ = prev_keypair_ = NULL;
expect_cookie_reply_ = false; expect_cookie_reply_ = false;
@ -1265,7 +1266,8 @@ void WgPeer::CheckAndUpdateTimeOfNextKeyEvent(uint64 now) {
time_of_next_key_event_ = next_time; 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; endpoint_ = sin;
} }

View file

@ -456,7 +456,7 @@ public:
void SetPublicKey(const WgPublicKey &spub); void SetPublicKey(const WgPublicKey &spub);
void SetPresharedKey(const uint8 preshared_key[WG_SYMMETRIC_KEY_LEN]); void SetPresharedKey(const uint8 preshared_key[WG_SYMMETRIC_KEY_LEN]);
bool SetPersistentKeepalive(int persistent_keepalive_secs); bool SetPersistentKeepalive(int persistent_keepalive_secs);
void SetEndpoint(const IpAddr &sin); void SetEndpoint(int endpoint_proto, const IpAddr &sin);
void SetAllowMulticast(bool allow); void SetAllowMulticast(bool allow);
void SetFeature(int feature, uint8 value); void SetFeature(int feature, uint8 value);
@ -492,6 +492,9 @@ public:
bool IsPeerLocked() { return WG_IF_LOCKS_ENABLED_ELSE(mutex_.IsLocked(), true); } bool IsPeerLocked() { return WG_IF_LOCKS_ENABLED_ELSE(mutex_.IsLocked(), true); }
const IpAddr &endpoint() const { return endpoint_; } const IpAddr &endpoint() const { return endpoint_; }
uint8 endpoint_protocol() const { return endpoint_protocol_; }
WgPeer *next_peer() { return next_peer_; }
private: private:
static WgKeypair *CreateNewKeypair(bool is_initiator, const uint8 key[WG_HASH_LEN], uint32 send_key_id, const uint8 *extfield, size_t extfield_size); 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); void WriteMacToPacket(const uint8 *data, MessageMacs *mac);
@ -526,9 +529,6 @@ private:
// Holds the entry into the key id table during handshake - mt only. // Holds the entry into the key id table during handshake - mt only.
uint32 local_key_id_during_hs_; uint32 local_key_id_during_hs_;
// Address of peer
IpAddr endpoint_;
enum { enum {
kMainThreadScheduled_ScheduleHandshake = 1, kMainThreadScheduled_ScheduleHandshake = 1,
}; };
@ -564,6 +564,9 @@ private:
// Number of handshakes made so far, when this gets too high we stop connecting. // Number of handshakes made so far, when this gets too high we stop connecting.
uint8 handshake_attempts_; uint8 handshake_attempts_;
// What's the protocol of the currently configured endpoint
uint8 endpoint_protocol_;
// Which features are enabled for this peer? // Which features are enabled for this peer?
uint8 features_[WG_FEATURES_COUNT]; uint8 features_[WG_FEATURES_COUNT];
@ -571,6 +574,9 @@ private:
uint8 num_queued_packets_; uint8 num_queued_packets_;
Packet *first_queued_packet_, **last_queued_packet_ptr_; Packet *first_queued_packet_, **last_queued_packet_ptr_;
// Address of peer
IpAddr endpoint_;
// For statistics // For statistics
uint64 last_handshake_init_timestamp_; uint64 last_handshake_init_timestamp_;
uint64 last_complete_handskake_timestamp_; uint64 last_complete_handskake_timestamp_;