From 930b059a5e7a7cdbe59c4def0bed0f60c10b6081 Mon Sep 17 00:00:00 2001 From: Brian Neradt Date: Fri, 21 Apr 2023 21:13:03 +0000 Subject: [PATCH] Fix Proxy Protocol outbound The Proxy Protocol outbound functionality broke with the HTTP/2 to origin merge (#9366). I didn't update the Proxy Protocol feature correctly with the merge and the CI's proxy_protocol.test.py was skipped because our CI system didn't have the new go-httpbin in the path. This fixes the outbound Proxy Protocol feature again. --- proxy/http/ConnectingEntry.cc | 12 ++++++++---- proxy/http/ConnectingEntry.h | 4 +++- proxy/http/HttpSM.cc | 29 ++++++----------------------- proxy/http/HttpSM.h | 14 ++++++++++++-- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/proxy/http/ConnectingEntry.cc b/proxy/http/ConnectingEntry.cc index bbbaba5bfdb..ffefb873dbb 100644 --- a/proxy/http/ConnectingEntry.cc +++ b/proxy/http/ConnectingEntry.cc @@ -49,12 +49,16 @@ ConnectingEntry::state_http_server_open(int event, void *data) // The buffer we create will be handed over to the eventually created server session _netvc_read_buffer = new_MIOBuffer(HTTP_SERVER_RESP_HDR_BUFFER_INDEX); _netvc_reader = _netvc_read_buffer->alloc_reader(); - netvc->do_io_write(this, 1, _netvc_reader); ink_release_assert(!connect_sms.empty()); - if (!connect_sms.empty()) { - HttpSM *prime_connect_sm = *(connect_sms.begin()); - netvc->set_inactivity_timeout(prime_connect_sm->get_server_connect_timeout()); + HttpSM *prime_connect_sm = *(connect_sms.begin()); + + int64_t nbytes = 1; + if (is_no_plugin_tunnel && prime_connect_sm->t_state.txn_conf->proxy_protocol_out >= 0) { + nbytes = do_outbound_proxy_protocol(_netvc_reader->mbuf, vc, ua_txn->get_netvc(), + prime_connect_sm->t_state.txn_conf->proxy_protocol_out); } + netvc->do_io_write(this, nbytes, _netvc_reader); + netvc->set_inactivity_timeout(prime_connect_sm->get_server_connect_timeout()); ink_release_assert(_pending_action == nullptr); return 0; } diff --git a/proxy/http/ConnectingEntry.h b/proxy/http/ConnectingEntry.h index f612fa4258d..c63a5a33a99 100644 --- a/proxy/http/ConnectingEntry.h +++ b/proxy/http/ConnectingEntry.h @@ -46,7 +46,9 @@ class ConnectingEntry : public Continuation IpEndpoint ipaddr; std::string hostname; std::set connect_sms; - NetVConnection *netvc = nullptr; + ProxyTransaction *ua_txn = nullptr; + NetVConnection *netvc = nullptr; + bool is_no_plugin_tunnel = false; private: MIOBuffer *_netvc_read_buffer = nullptr; diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc index 78d3fdd35a8..4a19591f87b 100644 --- a/proxy/http/HttpSM.cc +++ b/proxy/http/HttpSM.cc @@ -110,12 +110,8 @@ std::atomic next_sm_id(0); /// Buffer for some error logs. thread_local std::string error_bw_buffer; -/** - Outbound PROXY Protocol +} // namespace - Write PROXY Protocol to the first block of given MIOBuffer - FIXME: make @vc_in const - */ int64_t do_outbound_proxy_protocol(MIOBuffer *miob, NetVConnection *vc_out, NetVConnection *vc_in, int conf) { @@ -148,8 +144,6 @@ do_outbound_proxy_protocol(MIOBuffer *miob, NetVConnection *vc_out, NetVConnecti return len; } -} // namespace - ClassAllocator httpSMAllocator("httpSMAllocator"); HttpVCTable::HttpVCTable(HttpSM *mysm) @@ -1931,7 +1925,6 @@ HttpSM::state_http_server_open(int event, void *data) case CONNECT_EVENT_TXN: SMDebug("http", "Connection handshake complete via CONNECT_EVENT_TXN"); if (this->create_server_txn(static_cast(data))) { - write_outbound_proxy_protocol(); handle_http_server_open(); } else { // Failed to create transaction. Maybe too many active transactions already // Try again (probably need a bounding counter here) @@ -1944,7 +1937,6 @@ HttpSM::state_http_server_open(int event, void *data) // Update the time out to the regular connection timeout. SMDebug("http_ss", "Connection handshake complete"); this->create_server_txn(this->create_server_session(_netvc, _netvc_read_buffer, _netvc_reader)); - write_outbound_proxy_protocol(); t_state.current.server->clear_connect_fail(); handle_http_server_open(); return 0; @@ -5681,11 +5673,13 @@ HttpSM::do_http_server_open(bool raw, bool only_direct) SMDebug("http_ss", "Queue multiplexed request"); new_entry = new ConnectingEntry(); new_entry->mutex = this->mutex; + new_entry->ua_txn = ua_txn; new_entry->handler = (ContinuationHandler)&ConnectingEntry::state_http_server_open; new_entry->ipaddr.assign(&t_state.current.server->dst_addr.sa); - new_entry->hostname = t_state.current.server->name; - new_entry->sni = this->get_outbound_sni(); - new_entry->cert_name = this->get_outbound_cert(); + new_entry->hostname = t_state.current.server->name; + new_entry->sni = this->get_outbound_sni(); + new_entry->cert_name = this->get_outbound_cert(); + new_entry->is_no_plugin_tunnel = plugin_tunnel_type == HTTP_NO_PLUGIN_TUNNEL; this->t_state.set_connect_fail(EIO); new_entry->connect_sms.insert(this); ethread->connecting_pool->m_ip_pool.insert(std::make_pair(new_entry->ipaddr, new_entry)); @@ -6549,17 +6543,6 @@ HttpSM::write_header_into_buffer(HTTPHdr *h, MIOBuffer *b) return dumpoffset; } -void -HttpSM::write_outbound_proxy_protocol() -{ - int64_t nbytes = 1; - if (t_state.txn_conf->proxy_protocol_out >= 0) { - nbytes = do_outbound_proxy_protocol(server_txn->get_remote_reader()->mbuf, server_txn->get_netvc(), ua_txn->get_netvc(), - t_state.txn_conf->proxy_protocol_out); - } - server_entry->write_vio = server_txn->do_io_write(this, nbytes, server_txn->get_remote_reader()); -} - void HttpSM::attach_server_session() { diff --git a/proxy/http/HttpSM.h b/proxy/http/HttpSM.h index 830b58bd5bc..5c7da145694 100644 --- a/proxy/http/HttpSM.h +++ b/proxy/http/HttpSM.h @@ -70,6 +70,18 @@ class PreWarmSM; class HttpSM; using HttpSMHandler = int (HttpSM::*)(int, void *); +/** Write Proxy Protocol to the first block of given MIOBuffer. + * + * @param[in] miob The MIOBuffer to write the Proxy Protocol to. + * @param[in] vc_out The outbound (server-side) VC. + * @param[in] vc_in The inbound (client-side) VC. + * @param[in] conf The configured Proxy Protocol version to write. + * + * @return The number of bytes written on the socket to write the Proxy + * Protocol. + */ +int64_t do_outbound_proxy_protocol(MIOBuffer *miob, NetVConnection *vc_out, NetVConnection *vc_in, int conf); + enum HttpVC_t { HTTP_UNKNOWN = 0, HTTP_UA_VC, @@ -235,8 +247,6 @@ class HttpSM : public Continuation, public PluginUserArgs ProxyTransaction *get_ua_txn(); ProxyTransaction *get_server_txn(); - // Write out the proxy_protocol information on a new outbound connection - void write_outbound_proxy_protocol(); // Called by transact. Updates are fire and forget // so there are no callbacks and are safe to do