| 113 | ) |
| 114 | |
| 115 | def _next_layer( |
| 116 | self, context: Context, data_client: bytes, data_server: bytes |
| 117 | ) -> Layer | None: |
| 118 | assert context.layers |
| 119 | |
| 120 | def s(*layers): |
| 121 | return stack_match(context, layers) |
| 122 | |
| 123 | tcp_based = context.client.transport_protocol == "tcp" |
| 124 | udp_based = context.client.transport_protocol == "udp" |
| 125 | |
| 126 | # 1) check for --ignore/--allow |
| 127 | if self._ignore_connection(context, data_client, data_server): |
| 128 | return ( |
| 129 | layers.TCPLayer(context, ignore=not ctx.options.show_ignored_hosts) |
| 130 | if tcp_based |
| 131 | else layers.UDPLayer(context, ignore=not ctx.options.show_ignored_hosts) |
| 132 | ) |
| 133 | |
| 134 | # 2) Handle proxy modes with well-defined next protocol |
| 135 | # 2a) Reverse proxy: derive from spec |
| 136 | if s(modes.ReverseProxy): |
| 137 | return self._setup_reverse_proxy(context, data_client) |
| 138 | # 2b) Explicit HTTP proxies |
| 139 | if s((modes.HttpProxy, modes.HttpUpstreamProxy)): |
| 140 | return self._setup_explicit_http_proxy(context, data_client) |
| 141 | |
| 142 | # 3) Handle security protocols |
| 143 | # 3a) TLS/DTLS |
| 144 | is_tls_or_dtls = ( |
| 145 | tcp_based |
| 146 | and starts_like_tls_record(data_client) |
| 147 | or udp_based |
| 148 | and starts_like_dtls_record(data_client) |
| 149 | ) |
| 150 | if is_tls_or_dtls: |
| 151 | server_tls = ServerTLSLayer(context) |
| 152 | server_tls.child_layer = ClientTLSLayer(context) |
| 153 | return server_tls |
| 154 | # 3b) QUIC |
| 155 | if udp_based and _starts_like_quic(data_client, context.server.address): |
| 156 | server_quic = ServerQuicLayer(context) |
| 157 | server_quic.child_layer = ClientQuicLayer(context) |
| 158 | return server_quic |
| 159 | |
| 160 | # 4) Check for --tcp/--udp |
| 161 | if tcp_based and self._is_destination_in_hosts(context, self.tcp_hosts): |
| 162 | return layers.TCPLayer(context) |
| 163 | if udp_based and self._is_destination_in_hosts(context, self.udp_hosts): |
| 164 | return layers.UDPLayer(context) |
| 165 | |
| 166 | # 5) Handle application protocol |
| 167 | # 5a) Do we have a known ALPN negotiation? |
| 168 | if context.client.alpn: |
| 169 | if context.client.alpn in HTTP_ALPNS: |
| 170 | return layers.HttpLayer(context, HTTPMode.transparent) |
| 171 | elif context.client.tls_version == "QUICv1": |
| 172 | # TODO: Once we support more QUIC-based protocols, relax force_raw here. |