@@ -9,6 +9,11 @@ Async HTTP CONNECT proxy connector, use any TCP/IP protocol through an HTTP prox
9
9
* [ ConnectorInterface] ( #connectorinterface )
10
10
* [ connect()] ( #connect )
11
11
* [ ProxyConnector] ( #proxyconnector )
12
+ * [ Plain TCP connections] ( #plain-tcp-connections )
13
+ * [ Secure TLS connections] ( #secure-tls-connections )
14
+ * [ Connection timeout] ( #connection-timeout )
15
+ * [ DNS resolution] ( #dns-resolution )
16
+ * [ Advanced secure proxy connections] ( #advanced-secure-proxy-connections )
12
17
* [ Install] ( #install )
13
18
* [ Tests] ( #tests )
14
19
* [ License] ( #license )
@@ -21,11 +26,15 @@ secure HTTPS request to google.com through a local HTTP proxy server:
21
26
22
27
``` php
23
28
$loop = React\EventLoop\Factory::create();
24
- $connector = new TcpConnector($loop);
25
- $proxy = new ProxyConnector('127.0.0.1:8080', $connector);
26
- $ssl = new SecureConnector($proxy, $loop);
27
29
28
- $ssl->connect('google.com:443')->then(function (ConnectionInterface $stream) {
30
+ $proxy = new ProxyConnector('127.0.0.1:8080', new Connector($loop));
31
+ $connector = new Connector($loop, array(
32
+ 'tcp' => $proxy,
33
+ 'timeout' => 3.0,
34
+ 'dns' => false
35
+ ));
36
+
37
+ $connector->connect('tls://google.com:443')->then(function (ConnectionInterface $stream) {
29
38
$stream->write("GET / HTTP/1.1\r\nHost: google.com\r\nConnection: close\r\n\r\n");
30
39
$stream->on('data', function ($chunk) {
31
40
echo $chunk;
@@ -91,15 +100,15 @@ Its constructor simply accepts an HTTP proxy URL and a connector used to connect
91
100
to the proxy server address:
92
101
93
102
``` php
94
- $connector = new TcpConnector ($loop);
103
+ $connector = new Connector ($loop);
95
104
$proxy = new ProxyConnector('127.0.0.1:8080', $connector);
96
105
```
97
106
98
107
The proxy URL may or may not contain a scheme and port definition. The default
99
108
port will be ` 80 ` for HTTP (or ` 443 ` for HTTPS), but many common HTTP proxy
100
109
servers use custom ports.
101
110
In its most simple form, the given connector will be a
102
- [ ` TcpConnector ` ] ( https://github.com/reactphp/socket#tcpconnector ) if you
111
+ [ ` \React\Socket\Connector ` ] ( https://github.com/reactphp/socket#connector ) if you
103
112
want to connect to a given IP address as above.
104
113
105
114
This is the main class in this package.
@@ -114,14 +123,36 @@ higher-level component:
114
123
+ $client = new SomeClient($proxy);
115
124
```
116
125
126
+ #### Plain TCP connections
127
+
117
128
This is most frequently used to issue HTTPS requests to your destination.
118
129
However, this is actually performed on a higher protocol layer and this
119
- connector is actually inherently a general-purpose plain TCP/IP connector:
130
+ connector is actually inherently a general-purpose plain TCP/IP connector.
131
+
132
+ The ` ProxyConnector ` implements the [ ` ConnectorInterface ` ] ( #connectorinterface ) and
133
+ hence provides a single public method, the [ ` connect() ` ] ( #connect ) method.
120
134
121
135
``` php
122
136
$proxy = new ProxyConnector('127.0.0.1:8080', $connector);
123
137
124
- $proxy->connect('smtp.googlemail.com:587')->then(function (ConnectionInterface $stream) {
138
+ $proxy->connect('tcp://smtp.googlemail.com:587')->then(function (ConnectionInterface $stream) {
139
+ $stream->write("EHLO local\r\n");
140
+ $stream->on('data', function ($chunk) use ($stream) {
141
+ echo $chunk;
142
+ });
143
+ });
144
+ ```
145
+
146
+ You can either use the ` ProxyConnector ` directly or you may want to wrap this connector
147
+ in React's [ ` Connector ` ] ( https://github.com/reactphp/socket#connector ) :
148
+
149
+ ``` php
150
+ $connector = new Connector($loop, array(
151
+ 'tcp' => $proxy,
152
+ 'dns' => false
153
+ ));
154
+
155
+ $connector->connect('tcp://smtp.googlemail.com:587')->then(function (ConnectionInterface $stream) {
125
156
$stream->write("EHLO local\r\n");
126
157
$stream->on('data', function ($chunk) use ($stream) {
127
158
echo $chunk;
@@ -132,23 +163,112 @@ $proxy->connect('smtp.googlemail.com:587')->then(function (ConnectionInterface $
132
163
Note that HTTP CONNECT proxies often restrict which ports one may connect to.
133
164
Many (public) proxy servers do in fact limit this to HTTPS (443) only.
134
165
166
+ #### Secure TLS connections
167
+
135
168
If you want to establish a TLS connection (such as HTTPS) between you and
136
- your destination, you may want to wrap this connector in a
137
- [ ` SecureConnector ` ] ( https://github.com/reactphp/socket#secureconnector )
138
- instance :
169
+ your destination, you may want to wrap this connector in React's
170
+ [ ` Connector ` ] ( https://github.com/reactphp/socket#connector ) or the low-level
171
+ [ ` SecureConnector ` ] ( https://github.com/reactphp/socket#secureconnector ) :
139
172
140
173
``` php
141
174
$proxy = new ProxyConnector('127.0.0.1:8080', $connector);
142
- $ssl = new SecureConnector($proxy, $loop);
175
+ $connector = new Connector($loop, array(
176
+ 'tcp' => $proxy,
177
+ 'dns' => false
178
+ ));
143
179
144
- $ssl ->connect('smtp.googlemail.com:465')->then(function (ConnectionInterface $stream) {
180
+ $connector ->connect('tls:// smtp.googlemail.com:465')->then(function (ConnectionInterface $stream) {
145
181
$stream->write("EHLO local\r\n");
146
182
$stream->on('data', function ($chunk) use ($stream) {
147
183
echo $chunk;
148
184
});
149
185
});
150
186
```
151
187
188
+ > Also note how secure TLS connections are in fact entirely handled outside of
189
+ this HTTP CONNECT client implementation.
190
+
191
+ #### Connection timeout
192
+
193
+ By default, the ` ProxyConnector ` does not implement any timeouts for establishing remote
194
+ connections.
195
+ Your underlying operating system may impose limits on pending and/or idle TCP/IP
196
+ connections, anywhere in a range of a few minutes to several hours.
197
+
198
+ Many use cases require more control over the timeout and likely values much
199
+ smaller, usually in the range of a few seconds only.
200
+
201
+ You can use React's [ ` Connector ` ] ( https://github.com/reactphp/socket#connector )
202
+ or the low-level
203
+ [ ` TimeoutConnector ` ] ( https://github.com/reactphp/socket#timeoutconnector )
204
+ to decorate any given ` ConnectorInterface ` instance.
205
+ It provides the same ` connect() ` method, but will automatically reject the
206
+ underlying connection attempt if it takes too long:
207
+
208
+ ``` php
209
+ $connector = new Connector($loop, array(
210
+ 'tcp' => $proxy,
211
+ 'dns' => false,
212
+ 'timeout' => 3.0
213
+ ));
214
+
215
+ $connector->connect('tcp://google.com:80')->then(function ($stream) {
216
+ // connection succeeded within 3.0 seconds
217
+ });
218
+ ```
219
+
220
+ See also any of the [ examples] ( examples ) .
221
+
222
+ > Also note how connection timeout is in fact entirely handled outside of this
223
+ HTTP CONNECT client implementation.
224
+
225
+ #### DNS resolution
226
+
227
+ By default, the ` ProxyConnector ` does not perform any DNS resolution at all and simply
228
+ forwards any hostname you're trying to connect to the remote proxy server.
229
+ The remote proxy server is thus responsible for looking up any hostnames via DNS
230
+ (this default mode is thus called * remote DNS resolution* ).
231
+
232
+ As an alternative, you can also send the destination IP to the remote proxy
233
+ server.
234
+ In this mode you either have to stick to using IPs only (which is ofen unfeasable)
235
+ or perform any DNS lookups locally and only transmit the resolved destination IPs
236
+ (this mode is thus called * local DNS resolution* ).
237
+
238
+ The default * remote DNS resolution* is useful if your local ` ProxyConnector ` either can
239
+ not resolve target hostnames because it has no direct access to the internet or
240
+ if it should not resolve target hostnames because its outgoing DNS traffic might
241
+ be intercepted.
242
+
243
+ As noted above, the ` ProxyConnector ` defaults to using remote DNS resolution.
244
+ However, wrapping the ` ProxyConnector ` in React's
245
+ [ ` Connector ` ] ( https://github.com/reactphp/socket#connector ) actually
246
+ performs local DNS resolution unless explicitly defined otherwise.
247
+ Given that remote DNS resolution is assumed to be the preferred mode, all
248
+ other examples explicitly disable DNS resoltion like this:
249
+
250
+ ``` php
251
+ $connector = new Connector($loop, array(
252
+ 'tcp' => $proxy,
253
+ 'dns' => false
254
+ ));
255
+ ```
256
+
257
+ If you want to explicitly use * local DNS resolution* , you can use the following code:
258
+
259
+ ``` php
260
+ // set up Connector which uses Google's public DNS (8.8.8.8)
261
+ $connector = Connector($loop, array(
262
+ 'tcp' => $proxy,
263
+ 'dns' => '8.8.8.8'
264
+ ));
265
+ ```
266
+
267
+ > Also note how local DNS resolution is in fact entirely handled outside of this
268
+ HTTP CONNECT client implementation.
269
+
270
+ #### Advanced secure proxy connections
271
+
152
272
Note that communication between the client and the proxy is usually via an
153
273
unencrypted, plain TCP/IP HTTP connection. Note that this is the most common
154
274
setup, because you can still establish a TLS connection between you and the
0 commit comments