Skip to content

Commit 1f4f990

Browse files
committed
Rebased pull request
Shopify#270 With small modifications for new APIs and new toxic that drops connection after a timeout
1 parent 7abcb6f commit 1f4f990

File tree

6 files changed

+412
-12
lines changed

6 files changed

+412
-12
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,7 @@ dist/
55
vendor/
66

77
tmp/
8+
9+
config/
10+
11+
.vscode/

README.md

+25
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,31 @@ An example `config/toxiproxy.json`:
330330
]
331331
```
332332

333+
An example `config/toxiproxy.json` with the experimental TLS feature:
334+
335+
```json
336+
[
337+
{
338+
"name": "plain",
339+
"listen": "[::]:1080",
340+
"upstream": "www.arnes.si:80",
341+
"enabled": true
342+
},
343+
{
344+
"name": "ssl",
345+
"listen": "[::]:1443",
346+
"upstream": "www.arnes.si:443",
347+
"enabled": true,
348+
"tls": {
349+
"cert": "./cert.crt",
350+
"key": "./cert.key"
351+
}
352+
}
353+
]
354+
```
355+
356+
For more details about TLS please check [TLS.md](./TLS.md).
357+
333358
Use ports outside the ephemeral port range to avoid random port conflicts.
334359
It's `32,768` to `61,000` on Linux by default, see
335360
`/proc/sys/net/ipv4/ip_local_port_range`.

TLS.md

+117
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# TLS
2+
3+
Using Toxiproxy with TLS presents its own challenges.
4+
There are multiple ways how to use Toxiproxy in such a set-up.
5+
6+
## Plain-connection
7+
8+
That means Toxiproxy will just act as a TCP proxy. No patches are necessary.
9+
TLS handshake will still be performed with actual endpoint. Thus Toxiproxy will
10+
not be able to see (plain-text) traffic but may still apply toxics (like delays) to the flow.
11+
12+
Example `config/toxiproxy.json`
13+
```json
14+
[
15+
{
16+
"name": "quasissl",
17+
"listen": "[::]:443",
18+
"upstream": "www.arnes.si:443",
19+
"enabled": true
20+
}
21+
]
22+
```
23+
24+
In this case you need to make sure the hostname (www.arnes.si in the example)
25+
points to Toxiproxy IP. You could use hosts file for that with an entry like
26+
27+
```
28+
127.0.0.1 www.arnes.si
29+
```
30+
31+
but that isn't really the best option. A more scalable solution would be to change your DNS server to return fake responses.
32+
Easiest is probably [Coredns](https://coredns.io) with rewrite plugin.
33+
34+
Other option is a transparent proxy to forward specific traffic via iptables/netfilter rules.
35+
36+
## TLS connection with static certificate
37+
38+
In this mode patched Toxiproxy will terminate the TLS connection and always return the configured certificate.
39+
40+
Example `config/toxiproxy.json`
41+
```json
42+
[
43+
{
44+
"name": "ssl",
45+
"listen": "[::]:443",
46+
"upstream": "www.arnes.si:443",
47+
"enabled": true,
48+
"tls": {
49+
"cert": "./cert.crt",
50+
"key": "./cert.key"
51+
}
52+
}
53+
]
54+
```
55+
56+
In this case users will configure different hostname - say toxiproxy.mydomain.org instead of www.arnes.si. If you have
57+
proper X.509 certificate for toxiproxy.mydomain.org (for instance through [Let's Encrypt](https://letsencrypt.org)) everything
58+
will behave fine.
59+
60+
TLS section has an additional option:
61+
"verifyUpstream" that is by default set to false. That is if we are already performing a Man-In-The-Middle attack it doesn't really make much
62+
sense to be cautious about the upstream doing something similar. But you can always do something like:
63+
64+
```json
65+
[
66+
{
67+
"name": "ssl",
68+
"listen": "[::]:443",
69+
"upstream": "www.arnes.si:443",
70+
"enabled": true,
71+
"tls": {
72+
"cert": "./cert.crt",
73+
"key": "./cert.key",
74+
"verifyUpstream": true
75+
}
76+
}
77+
]
78+
```
79+
80+
## Dynamic certificates based on SNI
81+
82+
In this mode patched Toxiproxy will observe what the hostname was in the request and use the given certificate as a CA to sign the new (dummy) certificate
83+
that matches this hostname. Currently it will generate 2048 bit RSA keypair for that purpose.
84+
85+
This mode is very similar to the first one (except that Toxiproxy is doing the TLS termination and can see plain-text traffic).
86+
87+
An example `config/toxiproxy.json`:
88+
89+
```json
90+
[
91+
{
92+
"name": "ssl",
93+
"listen": "[::]:443",
94+
"upstream": "www.arnes.si:443",
95+
"enabled": true,
96+
"tls": {
97+
"cert": "./cert.crt",
98+
"key": "./cert.key",
99+
"isCA": true
100+
}
101+
}
102+
]
103+
104+
Here you need to do something similar to option number 1 and additionally also configure the given CA cert (still passed in the configuration as cert/key) as trusted on all machines
105+
that will be connecting to Toxiproxy. Benefit is that you can centrally configure the interception rules (no need to change endpoints).
106+
107+
You could use something like [SNIproxy](https://github.com/dlundquist/sniproxy) in front which makes it easier to just forward everything to the proxy and then route just specific
108+
stuff through Toxiproxy.
109+
110+
When isCA is true Toxiproxy will verify that cert.crt is actually a CA certificate (but you can always create a self-signed one of course). For now encrypted private key is not supported
111+
(so be careful).
112+
113+
It is also possible to use "verifyUpstream" setting in this mode.
114+
115+
## Notes
116+
117+
Note that currently there is no option that Toxiproxy would terminate TLS connection and make a plain-text connection to the upstream as (for now) there is no use-case for it.

0 commit comments

Comments
 (0)