From a7500473eb3dc9cd3e7acd67644a9f26ff23a113 Mon Sep 17 00:00:00 2001 From: sehraf Date: Wed, 5 Feb 2020 17:56:47 +0100 Subject: [PATCH 1/8] enable DHT stunner --- libretroshare/src/libretroshare.pro | 4 ---- retroshare.pri | 6 ++++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libretroshare/src/libretroshare.pro b/libretroshare/src/libretroshare.pro index cc4e1dc11..ca3554abb 100644 --- a/libretroshare/src/libretroshare.pro +++ b/libretroshare/src/libretroshare.pro @@ -12,10 +12,6 @@ DESTDIR = lib !include("use_libretroshare.pri"):error("Including") -# the dht stunner is used to obtain RS external ip addr. when it is natted -# this system is unreliable and rs supports a newer and better one (asking connected peers) -# CONFIG += useDhtStunner - # treat warnings as error for better removing #QMAKE_CFLAGS += -Werror #QMAKE_CXXFLAGS += -Werror diff --git a/retroshare.pri b/retroshare.pri index 3eea6b95a..fedd39e6a 100644 --- a/retroshare.pri +++ b/retroshare.pri @@ -111,6 +111,12 @@ no_direct_chat:CONFIG -= direct_chat CONFIG *= bitdht no_bitdht:CONFIG -= bitdht +# The DHT stunner is used to determine the NAT type using other RS DHT peers and the STUN (Session Traversal Utilities for NAT) protocol. +# To disable DHT stunner append the following assignation to qmake command line +# "CONFIG+=no_useDhtStunner" +CONFIG *= useDhtStunner +no_useDhtStunner:CONFIG -= useDhtStunner + # To select your MacOsX version append the following assignation to qmake # command line "CONFIG+=rs_macos10.11" where 10.11 depends your version macx:CONFIG *= rs_macos10.11 From 1874241ddd0ba606bce703036373720d7690f72d Mon Sep 17 00:00:00 2001 From: sehraf Date: Wed, 5 Feb 2020 18:25:56 +0100 Subject: [PATCH 2/8] first pass on udpstunner.cc --- libretroshare/src/tcponudp/udpstunner.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libretroshare/src/tcponudp/udpstunner.cc b/libretroshare/src/tcponudp/udpstunner.cc index f7a0ec47a..4cdc52589 100644 --- a/libretroshare/src/tcponudp/udpstunner.cc +++ b/libretroshare/src/tcponudp/udpstunner.cc @@ -164,12 +164,12 @@ int UdpStunner::grabExclusiveMode(std::string holder) /* returns seconds since commsage = 1; } #ifdef DEBUG_UDP_STUNNER_FILTER -#endif std::cerr << "UdpStunner::grabExclusiveMode() SUCCESS. last comms: " << commsage; std::cerr << " ago"; std::cerr << std::endl; std::cerr << "UdpStunner::grabExclusiveMode() Exclusive held by: " << mExclusiveHolder; std::cerr << std::endl; +#endif return commsage; } @@ -181,9 +181,9 @@ int UdpStunner::releaseExclusiveMode(std::string holder, bool forceStun) if (!mExclusiveMode) { #ifdef DEBUG_UDP_STUNNER_FILTER -#endif std::cerr << "UdpStunner::cancelExclusiveMode() ERROR, not in exclusive Mode"; std::cerr << std::endl; +#endif return 0; } @@ -217,10 +217,10 @@ int UdpStunner::releaseExclusiveMode(std::string holder, bool forceStun) } #ifdef DEBUG_UDP_STUNNER_FILTER -#endif std::cerr << "UdpStunner::cancelExclusiveMode() Canceled. Was in ExclusiveMode for: " << now - mExclusiveModeTS; std::cerr << " secs"; std::cerr << std::endl; +#endif return 1; } @@ -947,15 +947,15 @@ bool UdpStunner::locked_recvdStun(const struct sockaddr_in &remote, const str if (remote.sin_addr.s_addr == extaddr.sin_addr.s_addr) { #ifdef DEBUG_UDP_STUNNER -#endif std::cerr << "UdpStunner::locked_recvdStun() WARNING, BAD PEER: "; std::cerr << "Stun Peer Returned its own address: " << rs_inet_ntoa(remote.sin_addr); std::cerr << std::endl; +#endif return false; } #endif - bool found = true; + bool found = false; std::list::iterator it; for(it = mStunList.begin(); it != mStunList.end(); ++it) { From 4095d82a6769942475efc13353742f5c26860223 Mon Sep 17 00:00:00 2001 From: sehraf Date: Wed, 5 Feb 2020 19:01:42 +0100 Subject: [PATCH 3/8] add some documentation to updstunner.h --- libretroshare/src/tcponudp/udpstunner.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/libretroshare/src/tcponudp/udpstunner.h b/libretroshare/src/tcponudp/udpstunner.h index 8365b0fd9..a5ad1583b 100644 --- a/libretroshare/src/tcponudp/udpstunner.h +++ b/libretroshare/src/tcponudp/udpstunner.h @@ -30,10 +30,10 @@ #include "util/rsthreads.h" #include -/* UdpStun. +/** + * @brief The TouStunPeer class * Stuns peers to determine external addresses. */ - class TouStunPeer { public: @@ -53,10 +53,15 @@ class TouStunPeer return; } + /// id for identification std::string id; + /// remote address struct sockaddr_in remote, eaddr; + /// true when a response was received in the past bool response; + /// used to rate limit STUN requests rstime_t lastsend; + /// fail counter for dead/bad peer detection (0 = good) uint32_t failCount; }; @@ -65,6 +70,13 @@ class TouStunPeer * #define UDPSTUN_ALLOW_LOCALNET 1 */ +/** + * @brief The UdpStunner class + * The UDP stunner implements the STUN protocol to determin the NAT type (behind that RS is usually running). + * It maintains a list of DHT peers that are regulary contacted. + * + * The actual NAT type determination logic is located in void pqiNetStateBox::determineNetworkState() + */ class UdpStunner: public UdpSubReceiver { public: @@ -123,7 +135,7 @@ bool locked_checkExternalAddress(); struct sockaddr_in eaddr; /* external addr */ - bool eaddrKnown; + bool eaddrKnown; bool eaddrStable; /* if true then usable. if false -> Symmettric NAT */ rstime_t eaddrTime; @@ -144,7 +156,7 @@ bool locked_checkExternalAddress(); #endif bool mPassiveStunMode; - uint32_t mTargetStunPeriod; + uint32_t mTargetStunPeriod; double mSuccessRate; bool mExclusiveMode; /* when this is switched on, the stunner stays silent (and extAddr is maintained) */ From e91d877af2db177ae26e52bd10aa5101fc9cdb34 Mon Sep 17 00:00:00 2001 From: sehraf Date: Wed, 5 Feb 2020 19:46:29 +0100 Subject: [PATCH 4/8] udpstunner: don't open code header fields, reference and follow (old) RFC --- libretroshare/src/tcponudp/udpstunner.cc | 58 +++++++++++++++--------- libretroshare/src/tcponudp/udpstunner.h | 2 +- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/libretroshare/src/tcponudp/udpstunner.cc b/libretroshare/src/tcponudp/udpstunner.cc index 4cdc52589..1f79d00d8 100644 --- a/libretroshare/src/tcponudp/udpstunner.cc +++ b/libretroshare/src/tcponudp/udpstunner.cc @@ -47,6 +47,12 @@ const uint32_t TOU_STUN_MAX_RECV_RATE = 25; /* every 25 seconds */ const int32_t TOU_STUN_DEFAULT_TARGET_RATE = 15; /* 20 secs is minimum to keep a NAT UDP port open */ const double TOU_SUCCESS_LPF_FACTOR = 0.90; +/* + * based on RFC 3489 + */ +const uint16_t STUN_BINDING_REQUEST = 0x0001; +const uint16_t STUN_BINDING_RESPONSE = 0x0101; + #define EXCLUSIVE_MODE_TIMEOUT 300 UdpStunner::UdpStunner(UdpPublisher *pub) @@ -187,7 +193,6 @@ int UdpStunner::releaseExclusiveMode(std::string holder, bool forceStun) return 0; } - rstime_t now = time(NULL); mExclusiveMode = false; if (forceStun) { @@ -217,6 +222,7 @@ int UdpStunner::releaseExclusiveMode(std::string holder, bool forceStun) } #ifdef DEBUG_UDP_STUNNER_FILTER + rstime_t now = time(NULL); std::cerr << "UdpStunner::cancelExclusiveMode() Canceled. Was in ExclusiveMode for: " << now - mExclusiveModeTS; std::cerr << " secs"; std::cerr << std::endl; @@ -326,7 +332,7 @@ bool UdpStunner::locked_handleStunPkt(void *data, int size, struct sockaddr_in & #endif /* generate a response */ int len; - void *pkt = UdpStun_generate_stun_reply(&from, &len); + void *pkt = UdpStun_generate_stun_reply(&from, &len, data); if (!pkt) return false; @@ -485,7 +491,7 @@ bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr) return false; } - if (htons(((uint16_t *) stun_pkt)[0]) != 0x0101) + if (htons(((uint16_t *) stun_pkt)[0]) != STUN_BINDING_RESPONSE) { /* not a response */ return false; @@ -517,33 +523,41 @@ bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len) } /* just the header */ - ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(0x0001); + ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(STUN_BINDING_REQUEST); ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(20); /* only header */ - /* transaction id - should be random */ - ((uint32_t *) stun_pkt)[1] = (uint32_t) htonl(0x0020); - ((uint32_t *) stun_pkt)[2] = (uint32_t) htonl(0x0121); - ((uint32_t *) stun_pkt)[3] = (uint32_t) htonl(0x0111); - ((uint32_t *) stun_pkt)[4] = (uint32_t) htonl(0x1010); + /* RFC 3489 + * The transaction ID is used to correlate requests and responses. + * + * RFC 5389 introduces a mmgic cokie at the location where preciously the transaction ID was located: + * In RFC 3489 [RFC3489], this field was part of + * the transaction ID; placing the magic cookie in this location allows + * a server to detect if the client will understand certain attributes + * that were added in this revised specification. + */ + ((uint32_t *) stun_pkt)[1] = htonl(RsRandom::random_u32()); + ((uint32_t *) stun_pkt)[2] = htonl(RsRandom::random_u32()); + ((uint32_t *) stun_pkt)[3] = htonl(RsRandom::random_u32()); + ((uint32_t *) stun_pkt)[4] = htonl(RsRandom::random_u32()); *len = 20; return true; } -void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len) +void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void *data) { /* just the header */ void *stun_pkt = rs_malloc(28); - if(!stun_pkt) - return NULL ; + if(!stun_pkt) + return NULL ; - ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(0x0101); + ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(STUN_BINDING_RESPONSE); ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(28); /* only header + 8 byte addr */ - /* transaction id - should be random */ - ((uint32_t *) stun_pkt)[1] = (uint32_t) htonl(0x0f20); - ((uint32_t *) stun_pkt)[2] = (uint32_t) htonl(0x0f21); - ((uint32_t *) stun_pkt)[3] = (uint32_t) htonl(0x0f11); - ((uint32_t *) stun_pkt)[4] = (uint32_t) htonl(0x1010); + /* RFC 3489 + * The Binding Response MUST contain the same transaction ID contained in the Binding Request. + */ + memcpy(&((uint32_t *) stun_pkt)[1], &((uint32_t *) data)[1], 4 * sizeof (uint32_t)); + /* now add address * 0 1 2 3 * @@ -586,20 +600,20 @@ bool UdpStun_isStunPacket(void *data, int size) return false; } - if ((size == 20) && (0x0001 == ntohs(((uint16_t *) data)[0]))) + if ((size == 20) && (STUN_BINDING_REQUEST == ntohs(((uint16_t *) data)[0]))) { #ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() (size=20 & data[0]=0x0001) -> true"; + std::cerr << "UdpStunner::isStunPacket() (size=20 & data[0]=STUN_BINDING_REQUEST) -> true"; std::cerr << std::endl; #endif /* request */ return true; } - if ((size == 28) && (0x0101 == ntohs(((uint16_t *) data)[0]))) + if ((size == 28) && (STUN_BINDING_RESPONSE == ntohs(((uint16_t *) data)[0]))) { #ifdef DEBUG_UDP_STUNNER_FILTER - std::cerr << "UdpStunner::isStunPacket() (size=28 & data[0]=0x0101) -> true"; + std::cerr << "UdpStunner::isStunPacket() (size=28 & data[0]=STUN_BINDING_RESPONSE) -> true"; std::cerr << std::endl; #endif /* response */ diff --git a/libretroshare/src/tcponudp/udpstunner.h b/libretroshare/src/tcponudp/udpstunner.h index a5ad1583b..eb05c2018 100644 --- a/libretroshare/src/tcponudp/udpstunner.h +++ b/libretroshare/src/tcponudp/udpstunner.h @@ -170,7 +170,7 @@ bool locked_checkExternalAddress(); bool UdpStun_isStunPacket(void *data, int size); bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr); -void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len); +void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void* data); bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len); #endif From 6f9d875fc69fab52b20e5f886fc614949d937250 Mon Sep 17 00:00:00 2001 From: sehraf Date: Wed, 5 Feb 2020 20:11:53 +0100 Subject: [PATCH 5/8] * unify CONFIG option for DHT stunner * implement optional (turned off by default) usage of dht stunner to determin external ip (this can be usefull for some corner case setups) --- libretroshare/src/pqi/p3netmgr.cc | 6 ++++-- retroshare.pri | 21 ++++++++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc index 8eebd4c1e..89ff6f0cd 100644 --- a/libretroshare/src/pqi/p3netmgr.cc +++ b/libretroshare/src/pqi/p3netmgr.cc @@ -712,8 +712,10 @@ void p3NetMgrIMPL::netExtCheck() } #ifdef ALLOW_DHT_STUNNER - // (cyril) I disabled this because it's pretty dangerous. The DHT can report a wrong address quite easily - // if the other DHT peers are not collaborating. + // (cyril) I disabled this because it's pretty dangerous. The DHT can report a wrong address quite easily + // if the other DHT peers are not collaborating. + // (sehraf) For the record: The udp stunner uses multiple (as for now: two) peers to ensure that the IP recieved is the correct one, see UdpStunner::locked_checkExternalAddress() + // Nevertheless this stays a more risky method to determine the external ip address. /* Next ask the DhtStunner */ { diff --git a/retroshare.pri b/retroshare.pri index fedd39e6a..565324259 100644 --- a/retroshare.pri +++ b/retroshare.pri @@ -113,9 +113,16 @@ no_bitdht:CONFIG -= bitdht # The DHT stunner is used to determine the NAT type using other RS DHT peers and the STUN (Session Traversal Utilities for NAT) protocol. # To disable DHT stunner append the following assignation to qmake command line -# "CONFIG+=no_useDhtStunner" -CONFIG *= useDhtStunner -no_useDhtStunner:CONFIG -= useDhtStunner +# "CONFIG+=no_use_dht_stunner" +CONFIG *= use_dht_stunner +no_use_dht_stunner:CONFIG -= use_dht_stunner + +# The DHT stunner can be used to figure out our external IP. As this purely relying on random DHT peers that answer our request, it can easily be abused +# Therefore, it is turned off by default. +# To enable external ip determination (additionally) based on the dht stunner append the following assignation to qmake +# command line "CONFIG+=rs_async_chat" +CONFIG *= no_use_dht_stunner_ext_ip +use_dht_stunner_ext_ip:CONFIG -= no_use_dht_stunner_ext_ip # To select your MacOsX version append the following assignation to qmake # command line "CONFIG+=rs_macos10.11" where 10.11 depends your version @@ -498,6 +505,14 @@ rs_gxs_trans { bitdht { DEFINES *= RS_USE_BITDHT + + use_dht_stunner { + CONFIG *= useDhtStunner + + use_dht_stunner_ext_ip { + DEFINES *= ALLOW_DHT_STUNNER + } + } } direct_chat { From 6e3740f3b8fa1de412ed493968a401cbb1945691 Mon Sep 17 00:00:00 2001 From: sehraf Date: Sun, 9 Feb 2020 11:18:16 +0100 Subject: [PATCH 6/8] add more documentation to updstunner.h --- libretroshare/src/tcponudp/udpstunner.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libretroshare/src/tcponudp/udpstunner.h b/libretroshare/src/tcponudp/udpstunner.h index eb05c2018..9e1447bcf 100644 --- a/libretroshare/src/tcponudp/udpstunner.h +++ b/libretroshare/src/tcponudp/udpstunner.h @@ -155,13 +155,19 @@ bool locked_checkExternalAddress(); #endif + /// The UDP stunner will only (actively) contact it's peers when mPassiveStunMode is false. (has priority over mForceRestun bool mPassiveStunMode; + /// Time between STUNs uint32_t mTargetStunPeriod; + /// Rate that determines how often STUN attempts are successfull double mSuccessRate; + /// Some variables used for tracking who and when exclusive mode is enabled bool mExclusiveMode; /* when this is switched on, the stunner stays silent (and extAddr is maintained) */ rstime_t mExclusiveModeTS; std::string mExclusiveHolder; + + /// force a STUN immediately bool mForceRestun; }; From f27022fe7ba49e9509d11a8abb3597c3b8baad53 Mon Sep 17 00:00:00 2001 From: sehraf Date: Sun, 9 Feb 2020 12:04:13 +0100 Subject: [PATCH 7/8] review fixup --- libretroshare/src/tcponudp/udpstunner.cc | 31 +++++++++--------------- libretroshare/src/tcponudp/udpstunner.h | 21 +++++++++++++--- retroshare.pri | 4 +-- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/libretroshare/src/tcponudp/udpstunner.cc b/libretroshare/src/tcponudp/udpstunner.cc index 1f79d00d8..4409f256f 100644 --- a/libretroshare/src/tcponudp/udpstunner.cc +++ b/libretroshare/src/tcponudp/udpstunner.cc @@ -47,12 +47,6 @@ const uint32_t TOU_STUN_MAX_RECV_RATE = 25; /* every 25 seconds */ const int32_t TOU_STUN_DEFAULT_TARGET_RATE = 15; /* 20 secs is minimum to keep a NAT UDP port open */ const double TOU_SUCCESS_LPF_FACTOR = 0.90; -/* - * based on RFC 3489 - */ -const uint16_t STUN_BINDING_REQUEST = 0x0001; -const uint16_t STUN_BINDING_RESPONSE = 0x0101; - #define EXCLUSIVE_MODE_TIMEOUT 300 UdpStunner::UdpStunner(UdpPublisher *pub) @@ -222,7 +216,7 @@ int UdpStunner::releaseExclusiveMode(std::string holder, bool forceStun) } #ifdef DEBUG_UDP_STUNNER_FILTER - rstime_t now = time(NULL); + rstime_t now = time(nullptr); std::cerr << "UdpStunner::cancelExclusiveMode() Canceled. Was in ExclusiveMode for: " << now - mExclusiveModeTS; std::cerr << " secs"; std::cerr << std::endl; @@ -491,7 +485,7 @@ bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr) return false; } - if (htons(((uint16_t *) stun_pkt)[0]) != STUN_BINDING_RESPONSE) + if (htons(((uint16_t *) stun_pkt)[0]) != UdpStunner::STUN_BINDING_RESPONSE) { /* not a response */ return false; @@ -523,40 +517,37 @@ bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len) } /* just the header */ - ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(STUN_BINDING_REQUEST); + ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(UdpStunner::STUN_BINDING_REQUEST); ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(20); /* only header */ /* RFC 3489 * The transaction ID is used to correlate requests and responses. * * RFC 5389 introduces a mmgic cokie at the location where preciously the transaction ID was located: - * In RFC 3489 [RFC3489], this field was part of + * In RFC 3489, this field was part of * the transaction ID; placing the magic cookie in this location allows * a server to detect if the client will understand certain attributes * that were added in this revised specification. */ - ((uint32_t *) stun_pkt)[1] = htonl(RsRandom::random_u32()); - ((uint32_t *) stun_pkt)[2] = htonl(RsRandom::random_u32()); - ((uint32_t *) stun_pkt)[3] = htonl(RsRandom::random_u32()); - ((uint32_t *) stun_pkt)[4] = htonl(RsRandom::random_u32()); + RsRandom::random_bytes(&((uint8_t *) stun_pkt)[4], 4 * sizeof (uint32_t)); *len = 20; return true; } -void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void *data) +void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void *transId) { /* just the header */ void *stun_pkt = rs_malloc(28); if(!stun_pkt) - return NULL ; + return nullptr ; - ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(STUN_BINDING_RESPONSE); + ((uint16_t *) stun_pkt)[0] = (uint16_t) htons(UdpStunner::STUN_BINDING_RESPONSE); ((uint16_t *) stun_pkt)[1] = (uint16_t) htons(28); /* only header + 8 byte addr */ /* RFC 3489 * The Binding Response MUST contain the same transaction ID contained in the Binding Request. */ - memcpy(&((uint32_t *) stun_pkt)[1], &((uint32_t *) data)[1], 4 * sizeof (uint32_t)); + memcpy(&((uint32_t *) stun_pkt)[1], &((uint32_t *) transId)[1], 4 * sizeof (uint32_t)); /* now add address * 0 1 2 3 @@ -600,7 +591,7 @@ bool UdpStun_isStunPacket(void *data, int size) return false; } - if ((size == 20) && (STUN_BINDING_REQUEST == ntohs(((uint16_t *) data)[0]))) + if ((size == 20) && (UdpStunner::STUN_BINDING_REQUEST == ntohs(((uint16_t *) data)[0]))) { #ifdef DEBUG_UDP_STUNNER_FILTER std::cerr << "UdpStunner::isStunPacket() (size=20 & data[0]=STUN_BINDING_REQUEST) -> true"; @@ -610,7 +601,7 @@ bool UdpStun_isStunPacket(void *data, int size) return true; } - if ((size == 28) && (STUN_BINDING_RESPONSE == ntohs(((uint16_t *) data)[0]))) + if ((size == 28) && (UdpStunner::STUN_BINDING_RESPONSE == ntohs(((uint16_t *) data)[0]))) { #ifdef DEBUG_UDP_STUNNER_FILTER std::cerr << "UdpStunner::isStunPacket() (size=28 & data[0]=STUN_BINDING_RESPONSE) -> true"; diff --git a/libretroshare/src/tcponudp/udpstunner.h b/libretroshare/src/tcponudp/udpstunner.h index 9e1447bcf..00accaa45 100644 --- a/libretroshare/src/tcponudp/udpstunner.h +++ b/libretroshare/src/tcponudp/udpstunner.h @@ -55,8 +55,10 @@ class TouStunPeer /// id for identification std::string id; - /// remote address - struct sockaddr_in remote, eaddr; + /// Remote address of the peer. + struct sockaddr_in remote; + /// Our external IP address as reported by the peer. + struct sockaddr_in eaddr; /// true when a response was received in the past bool response; /// used to rate limit STUN requests @@ -114,6 +116,12 @@ virtual int status(std::ostream &out); /* monitoring / updates */ int tick(); + /* + * based on RFC 3489 + */ + static constexpr uint16_t STUN_BINDING_REQUEST = 0x0001; + static constexpr uint16_t STUN_BINDING_RESPONSE = 0x0101; + private: bool checkStunDesired(); @@ -176,7 +184,14 @@ bool locked_checkExternalAddress(); bool UdpStun_isStunPacket(void *data, int size); bool UdpStun_response(void *stun_pkt, int size, struct sockaddr_in &addr); -void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void* data); +/** + * @brief UdpStun_generate_stun_reply Generates a STUN reply package. + * @param stun_addr The address to set in the response field. + * @param len Lenght of the generated package (always 28). + * @param transId The transaction ID of the request package. + * @return Pointer to the generated reply package. + */ +void *UdpStun_generate_stun_reply(struct sockaddr_in *stun_addr, int *len, const void* transId); bool UdpStun_generate_stun_pkt(void *stun_pkt, int *len); #endif diff --git a/retroshare.pri b/retroshare.pri index 565324259..977bb84f7 100644 --- a/retroshare.pri +++ b/retroshare.pri @@ -117,10 +117,10 @@ no_bitdht:CONFIG -= bitdht CONFIG *= use_dht_stunner no_use_dht_stunner:CONFIG -= use_dht_stunner -# The DHT stunner can be used to figure out our external IP. As this purely relying on random DHT peers that answer our request, it can easily be abused +# The DHT stunner can be used to figure out our external IP. As this purely relying on random DHT peers that answer our request, it can easily be abused. # Therefore, it is turned off by default. # To enable external ip determination (additionally) based on the dht stunner append the following assignation to qmake -# command line "CONFIG+=rs_async_chat" +# command line "CONFIG+=use_dht_stunner_ext_ip" CONFIG *= no_use_dht_stunner_ext_ip use_dht_stunner_ext_ip:CONFIG -= no_use_dht_stunner_ext_ip From f019a71472fbc093931a067c5d73a8f69f39527f Mon Sep 17 00:00:00 2001 From: sehraf Date: Sat, 15 Feb 2020 17:51:22 +0100 Subject: [PATCH 8/8] only use external up from DHT stunner as fallback when no other source provides a valid IP --- libretroshare/src/pqi/p3netmgr.cc | 86 +++++++++++++++---------------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/libretroshare/src/pqi/p3netmgr.cc b/libretroshare/src/pqi/p3netmgr.cc index 89ff6f0cd..38007c309 100644 --- a/libretroshare/src/pqi/p3netmgr.cc +++ b/libretroshare/src/pqi/p3netmgr.cc @@ -711,49 +711,6 @@ void p3NetMgrIMPL::netExtCheck() } } -#ifdef ALLOW_DHT_STUNNER - // (cyril) I disabled this because it's pretty dangerous. The DHT can report a wrong address quite easily - // if the other DHT peers are not collaborating. - // (sehraf) For the record: The udp stunner uses multiple (as for now: two) peers to ensure that the IP recieved is the correct one, see UdpStunner::locked_checkExternalAddress() - // Nevertheless this stays a more risky method to determine the external ip address. - - /* Next ask the DhtStunner */ - { -#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) - std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok, Checking DhtStunner" << std::endl; -#endif - uint8_t isstable = 0; - struct sockaddr_storage tmpaddr; - sockaddr_storage_clear(tmpaddr); - - if (mDhtStunner) - { - /* input network bits */ - if (mDhtStunner->getExternalAddr(tmpaddr, isstable)) - { - if((rsBanList == NULL) || rsBanList->isAddressAccepted(tmpaddr,RSBANLIST_CHECKING_FLAGS_BLACKLIST)) - { - // must be stable??? - isStable = (isstable == 1); - //mNetFlags.mExtAddr = tmpaddr; - mNetFlags.mExtAddrOk = true; - mNetFlags.mExtAddrStableOk = isStable; - - address_votes[tmpaddr].n++ ; -#ifdef NETMGR_DEBUG_STATEBOX - std::cerr << "p3NetMgrIMPL::netExtCheck() From DhtStunner: "; - std::cerr << sockaddr_storage_tostring(tmpaddr); - std::cerr << " Stable: " << (uint32_t) isstable; - std::cerr << std::endl; -#endif - } - else - std::cerr << "(SS) DHTStunner returned wrong own IP " << sockaddr_storage_iptostring(tmpaddr) << " (banned). Rejecting." << std::endl; - } - } - } -#endif - /* ask ExtAddrFinder */ { /* ExtAddrFinder */ @@ -831,6 +788,49 @@ void p3NetMgrIMPL::netExtCheck() #endif } +#ifdef ALLOW_DHT_STUNNER + // (cyril) I disabled this because it's pretty dangerous. The DHT can report a wrong address quite easily + // if the other DHT peers are not collaborating. + // (sehraf) For the record: The udp stunner uses multiple (as for now: two) peers to ensure that the IP recieved is the correct one, see UdpStunner::locked_checkExternalAddress() + // Nevertheless this stays a more risky method to determine the external ip address. + + /* lastly ask the DhtStunner as fallback */ + if (address_votes.empty()) { +#if defined(NETMGR_DEBUG_TICK) || defined(NETMGR_DEBUG_RESET) + std::cerr << "p3NetMgrIMPL::netExtCheck() Ext Not Ok, Checking DhtStunner" << std::endl; +#endif + uint8_t isstable = 0; + struct sockaddr_storage tmpaddr; + sockaddr_storage_clear(tmpaddr); + + if (mDhtStunner) + { + /* input network bits */ + if (mDhtStunner->getExternalAddr(tmpaddr, isstable)) + { + if((rsBanList == NULL) || rsBanList->isAddressAccepted(tmpaddr,RSBANLIST_CHECKING_FLAGS_BLACKLIST)) + { + // must be stable??? + isStable = (isstable == 1); + //mNetFlags.mExtAddr = tmpaddr; + mNetFlags.mExtAddrOk = true; + mNetFlags.mExtAddrStableOk = isStable; + + address_votes[tmpaddr].n++ ; +#ifdef NETMGR_DEBUG_STATEBOX + std::cerr << "p3NetMgrIMPL::netExtCheck() From DhtStunner: "; + std::cerr << sockaddr_storage_tostring(tmpaddr); + std::cerr << " Stable: " << (uint32_t) isstable; + std::cerr << std::endl; +#endif + } + else + std::cerr << "(SS) DHTStunner returned wrong own IP " << sockaddr_storage_iptostring(tmpaddr) << " (banned). Rejecting." << std::endl; + } + } + } +#endif + /* any other sources ??? */ /* finalise address */