-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
Describe the bug
The Connection header is a hop-by-hop header, and proxy servers should not forward it. However, Pingora appears to forward the Connection header from the client directly to the upstream server.
For example, if a client sends Connection: close, Pingora will forward Connection: close to the upstream server. In some environments, this may cause the connection between Pingora and the upstream to be closed, which can lead to performance issues.
I also tested the hop-by-hop headers listed in RFC 2616, and all of them were forwarded to the upstream server without modification.
Pingora info
Pingora version: 0.6.0
Rust version: 1.90.0
Operating system version: Ubuntu 22.04
Steps to reproduce
This is the source code of the load balancer. It simply proxies the request to localhost:3000.
use async_trait::async_trait;
use pingora::prelude::*;
struct LB;
#[async_trait]
impl ProxyHttp for LB {
type CTX = ();
fn new_ctx(&self) -> Self::CTX {}
async fn upstream_peer(&self, _session: &mut Session, _ctx: &mut ()) -> Result<Box<HttpPeer>> {
let peer = HttpPeer::new("127.0.0.1:3000", false, "".to_string());
Ok(Box::new(peer))
}
}
fn main() -> pingora::Result<()> {
env_logger::init();
let mut my_server = Server::new(None)?;
my_server.bootstrap();
let mut lb = http_proxy_service(&my_server.configuration, LB);
lb.add_tcp("[::]:8000");
my_server.add_service(lb);
my_server.run_forever();
}Start this server.
In another shell, start a TCP server by using socat. Note that this server never returns a response.
socat TCP-LISTEN:3000,reuseaddr,fork -Send an HTTP request like the following from another shell. Then, socat will print the HTTP request sent from Pingora.
nc -C localhost 8000 <<'EOF'
GET / HTTP/1.1
Host: example.com
Connection: close
EOFExpected results
The upstream server should not receive Connection: close header given by the client.
GET / HTTP/1.1
Host: example.com
Observed results
socat outputs the following text, which is a HTTP request sent from Pingora to the upstream server.
GET / HTTP/1.1
Host: example.com
Connection: close
Connection: close is included in the request.