File: socks_server.hpp

package info (click to toggle)
libtorrent-rasterbar 2.0.11-1
  • links: PTS
  • area: main
  • in suites: forky, trixie
  • size: 18,304 kB
  • sloc: cpp: 190,670; python: 7,142; makefile: 1,374; ansic: 574; sh: 317; xml: 104
file content (202 lines) | stat: -rw-r--r-- 5,798 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*

Copyright (c) 2015, Arvid Norberg
All rights reserved.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#ifndef SOCKS_SERVER_HPP_INCLUDED
#define SOCKS_SERVER_HPP_INCLUDED

#include "simulator/simulator.hpp"

#ifdef __GNUC__
#pragma GCC diagnostic push
#if __GNUC__ >= 9
#pragma GCC diagnostic ignored "-Wparentheses"
#endif
#endif

#include <boost/bimap.hpp>

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif

#ifdef _MSC_VER
#pragma warning(push)
// warning C4251: X: class Y needs to have dll-interface to be used by clients of struct
#pragma warning( disable : 4251)
#endif

namespace sim
{

enum socks_flag
{
	// when this flag is set, the proxy will close the client connection
	// immediately after sending the response to a UDP ASSOCIATE command
	disconnect_udp_associate = 1,

	// when this flag is set, the reponse to UDP ASSOCIATE will contain an empty
	// hostname, rather than the relay IP address
	udp_associate_respond_empty_hostname = 2
};

struct SIMULATOR_DECL socks_connection : std::enable_shared_from_this<socks_connection>
{
	socks_connection(asio::io_context& ios, int version, std::array<int, 3>& cmd_counts
		, std::uint32_t flags, int& bind_port);

	asio::ip::tcp::socket& socket() { return m_client_connection; }

	void start();

private:

	void on_handshake1(boost::system::error_code const& ec, size_t bytes_transferred);
	void on_handshake2(boost::system::error_code const& ec, size_t bytes_transferred);
	void on_handshake3(boost::system::error_code const& ec, size_t bytes_transferred);
	void on_request1(boost::system::error_code const& ec, size_t bytes_transferred);
	void on_request2(boost::system::error_code const& ec, size_t bytes_transferred);

	void on_write(boost::system::error_code const& ec, size_t bytes_transferred
		, bool close);
	void close_connection();

	int format_response(asio::ip::address const& addr, int port, int response);
	int format_hostname_response(char const* hostname, int port, int response);

	void on_connected(boost::system::error_code const& ec);
	void on_request_domain_name(boost::system::error_code const& ec, size_t bytes_transferred);
	void on_request_domain_lookup(boost::system::error_code const& ec
		, const asio::ip::tcp::resolver::results_type ips);

	void open_forward_connection(asio::ip::tcp::endpoint const& target);
	void bind_connection(asio::ip::tcp::endpoint const& target);
	void start_accept(boost::system::error_code const& ec);

	void udp_associate(asio::ip::tcp::endpoint const& target);
	void on_read_udp(boost::system::error_code const& ec, std::size_t bytes_transferred);
	void wait_for_eof(boost::system::error_code const& ec, std::size_t bytes_transferred);

	void on_server_receive(boost::system::error_code const& ec
		, std::size_t bytes_transferred);
	void on_server_forward(boost::system::error_code const& ec
		, size_t bytes_transferred);

	void on_client_receive(boost::system::error_code const& ec
		, std::size_t bytes_transferred);
	void on_client_forward(boost::system::error_code const& ec
		, size_t bytes_transferred);

	char const* command() const;

	int& m_bind_port;

	asio::io_context& m_ios;

	asio::ip::udp::resolver m_udp_resolver;

	asio::ip::tcp::resolver m_resolver;

	boost::bimap<asio::ip::address, std::string> m_name_mapping;

	// this is the SOCKS client connection, i.e. the client connecting to us and
	// being forwarded
	asio::ip::tcp::socket m_client_connection;

	// this is the connection to the server the socks client is being forwarded
	// to
	asio::ip::tcp::socket m_server_connection;
	asio::ip::tcp::acceptor m_bind_socket;

	asio::ip::udp::socket m_udp_associate;
	asio::ip::udp::endpoint m_udp_associate_ep;
	asio::ip::udp::endpoint m_udp_from;

	std::array<char, 1500> m_udp_buffer;

	// receive buffer for data going out, i.e. client -> proxy (us) -> server
	char m_out_buffer[65536];
	// buffer size
	int m_num_out_bytes;

	// receive buffer for data coming in, i.e. server -> proxy (us) -> client
	char m_in_buffer[65536];
	// buffer size
	int m_num_in_bytes;

	// set to true when shutting down
	bool m_close = false;

	// the SOCKS protocol version (4 or 5)
	const int m_version;

	int m_command;

	std::array<int, 3>& m_cmd_counts;

	std::uint32_t const m_flags;
};

// This is a very simple socks4 and 5 server that only supports a single
// concurrent connection
struct SIMULATOR_DECL socks_server
{
	socks_server(asio::io_context& ios, unsigned short listen_port
		, int version = 5, std::uint32_t flags = 0);

	void stop();

	void bind_start_port(int const port) { m_bind_port = port; }

	// return the number of CONNECT, BIND and UDP_ASSOCIATE commands the proxy
	// has received
	std::array<int, 3> cmd_counts() const
	{ return m_cmd_counts; }

private:

	void on_accept(boost::system::error_code const& ec);

	asio::io_context& m_ios;

	asio::ip::tcp::acceptor m_listen_socket;

	std::shared_ptr<socks_connection> m_conn;

	asio::ip::tcp::endpoint m_ep;

	int m_bind_port = 2048;

	// set to true when shutting down
	bool m_close = false;

	// the SOCKS protocol version (4 or 5)
	const int m_version;

	std::array<int, 3> m_cmd_counts;

	std::uint32_t const m_flags;
};

}

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#endif