mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-04-24 01:46:36 +02:00
handle ipv6 adrresses
This commit is contained in:
parent
d84a7ebc7e
commit
d513f20225
2 changed files with 97 additions and 32 deletions
127
SSU.cpp
127
SSU.cpp
|
@ -237,7 +237,7 @@ namespace transport
|
||||||
if (!s.Verify (m_RemoteIdentity, payload))
|
if (!s.Verify (m_RemoteIdentity, payload))
|
||||||
LogPrint (eLogError, "SSU signature verification failed");
|
LogPrint (eLogError, "SSU signature verification failed");
|
||||||
|
|
||||||
SendSessionConfirmed (y, ourAddress);
|
SendSessionConfirmed (y, ourAddress, addressSize + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::ProcessSessionConfirmed (uint8_t * buf, size_t len)
|
void SSUSession::ProcessSessionConfirmed (uint8_t * buf, size_t len)
|
||||||
|
@ -269,17 +269,26 @@ namespace transport
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t buf[304 + 18]; // 304 bytes for ipv4 (320 for ipv6)
|
uint8_t buf[320 + 18]; // 304 bytes for ipv4, 320 for ipv6
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
memcpy (payload, m_DHKeysPair->publicKey, 256); // x
|
memcpy (payload, m_DHKeysPair->publicKey, 256); // x
|
||||||
payload[256] = 4; // we assume ipv4
|
bool isV4 = m_RemoteEndpoint.address ().is_v4 ();
|
||||||
*(uint32_t *)(payload + 257) = htobe32 (m_RemoteEndpoint.address ().to_v4 ().to_ulong ());
|
if (isV4)
|
||||||
|
{
|
||||||
|
payload[256] = 4;
|
||||||
|
memcpy (payload + 257, m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data(), 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
payload[256] = 16;
|
||||||
|
memcpy (payload + 257, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t iv[16];
|
uint8_t iv[16];
|
||||||
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
|
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
|
||||||
rnd.GenerateBlock (iv, 16); // random iv
|
rnd.GenerateBlock (iv, 16); // random iv
|
||||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_REQUEST, buf, 304, introKey, iv, introKey);
|
FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_REQUEST, buf, isV4 ? 304 : 320, introKey, iv, introKey);
|
||||||
m_Server.Send (buf, 304, m_RemoteEndpoint);
|
m_Server.Send (buf, isV4 ? 304 : 320, m_RemoteEndpoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::SendRelayRequest (uint32_t iTag, const uint8_t * iKey)
|
void SSUSession::SendRelayRequest (uint32_t iTag, const uint8_t * iKey)
|
||||||
|
@ -333,14 +342,31 @@ namespace transport
|
||||||
memcpy (payload, m_DHKeysPair->publicKey, 256);
|
memcpy (payload, m_DHKeysPair->publicKey, 256);
|
||||||
s.Insert (payload, 256); // y
|
s.Insert (payload, 256); // y
|
||||||
payload += 256;
|
payload += 256;
|
||||||
*payload = 4; // we assume ipv4
|
if (m_RemoteEndpoint.address ().is_v4 ())
|
||||||
payload++;
|
{
|
||||||
*(uint32_t *)(payload) = htobe32 (m_RemoteEndpoint.address ().to_v4 ().to_ulong ());
|
// ipv4
|
||||||
payload += 4;
|
*payload = 4;
|
||||||
|
payload++;
|
||||||
|
memcpy (payload, m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data(), 4);
|
||||||
|
s.Insert (payload, 4); // remote endpoint IP V4
|
||||||
|
payload += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// ipv6
|
||||||
|
*payload = 16;
|
||||||
|
payload++;
|
||||||
|
memcpy (payload, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16);
|
||||||
|
s.Insert (payload, 16); // remote endpoint IP V6
|
||||||
|
payload += 16;
|
||||||
|
}
|
||||||
*(uint16_t *)(payload) = htobe16 (m_RemoteEndpoint.port ());
|
*(uint16_t *)(payload) = htobe16 (m_RemoteEndpoint.port ());
|
||||||
|
s.Insert (payload, 2); // remote port
|
||||||
payload += 2;
|
payload += 2;
|
||||||
s.Insert (payload - 6, 6); // remote endpoint IP and port
|
if (address->host.is_v4 ())
|
||||||
s.Insert (htobe32 (address->host.to_v4 ().to_ulong ())); // our IP
|
s.Insert (address->host.to_v4 ().to_bytes ().data (), 4); // our IP V4
|
||||||
|
else
|
||||||
|
s.Insert (address->host.to_v6 ().to_bytes ().data (), 16); // our IP V6
|
||||||
s.Insert (htobe16 (address->port)); // our port
|
s.Insert (htobe16 (address->port)); // our port
|
||||||
uint32_t relayTag = 0;
|
uint32_t relayTag = 0;
|
||||||
if (i2p::context.GetRouterInfo ().IsIntroducer ())
|
if (i2p::context.GetRouterInfo ().IsIntroducer ())
|
||||||
|
@ -373,7 +399,7 @@ namespace transport
|
||||||
Send (buf, msgLen);
|
Send (buf, msgLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUSession::SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress)
|
void SSUSession::SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress, size_t ourAddressLen)
|
||||||
{
|
{
|
||||||
uint8_t buf[512 + 18];
|
uint8_t buf[512 + 18];
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
|
@ -397,8 +423,11 @@ namespace transport
|
||||||
SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, our signed on time
|
SignedData s; // x,y, our IP, our port, remote IP, remote port, relayTag, our signed on time
|
||||||
s.Insert (m_DHKeysPair->publicKey, 256); // x
|
s.Insert (m_DHKeysPair->publicKey, 256); // x
|
||||||
s.Insert (y, 256); // y
|
s.Insert (y, 256); // y
|
||||||
s.Insert (ourAddress, 6); // our address/port as seem by party
|
s.Insert (ourAddress, ourAddressLen); // our address/port as seem by party
|
||||||
s.Insert (htobe32 (m_RemoteEndpoint.address ().to_v4 ().to_ulong ())); // remote IP
|
if (m_RemoteEndpoint.address ().is_v4 ())
|
||||||
|
s.Insert (m_RemoteEndpoint.address ().to_v4 ().to_bytes ().data (), 4); // remote IP V4
|
||||||
|
else
|
||||||
|
s.Insert (m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data (), 16); // remote IP V6
|
||||||
s.Insert (htobe16 (m_RemoteEndpoint.port ())); // remote port
|
s.Insert (htobe16 (m_RemoteEndpoint.port ())); // remote port
|
||||||
s.Insert (htobe32 (m_RelayTag)); // relay tag
|
s.Insert (htobe32 (m_RelayTag)); // relay tag
|
||||||
s.Insert (htobe32 (signedOnTime)); // signed on time
|
s.Insert (htobe32 (signedOnTime)); // signed on time
|
||||||
|
@ -439,9 +468,14 @@ namespace transport
|
||||||
void SSUSession::SendRelayResponse (uint32_t nonce, const boost::asio::ip::udp::endpoint& from,
|
void SSUSession::SendRelayResponse (uint32_t nonce, const boost::asio::ip::udp::endpoint& from,
|
||||||
const uint8_t * introKey, const boost::asio::ip::udp::endpoint& to)
|
const uint8_t * introKey, const boost::asio::ip::udp::endpoint& to)
|
||||||
{
|
{
|
||||||
uint8_t buf[64 + 18];
|
uint8_t buf[80 + 18]; // 64 Alice's ipv4 and 80 Alice's ipv6
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
// Charlie
|
// Charlie's address always v4
|
||||||
|
if (!to.address ().is_v4 ())
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Charlie's IP must be v4");
|
||||||
|
return;
|
||||||
|
}
|
||||||
*payload = 4;
|
*payload = 4;
|
||||||
payload++; // size
|
payload++; // size
|
||||||
*(uint32_t *)payload = htobe32 (to.address ().to_v4 ().to_ulong ()); // Charlie's IP
|
*(uint32_t *)payload = htobe32 (to.address ().to_v4 ().to_ulong ()); // Charlie's IP
|
||||||
|
@ -449,10 +483,21 @@ namespace transport
|
||||||
*(uint16_t *)payload = htobe16 (to.port ()); // Charlie's port
|
*(uint16_t *)payload = htobe16 (to.port ()); // Charlie's port
|
||||||
payload += 2; // port
|
payload += 2; // port
|
||||||
// Alice
|
// Alice
|
||||||
*payload = 4;
|
bool isV4 = from.address ().is_v4 (); // Alice's
|
||||||
payload++; // size
|
if (isV4)
|
||||||
*(uint32_t *)payload = htobe32 (from.address ().to_v4 ().to_ulong ()); // Alice's IP
|
{
|
||||||
payload += 4; // address
|
*payload = 4;
|
||||||
|
payload++; // size
|
||||||
|
memcpy (payload, from.address ().to_v4 ().to_bytes ().data (), 4); // Alice's IP V4
|
||||||
|
payload += 4; // address
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*payload = 16;
|
||||||
|
payload++; // size
|
||||||
|
memcpy (payload, from.address ().to_v6 ().to_bytes ().data (), 16); // Alice's IP V6
|
||||||
|
payload += 16; // address
|
||||||
|
}
|
||||||
*(uint16_t *)payload = htobe16 (from.port ()); // Alice's port
|
*(uint16_t *)payload = htobe16 (from.port ()); // Alice's port
|
||||||
payload += 2; // port
|
payload += 2; // port
|
||||||
*(uint32_t *)payload = htobe32 (nonce);
|
*(uint32_t *)payload = htobe32 (nonce);
|
||||||
|
@ -460,8 +505,8 @@ namespace transport
|
||||||
if (m_State == eSessionStateEstablished)
|
if (m_State == eSessionStateEstablished)
|
||||||
{
|
{
|
||||||
// encrypt with session key
|
// encrypt with session key
|
||||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_RESPONSE, buf, 64);
|
FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_RESPONSE, buf, isV4 ? 64 : 80);
|
||||||
Send (buf, 64);
|
Send (buf, isV4 ? 64 : 80);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -469,8 +514,8 @@ namespace transport
|
||||||
uint8_t iv[16];
|
uint8_t iv[16];
|
||||||
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
|
CryptoPP::RandomNumberGenerator& rnd = i2p::context.GetRandomNumberGenerator ();
|
||||||
rnd.GenerateBlock (iv, 16); // random iv
|
rnd.GenerateBlock (iv, 16); // random iv
|
||||||
FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_RESPONSE, buf, 64, introKey, iv, introKey);
|
FillHeaderAndEncrypt (PAYLOAD_TYPE_RELAY_RESPONSE, buf, isV4 ? 64 : 80, introKey, iv, introKey);
|
||||||
m_Server.Send (buf, 64, from);
|
m_Server.Send (buf, isV4 ? 64 : 80, from);
|
||||||
}
|
}
|
||||||
LogPrint (eLogDebug, "SSU relay response sent");
|
LogPrint (eLogDebug, "SSU relay response sent");
|
||||||
}
|
}
|
||||||
|
@ -478,6 +523,12 @@ namespace transport
|
||||||
void SSUSession::SendRelayIntro (SSUSession * session, const boost::asio::ip::udp::endpoint& from)
|
void SSUSession::SendRelayIntro (SSUSession * session, const boost::asio::ip::udp::endpoint& from)
|
||||||
{
|
{
|
||||||
if (!session) return;
|
if (!session) return;
|
||||||
|
// Alice's address always v4
|
||||||
|
if (!from.address ().is_v4 ())
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Alice's IP must be v4");
|
||||||
|
return;
|
||||||
|
}
|
||||||
uint8_t buf[48 + 18];
|
uint8_t buf[48 + 18];
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
*payload = 4;
|
*payload = 4;
|
||||||
|
@ -499,14 +550,28 @@ namespace transport
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Relay response received");
|
LogPrint (eLogDebug, "Relay response received");
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
|
uint8_t remoteSize = *payload;
|
||||||
payload++; // remote size
|
payload++; // remote size
|
||||||
//boost::asio::ip::address_v4 remoteIP (be32toh (*(uint32_t* )(payload)));
|
//boost::asio::ip::address_v4 remoteIP (be32toh (*(uint32_t* )(payload)));
|
||||||
payload += 4; // remote address
|
payload += remoteSize; // remote address
|
||||||
//uint16_t remotePort = be16toh (*(uint16_t *)(payload));
|
//uint16_t remotePort = be16toh (*(uint16_t *)(payload));
|
||||||
payload += 2; // remote port
|
payload += 2; // remote port
|
||||||
|
uint8_t ourSize = *payload;
|
||||||
payload++; // our size
|
payload++; // our size
|
||||||
boost::asio::ip::address_v4 ourIP (be32toh (*(uint32_t* )(payload)));
|
boost::asio::ip::address ourIP;
|
||||||
payload += 4; // our address
|
if (ourSize == 4)
|
||||||
|
{
|
||||||
|
boost::asio::ip::address_v4::bytes_type bytes;
|
||||||
|
memcpy (bytes.data (), payload, 4);
|
||||||
|
ourIP = boost::asio::ip::address_v4 (bytes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boost::asio::ip::address_v6::bytes_type bytes;
|
||||||
|
memcpy (bytes.data (), payload, 16);
|
||||||
|
ourIP = boost::asio::ip::address_v6 (bytes);
|
||||||
|
}
|
||||||
|
payload += ourSize; // our address
|
||||||
uint16_t ourPort = be16toh (*(uint16_t *)(payload));
|
uint16_t ourPort = be16toh (*(uint16_t *)(payload));
|
||||||
payload += 2; // our port
|
payload += 2; // our port
|
||||||
LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort);
|
LogPrint ("Our external address is ", ourIP.to_string (), ":", ourPort);
|
||||||
|
@ -924,9 +989,9 @@ namespace transport
|
||||||
|
|
||||||
void SSUSession::Send (uint8_t type, const uint8_t * payload, size_t len)
|
void SSUSession::Send (uint8_t type, const uint8_t * payload, size_t len)
|
||||||
{
|
{
|
||||||
uint8_t buf[SSU_MTU + 18];
|
uint8_t buf[SSU_MTU_V4 + 18];
|
||||||
size_t msgSize = len + sizeof (SSUHeader);
|
size_t msgSize = len + sizeof (SSUHeader);
|
||||||
if (msgSize > SSU_MTU)
|
if (msgSize > SSU_MTU_V4)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "SSU payload size ", msgSize, " exceeds MTU");
|
LogPrint (eLogWarning, "SSU payload size ", msgSize, " exceeds MTU");
|
||||||
return;
|
return;
|
||||||
|
@ -1016,7 +1081,7 @@ namespace transport
|
||||||
|
|
||||||
void SSUServer::Receive ()
|
void SSUServer::Receive ()
|
||||||
{
|
{
|
||||||
m_Socket.async_receive_from (boost::asio::buffer (m_ReceiveBuffer, SSU_MTU), m_SenderEndpoint,
|
m_Socket.async_receive_from (boost::asio::buffer (m_ReceiveBuffer, SSU_MTU_V4), m_SenderEndpoint,
|
||||||
boost::bind (&SSUServer::HandleReceivedFrom, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
boost::bind (&SSUServer::HandleReceivedFrom, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
SSU.h
2
SSU.h
|
@ -96,7 +96,7 @@ namespace transport
|
||||||
void ProcessSessionCreated (uint8_t * buf, size_t len);
|
void ProcessSessionCreated (uint8_t * buf, size_t len);
|
||||||
void SendSessionCreated (const uint8_t * x);
|
void SendSessionCreated (const uint8_t * x);
|
||||||
void ProcessSessionConfirmed (uint8_t * buf, size_t len);
|
void ProcessSessionConfirmed (uint8_t * buf, size_t len);
|
||||||
void SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress);
|
void SendSessionConfirmed (const uint8_t * y, const uint8_t * ourAddress, size_t ourAddressLen);
|
||||||
void ProcessRelayRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& from);
|
void ProcessRelayRequest (uint8_t * buf, size_t len, const boost::asio::ip::udp::endpoint& from);
|
||||||
void SendRelayResponse (uint32_t nonce, const boost::asio::ip::udp::endpoint& from,
|
void SendRelayResponse (uint32_t nonce, const boost::asio::ip::udp::endpoint& from,
|
||||||
const uint8_t * introKey, const boost::asio::ip::udp::endpoint& to);
|
const uint8_t * introKey, const boost::asio::ip::udp::endpoint& to);
|
||||||
|
|
Loading…
Add table
Reference in a new issue