Establish TLS or DTLS between client and proxy.
(self, tls_start: tls.TlsData)
| 208 | ) |
| 209 | |
| 210 | def tls_start_client(self, tls_start: tls.TlsData) -> None: |
| 211 | """Establish TLS or DTLS between client and proxy.""" |
| 212 | if tls_start.ssl_conn is not None: |
| 213 | return # a user addon has already provided the pyOpenSSL context. |
| 214 | |
| 215 | assert isinstance(tls_start.conn, connection.Client) |
| 216 | |
| 217 | client: connection.Client = tls_start.conn |
| 218 | server: connection.Server = tls_start.context.server |
| 219 | |
| 220 | entry = self.get_cert(tls_start.context) |
| 221 | |
| 222 | if not client.cipher_list and ctx.options.ciphers_client: |
| 223 | client.cipher_list = ctx.options.ciphers_client.split(":") |
| 224 | # don't assign to client.cipher_list, doesn't need to be stored. |
| 225 | cipher_list = client.cipher_list or _default_ciphers( |
| 226 | net_tls.Version[ctx.options.tls_version_client_min] |
| 227 | ) |
| 228 | |
| 229 | if ctx.options.add_upstream_certs_to_client_chain: # pragma: no cover |
| 230 | # exempted from coverage until https://bugs.python.org/issue18233 is fixed. |
| 231 | extra_chain_certs = server.certificate_list |
| 232 | else: |
| 233 | extra_chain_certs = [] |
| 234 | |
| 235 | ssl_ctx = net_tls.create_client_proxy_context( |
| 236 | method=net_tls.Method.DTLS_SERVER_METHOD |
| 237 | if tls_start.is_dtls |
| 238 | else net_tls.Method.TLS_SERVER_METHOD, |
| 239 | min_version=net_tls.Version[ctx.options.tls_version_client_min], |
| 240 | max_version=net_tls.Version[ctx.options.tls_version_client_max], |
| 241 | cipher_list=tuple(cipher_list), |
| 242 | ecdh_curve=net_tls.get_curve(ctx.options.tls_ecdh_curve_client), |
| 243 | chain_file=entry.chain_file, |
| 244 | request_client_cert=ctx.options.request_client_cert, |
| 245 | alpn_select_callback=alpn_select_callback, |
| 246 | extra_chain_certs=tuple(extra_chain_certs), |
| 247 | dhparams=self.certstore.dhparams, |
| 248 | ) |
| 249 | tls_start.ssl_conn = SSL.Connection(ssl_ctx) |
| 250 | |
| 251 | tls_start.ssl_conn.use_certificate(entry.cert.to_cryptography()) |
| 252 | tls_start.ssl_conn.use_privatekey(entry.privatekey) |
| 253 | |
| 254 | # Force HTTP/1 for secure web proxies, we currently don't support CONNECT over HTTP/2. |
| 255 | # There is a proof-of-concept branch at https://github.com/mhils/mitmproxy/tree/http2-proxy, |
| 256 | # but the complexity outweighs the benefits for now. |
| 257 | if len(tls_start.context.layers) == 2 and isinstance( |
| 258 | tls_start.context.layers[0], modes.HttpProxy |
| 259 | ): |
| 260 | client_alpn: bytes | None = b"http/1.1" |
| 261 | else: |
| 262 | client_alpn = client.alpn |
| 263 | |
| 264 | tls_start.ssl_conn.set_app_data( |
| 265 | AppData( |
| 266 | client_alpn=client_alpn, |
| 267 | server_alpn=server.alpn, |