I2PTunnel.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. #ifndef I2PTUNNEL_H__
  2. #define I2PTUNNEL_H__
  3. #include <inttypes.h>
  4. #include <string>
  5. #include <set>
  6. #include <tuple>
  7. #include <memory>
  8. #include <sstream>
  9. #include <boost/asio.hpp>
  10. #include "Identity.h"
  11. #include "Destination.h"
  12. #include "Datagram.h"
  13. #include "Streaming.h"
  14. #include "I2PService.h"
  15. #include "AddressBook.h"
  16. namespace i2p
  17. {
  18. namespace client
  19. {
  20. const size_t I2P_TUNNEL_CONNECTION_BUFFER_SIZE = 65536;
  21. const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds
  22. const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds
  23. // for HTTP tunnels
  24. const char X_I2P_DEST_HASH[] = "X-I2P-DestHash"; // hash in base64
  25. const char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64
  26. const char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address
  27. class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection>
  28. {
  29. public:
  30. I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
  31. std::shared_ptr<const i2p::data::LeaseSet> leaseSet, int port = 0); // to I2P
  32. I2PTunnelConnection (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
  33. std::shared_ptr<i2p::stream::Stream> stream); // to I2P using simplified API
  34. I2PTunnelConnection (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
  35. const boost::asio::ip::tcp::endpoint& target, bool quiet = true); // from I2P
  36. ~I2PTunnelConnection ();
  37. void I2PConnect (const uint8_t * msg = nullptr, size_t len = 0);
  38. void Connect (bool isUniqueLocal = true);
  39. protected:
  40. void Terminate ();
  41. void Receive ();
  42. void HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
  43. virtual void Write (const uint8_t * buf, size_t len); // can be overloaded
  44. void HandleWrite (const boost::system::error_code& ecode);
  45. void StreamReceive ();
  46. void HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred);
  47. void HandleConnect (const boost::system::error_code& ecode);
  48. std::shared_ptr<const boost::asio::ip::tcp::socket> GetSocket () const { return m_Socket; };
  49. private:
  50. uint8_t m_Buffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE], m_StreamBuffer[I2P_TUNNEL_CONNECTION_BUFFER_SIZE];
  51. std::shared_ptr<boost::asio::ip::tcp::socket> m_Socket;
  52. std::shared_ptr<i2p::stream::Stream> m_Stream;
  53. boost::asio::ip::tcp::endpoint m_RemoteEndpoint;
  54. bool m_IsQuiet; // don't send destination
  55. };
  56. class I2PClientTunnelConnectionHTTP: public I2PTunnelConnection
  57. {
  58. public:
  59. I2PClientTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<boost::asio::ip::tcp::socket> socket,
  60. std::shared_ptr<i2p::stream::Stream> stream):
  61. I2PTunnelConnection (owner, socket, stream), m_HeaderSent (false),
  62. m_ConnectionSent (false), m_ProxyConnectionSent (false) {};
  63. protected:
  64. void Write (const uint8_t * buf, size_t len);
  65. private:
  66. std::stringstream m_InHeader, m_OutHeader;
  67. bool m_HeaderSent, m_ConnectionSent, m_ProxyConnectionSent;
  68. };
  69. class I2PServerTunnelConnectionHTTP: public I2PTunnelConnection
  70. {
  71. public:
  72. I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
  73. std::shared_ptr<boost::asio::ip::tcp::socket> socket,
  74. const boost::asio::ip::tcp::endpoint& target, const std::string& host);
  75. protected:
  76. void Write (const uint8_t * buf, size_t len);
  77. private:
  78. std::string m_Host;
  79. std::stringstream m_InHeader, m_OutHeader;
  80. bool m_HeaderSent;
  81. std::shared_ptr<const i2p::data::IdentityEx> m_From;
  82. };
  83. class I2PTunnelConnectionIRC: public I2PTunnelConnection
  84. {
  85. public:
  86. I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
  87. std::shared_ptr<boost::asio::ip::tcp::socket> socket,
  88. const boost::asio::ip::tcp::endpoint& target, const std::string& m_WebircPass);
  89. protected:
  90. void Write (const uint8_t * buf, size_t len);
  91. private:
  92. std::shared_ptr<const i2p::data::IdentityEx> m_From;
  93. std::stringstream m_OutPacket, m_InPacket;
  94. bool m_NeedsWebIrc;
  95. std::string m_WebircPass;
  96. };
  97. class I2PClientTunnel: public TCPIPAcceptor
  98. {
  99. protected:
  100. // Implements TCPIPAcceptor
  101. std::shared_ptr<I2PServiceHandler> CreateHandler(std::shared_ptr<boost::asio::ip::tcp::socket> socket);
  102. public:
  103. I2PClientTunnel (const std::string& name, const std::string& destination,
  104. const std::string& address, int port, std::shared_ptr<ClientDestination> localDestination, int destinationPort = 0);
  105. ~I2PClientTunnel () {}
  106. void Start ();
  107. void Stop ();
  108. const char* GetName() { return m_Name.c_str (); }
  109. private:
  110. std::shared_ptr<const Address> GetAddress ();
  111. private:
  112. std::string m_Name, m_Destination;
  113. std::shared_ptr<const Address> m_Address;
  114. int m_DestinationPort;
  115. };
  116. /** 2 minute timeout for udp sessions */
  117. const uint64_t I2P_UDP_SESSION_TIMEOUT = 1000 * 60 * 2;
  118. /** max size for i2p udp */
  119. const size_t I2P_UDP_MAX_MTU = i2p::datagram::MAX_DATAGRAM_SIZE;
  120. struct UDPSession
  121. {
  122. i2p::datagram::DatagramDestination * m_Destination;
  123. boost::asio::ip::udp::socket IPSocket;
  124. i2p::data::IdentHash Identity;
  125. boost::asio::ip::udp::endpoint FromEndpoint;
  126. boost::asio::ip::udp::endpoint SendEndpoint;
  127. uint64_t LastActivity;
  128. uint16_t LocalPort;
  129. uint16_t RemotePort;
  130. uint8_t m_Buffer[I2P_UDP_MAX_MTU];
  131. UDPSession(boost::asio::ip::udp::endpoint localEndpoint,
  132. const std::shared_ptr<i2p::client::ClientDestination> & localDestination,
  133. boost::asio::ip::udp::endpoint remote, const i2p::data::IdentHash * ident,
  134. uint16_t ourPort, uint16_t theirPort);
  135. void HandleReceived(const boost::system::error_code & ecode, std::size_t len);
  136. void Receive();
  137. };
  138. /** read only info about a datagram session */
  139. struct DatagramSessionInfo
  140. {
  141. /** the name of this forward */
  142. std::string Name;
  143. /** ident hash of local destination */
  144. std::shared_ptr<const i2p::data::IdentHash> LocalIdent;
  145. /** ident hash of remote destination */
  146. std::shared_ptr<const i2p::data::IdentHash> RemoteIdent;
  147. /** ident hash of IBGW in use currently in this session or nullptr if none is set */
  148. std::shared_ptr<const i2p::data::IdentHash> CurrentIBGW;
  149. /** ident hash of OBEP in use for this session or nullptr if none is set */
  150. std::shared_ptr<const i2p::data::IdentHash> CurrentOBEP;
  151. /** i2p router's udp endpoint */
  152. boost::asio::ip::udp::endpoint LocalEndpoint;
  153. /** client's udp endpoint */
  154. boost::asio::ip::udp::endpoint RemoteEndpoint;
  155. /** how long has this converstation been idle in ms */
  156. uint64_t idle;
  157. };
  158. typedef std::shared_ptr<UDPSession> UDPSessionPtr;
  159. /** server side udp tunnel, many i2p inbound to 1 ip outbound */
  160. class I2PUDPServerTunnel
  161. {
  162. public:
  163. I2PUDPServerTunnel(const std::string & name,
  164. std::shared_ptr<i2p::client::ClientDestination> localDestination,
  165. boost::asio::ip::address localAddress,
  166. boost::asio::ip::udp::endpoint forwardTo, uint16_t port);
  167. ~I2PUDPServerTunnel();
  168. /** expire stale udp conversations */
  169. void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
  170. void Start();
  171. const char * GetName() const { return m_Name.c_str(); }
  172. std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions();
  173. std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; }
  174. void SetUniqueLocal(bool isUniqueLocal = true) { m_IsUniqueLocal = isUniqueLocal; }
  175. private:
  176. void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
  177. UDPSessionPtr ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort);
  178. private:
  179. bool m_IsUniqueLocal;
  180. const std::string m_Name;
  181. boost::asio::ip::address m_LocalAddress;
  182. boost::asio::ip::udp::endpoint m_RemoteEndpoint;
  183. std::mutex m_SessionsMutex;
  184. std::vector<UDPSessionPtr> m_Sessions;
  185. std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
  186. };
  187. class I2PUDPClientTunnel
  188. {
  189. public:
  190. I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest,
  191. boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr<i2p::client::ClientDestination> localDestination,
  192. uint16_t remotePort);
  193. ~I2PUDPClientTunnel();
  194. void Start();
  195. const char * GetName() const { return m_Name.c_str(); }
  196. std::vector<std::shared_ptr<DatagramSessionInfo> > GetSessions();
  197. bool IsLocalDestination(const i2p::data::IdentHash & destination) const { return destination == m_LocalDest->GetIdentHash(); }
  198. std::shared_ptr<ClientDestination> GetLocalDestination () const { return m_LocalDest; }
  199. void ExpireStale(const uint64_t delta=I2P_UDP_SESSION_TIMEOUT);
  200. private:
  201. typedef std::pair<boost::asio::ip::udp::endpoint, uint64_t> UDPConvo;
  202. void RecvFromLocal();
  203. void HandleRecvFromLocal(const boost::system::error_code & e, std::size_t transferred);
  204. void HandleRecvFromI2P(const i2p::data::IdentityEx& from, uint16_t fromPort, uint16_t toPort, const uint8_t * buf, size_t len);
  205. void TryResolving();
  206. const std::string m_Name;
  207. std::mutex m_SessionsMutex;
  208. std::map<uint16_t, UDPConvo > m_Sessions; // maps i2p port -> local udp convo
  209. const std::string m_RemoteDest;
  210. std::shared_ptr<i2p::client::ClientDestination> m_LocalDest;
  211. const boost::asio::ip::udp::endpoint m_LocalEndpoint;
  212. i2p::data::IdentHash * m_RemoteIdent;
  213. std::thread * m_ResolveThread;
  214. boost::asio::ip::udp::socket m_LocalSocket;
  215. boost::asio::ip::udp::endpoint m_RecvEndpoint;
  216. uint8_t m_RecvBuff[I2P_UDP_MAX_MTU];
  217. uint16_t RemotePort;
  218. bool m_cancel_resolve;
  219. };
  220. class I2PServerTunnel: public I2PService
  221. {
  222. public:
  223. I2PServerTunnel (const std::string& name, const std::string& address, int port,
  224. std::shared_ptr<ClientDestination> localDestination, int inport = 0, bool gzip = true);
  225. void Start ();
  226. void Stop ();
  227. void SetAccessList (const std::set<i2p::data::IdentHash>& accessList);
  228. void SetUniqueLocal (bool isUniqueLocal) { m_IsUniqueLocal = isUniqueLocal; }
  229. bool IsUniqueLocal () const { return m_IsUniqueLocal; }
  230. const std::string& GetAddress() const { return m_Address; }
  231. int GetPort () const { return m_Port; };
  232. uint16_t GetLocalPort () const { return m_PortDestination->GetLocalPort (); };
  233. const boost::asio::ip::tcp::endpoint& GetEndpoint () const { return m_Endpoint; }
  234. const char* GetName() { return m_Name.c_str (); }
  235. private:
  236. void HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it,
  237. std::shared_ptr<boost::asio::ip::tcp::resolver> resolver);
  238. void Accept ();
  239. void HandleAccept (std::shared_ptr<i2p::stream::Stream> stream);
  240. virtual std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
  241. private:
  242. bool m_IsUniqueLocal;
  243. std::string m_Name, m_Address;
  244. int m_Port;
  245. boost::asio::ip::tcp::endpoint m_Endpoint;
  246. std::shared_ptr<i2p::stream::StreamingDestination> m_PortDestination;
  247. std::set<i2p::data::IdentHash> m_AccessList;
  248. bool m_IsAccessList;
  249. };
  250. class I2PServerTunnelHTTP: public I2PServerTunnel
  251. {
  252. public:
  253. I2PServerTunnelHTTP (const std::string& name, const std::string& address, int port,
  254. std::shared_ptr<ClientDestination> localDestination, const std::string& host,
  255. int inport = 0, bool gzip = true);
  256. private:
  257. std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
  258. private:
  259. std::string m_Host;
  260. };
  261. class I2PServerTunnelIRC: public I2PServerTunnel
  262. {
  263. public:
  264. I2PServerTunnelIRC (const std::string& name, const std::string& address, int port,
  265. std::shared_ptr<ClientDestination> localDestination, const std::string& webircpass,
  266. int inport = 0, bool gzip = true);
  267. private:
  268. std::shared_ptr<I2PTunnelConnection> CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream);
  269. private:
  270. std::string m_WebircPass;
  271. };
  272. }
  273. }
  274. #endif