Added Code to detect Symmetric NAT (BAD!) Firewalls.

git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@361 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
drbob 2008-02-28 15:58:54 +00:00
parent 6dd3d30d8e
commit 2dc2954f40
14 changed files with 257 additions and 43 deletions

View file

@ -107,12 +107,12 @@ int tou_tick_stunkeepalive()
return 1;
}
int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen)
int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen, uint8_t *stable)
{
if (!tou_inited)
return -1;
if (udps->externalAddr(*(struct sockaddr_in *) ext_addr))
if (udps->externalAddr(*(struct sockaddr_in *) ext_addr, *stable))
{
return 1;
}

View file

@ -72,7 +72,7 @@ extern "C" {
*/
int tou_init(const struct sockaddr *my_addr, socklen_t addrlen);
int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen);
int tou_extaddr(struct sockaddr *ext_addr, socklen_t *addrlen, uint8_t *stable);
int tou_stunpeer(const struct sockaddr *ext_addr, socklen_t addrlen, const char *id);
int tou_stunkeepalive(int required);
int tou_tick_stunkeepalive();

View file

@ -39,7 +39,7 @@ static const int STUN_TTL = 64;
#define DEBUG_UDP_SORTER 1
UdpSorter::UdpSorter(struct sockaddr_in &local)
:udpLayer(NULL), laddr(local), eaddrKnown(false),
:udpLayer(NULL), laddr(local), eaddrKnown(false), eaddrStable(false),
mStunKeepAlive(false), mStunLastRecv(0), mStunLastSend(0)
@ -234,10 +234,7 @@ bool UdpSorter::locked_handleStunPkt(void *data, int size, struct sockaddr_in &f
std::cerr << inet_ntoa(eAddr.sin_addr) << ":" << ntohs(eAddr.sin_port);
std::cerr << std::endl;
#endif
eaddrKnown = true;
eaddr = eAddr;
locked_recvdStun(from);
locked_recvdStun(from, eAddr);
return true;
}
@ -251,11 +248,17 @@ bool UdpSorter::locked_handleStunPkt(void *data, int size, struct sockaddr_in &f
}
bool UdpSorter::externalAddr(struct sockaddr_in &external)
bool UdpSorter::externalAddr(struct sockaddr_in &external, uint8_t &stable)
{
if (eaddrKnown)
{
external = eaddr;
if (eaddrStable)
stable = 1;
else
stable = 0;
return true;
}
return false;
@ -612,15 +615,21 @@ bool UdpSorter::checkStunKeepAlive()
}
bool UdpSorter::locked_recvdStun(const struct sockaddr_in &remote)
bool UdpSorter::locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr)
{
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::recvdStun()";
std::cerr << std::endl;
std::ostringstream out;
out << "UdpSorter::locked_recvdStun() from:";
out << inet_ntoa(remote.sin_addr) << ":" << ntohs(remote.sin_port);
out << " claiming ExtAddr is:";
out << inet_ntoa(extaddr.sin_addr) << ":" << ntohs(extaddr.sin_port);
std::cerr << out.str() << std::endl;
#endif
locked_printStunList();
bool found = true;
std::list<TouStunPeer>::iterator it;
for(it = mStunList.begin(); it != mStunList.end(); it++)
{
@ -628,13 +637,85 @@ bool UdpSorter::locked_recvdStun(const struct sockaddr_in &remote)
(remote.sin_port == it->remote.sin_port))
{
it->failCount = 0;
return true;
it->eaddr = extaddr;
it->response = true;
found = true;
break;
}
}
if (!eaddrKnown)
{
locked_checkExternalAddress();
}
return found;
}
bool UdpSorter::locked_checkExternalAddress()
{
#ifdef DEBUG_UDP_SORTER
std::ostringstream out;
out << "UdpSorter::locked_checkExternalAddress()";
std::cerr << out.str() << std::endl;
#endif
bool found1 = false;
bool found2 = false;
std::list<TouStunPeer>::iterator it;
std::list<TouStunPeer>::iterator p1;
std::list<TouStunPeer>::iterator p2;
for(it = mStunList.begin(); it != mStunList.end(); it++)
{
if (it->response)
{
if (!found1)
{
p1 = it;
found1 = true;
}
else
{
p2 = it;
found2 = true;
break;
}
}
}
if (found1 && found2)
{
if ((p1->eaddr.sin_addr.s_addr == p2->eaddr.sin_addr.s_addr) &&
(p1->eaddr.sin_port == p2->eaddr.sin_port))
{
eaddrStable = true;
}
else
{
eaddrStable = false;
}
eaddrKnown = true;
eaddr = p1->eaddr;
#ifdef DEBUG_UDP_SORTER
std::cerr << "UdpSorter::locked_checkExternalAddress() Found State:";
if (eaddrStable)
std::cerr << " Stable NAT translation (GOOD!) ";
else
std::cerr << " unStable (symmetric NAT translation (BAD!) ";
std::cerr << std::endl;
#endif
return true;
}
return false;
}
bool UdpSorter::locked_printStunList()
{
std::ostringstream out;

View file

@ -49,13 +49,14 @@ class TouStunPeer
{
public:
TouStunPeer()
:lastsend(0), failCount(0) { return; }
:response(false), lastsend(0), failCount(0) { return; }
TouStunPeer(std::string id_in, const struct sockaddr_in &addr)
:id(id_in), remote(addr), lastsend(0), failCount(0) { return; }
:id(id_in), remote(addr), response(false), lastsend(0), failCount(0) { return; }
std::string id;
struct sockaddr_in remote;
struct sockaddr_in remote, eaddr;
bool response;
time_t lastsend;
uint32_t failCount;
};
@ -75,7 +76,7 @@ bool setStunKeepAlive(uint32_t required);
bool addStunPeer(const struct sockaddr_in &remote, const char *peerid);
bool checkStunKeepAlive();
bool externalAddr(struct sockaddr_in &remote);
bool externalAddr(struct sockaddr_in &remote, uint8_t &stable);
/* Packet IO */
/* pass-through send packets */
@ -108,7 +109,9 @@ bool generate_stun_pkt(void *stun_pkt, int *len);
/* stun keepAlive */
bool locked_printStunList();
bool locked_recvdStun(const struct sockaddr_in &remote);
bool locked_recvdStun(const struct sockaddr_in &remote, const struct sockaddr_in &extaddr);
bool locked_checkExternalAddress();
bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid);
UdpLayer *udpLayer;
@ -116,8 +119,10 @@ bool storeStunPeer(const struct sockaddr_in &remote, const char *peerid);
RsMutex sortMtx; /* for all class data (below) */
struct sockaddr_in laddr; /* local addr */
struct sockaddr_in eaddr; /* external addr */
bool eaddrKnown;
bool eaddrStable; /* if true then usable. if false -> Symmettric NAT */
bool mStunKeepAlive;
time_t mStunLastRecv;