diff --git a/ClientContext.cpp b/ClientContext.cpp index 9f5756e6..19d841d3 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -311,7 +311,8 @@ namespace client std::string keys = section.second.get (I2P_SERVER_TUNNEL_KEYS); // optional params int inPort = section.second.get (I2P_SERVER_TUNNEL_INPORT, 0); - std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, ""); + std::string accessList = section.second.get (I2P_SERVER_TUNNEL_ACCESS_LIST, ""); + std::string hostOverride = section.second.get (I2P_SERVER_TUNNEL_HOST_OVERRIDE, ""); i2p::data::SigningKeyType sigType = section.second.get (I2P_SERVER_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256); // I2CP std::map options; @@ -324,7 +325,7 @@ namespace client if (!localDestination) localDestination = CreateNewLocalDestination (k, true, &options); I2PServerTunnel * serverTunnel = (type == I2P_TUNNELS_SECTION_TYPE_HTTP) ? - new I2PServerTunnelHTTP (name, host, port, localDestination, inPort) : + new I2PServerTunnelHTTP (name, host, port, localDestination, hostOverride, inPort) : new I2PServerTunnel (name, host, port, localDestination, inPort); if (accessList.length () > 0) { diff --git a/ClientContext.h b/ClientContext.h index 52f1ab5b..30e495da 100644 --- a/ClientContext.h +++ b/ClientContext.h @@ -28,6 +28,7 @@ namespace client const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype"; const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport"; const char I2P_SERVER_TUNNEL_HOST[] = "host"; + const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride"; const char I2P_SERVER_TUNNEL_PORT[] = "port"; const char I2P_SERVER_TUNNEL_KEYS[] = "keys"; const char I2P_SERVER_TUNNEL_SIGNATURE_TYPE[] = "signaturetype"; diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index 07b9bd83..4eb1c573 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -422,14 +422,17 @@ namespace client } I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, int inport): - I2PServerTunnel (name, address, port, localDestination, inport) + int port, std::shared_ptr localDestination, + const std::string& host, int inport): + I2PServerTunnel (name, address, port, localDestination, inport), + m_Host (host.length () > 0 ? host : address) { } void I2PServerTunnelHTTP::CreateI2PConnection (std::shared_ptr stream) { - auto conn = std::make_shared (this, stream, std::make_shared (GetService ()), GetEndpoint (), GetAddress ()); + auto conn = std::make_shared (this, stream, + std::make_shared (GetService ()), GetEndpoint (), m_Host); AddHandler (conn); conn->Connect (); } diff --git a/I2PTunnel.h b/I2PTunnel.h index 4530a141..834897f7 100644 --- a/I2PTunnel.h +++ b/I2PTunnel.h @@ -152,11 +152,16 @@ namespace client public: I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port, - std::shared_ptr localDestination, int inport = 0); + std::shared_ptr localDestination, const std::string& host, + int inport = 0); private: - void CreateI2PConnection (std::shared_ptr stream); + void CreateI2PConnection (std::shared_ptr stream); + + private: + + std::string m_Host; }; } } diff --git a/SSUSession.cpp b/SSUSession.cpp index a6676cca..1fa29475 100644 --- a/SSUSession.cpp +++ b/SSUSession.cpp @@ -324,6 +324,18 @@ namespace transport { uint8_t buf[320 + 18]; // 304 bytes for ipv4, 320 for ipv6 uint8_t * payload = buf + sizeof (SSUHeader); + uint8_t flag = 0; + // fill extended options, 3 bytes extended options don't change message size + if (i2p::context.GetStatus () == eRouterStatusOK) // we don't need relays + { + // tell out peer to now assign relay tag + flag = SSU_HEADER_EXTENDED_OPTIONS_INCLUDED; + *payload = 2; payload++; // 1 byte length + uint16_t flags = 0; // clear EXTENDED_OPTIONS_FLAG_REQUEST_RELAY_TAG + htobe16buf (payload, flags); + payload += 2; + } + // fill payload memcpy (payload, m_DHKeysPair->GetPublicKey (), 256); // x bool isV4 = m_RemoteEndpoint.address ().is_v4 (); if (isV4) @@ -336,10 +348,10 @@ namespace transport payload[256] = 16; memcpy (payload + 257, m_RemoteEndpoint.address ().to_v6 ().to_bytes ().data(), 16); } - + // encrypt and send uint8_t iv[16]; RAND_bytes (iv, 16); // random iv - FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_REQUEST, buf, isV4 ? 304 : 320, m_IntroKey, iv, m_IntroKey); + FillHeaderAndEncrypt (PAYLOAD_TYPE_SESSION_REQUEST, buf, isV4 ? 304 : 320, m_IntroKey, iv, m_IntroKey, flag); m_Server.Send (buf, isV4 ? 304 : 320, m_RemoteEndpoint); } @@ -666,7 +678,7 @@ namespace transport } void SSUSession::FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, - const i2p::crypto::AESKey& aesKey, const uint8_t * iv, const i2p::crypto::MACKey& macKey) + const i2p::crypto::AESKey& aesKey, const uint8_t * iv, const i2p::crypto::MACKey& macKey, uint8_t flag) { if (len < sizeof (SSUHeader)) { @@ -675,7 +687,7 @@ namespace transport } SSUHeader * header = (SSUHeader *)buf; memcpy (header->iv, iv, 16); - header->flag = payloadType << 4; // MSB is 0 + header->flag = flag | (payloadType << 4); // MSB is 0 htobe32buf (header->time, i2p::util::GetSecondsSinceEpoch ()); uint8_t * encrypted = &header->flag; uint16_t encryptedLen = len - (encrypted - buf); diff --git a/SSUSession.h b/SSUSession.h index 2fbc0f67..cfe24f6c 100644 --- a/SSUSession.h +++ b/SSUSession.h @@ -124,7 +124,8 @@ namespace transport void Send (uint8_t type, const uint8_t * payload, size_t len); // with session key void Send (const uint8_t * buf, size_t size); - void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey, const uint8_t * iv, const i2p::crypto::MACKey& macKey); + void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey, + const uint8_t * iv, const i2p::crypto::MACKey& macKey, uint8_t flag = 0); void FillHeaderAndEncrypt (uint8_t payloadType, uint8_t * buf, size_t len); // with session key void Decrypt (uint8_t * buf, size_t len, const i2p::crypto::AESKey& aesKey); void DecryptSessionKey (uint8_t * buf, size_t len);