Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] V2.1.1: support HAProxy PROXY protocol V1 on MySQL frontends #2971

Closed

Commits on Feb 28, 2021

  1. [RFC] V2.1.1: support HAProxy PROXY protocol V1 on MySQL frontends

    This adds basic support for the HAProxy PROXY protocol V1 on MySQL frontend
    client connections.  This allows the true client IP to be seen in the output
    of `SHOW FULL PROCESSLIST` in ProxySQL's admin frontend when the ProxySQL
    servers sit behind a load balancer such as HAProxy or AWS classic ELBs with
    the PROXY protocol feature enabled.
    
    I believe this should resolve sysown#2497 (Support for proxy_protocol for proxysql behind aws load balancer).
    
    The patch adds a Proxy_Protocol class which handles:
    
    - parsing of PROXY protocol headers (only the V1 header supported for now)
    - matching client IPs against a list of configured network CIDRs
    
    A new option, `proxy_protocol_frontend_nets` (list of network CIDRs), is
    introduced to allow the PROXY protocol feature to be selectively turned on for
    specific subnets where e.g. load balancers are running.  This is similar to how
    the PROXY protocol is implemented in MariaDB.
    
    This variable can be set either in the config file or via the ProxySQL Admin
    interface.  Configuration file example:
    
        mysql_variables=
        {
            ...
            proxy_protocol_frontend_nets="10.42.0.0/28 127.10.0.0/16"
            ...
        }
    
    ProxySQL Admin interface example:
    
        UPDATE global_variables
        SET variable_value="192.168.42.0/24"
        WHERE variable_name="mysql-proxy_protocol_frontend_nets";
        LOAD MYSQL VARIABLES TO RUNTIME;
    
    The network CIDRs are stored as a thread-local variable in the MySQL_Thread
    class.  It's only updated by MySQL_Thread::refresh_variables().
    
    A new MySQL Data Stream state (DSS), `STATE_PROXY_PROTOCOL`, is introduced to
    handle the initial parsing of the PROXY protocol header.  Once this has
    completed, the state is reset back to `STATE_SERVER_HANDSHAKE`.
    
    The patch hooks into the MySQL_Thread's main loop where `accept()` is called
    to handle incoming connections.  Next, the actual parsing of the PROXY protocol
    header is invoked from the `MySQL_Data_Stream::read_pkts()` method, which is
    also called from MySQL_Thread's main loop (where incoming data is handled).
    
    I've only tested this with a HAProxy configuration block like:
    
        listen proxysql-with-proxy
            bind *:6030
            option tcp-check
            mode tcp
            timeout server 6h
            timeout client 6h
            balance roundrobin
            server proxysql-backend-1 127.0.0.1:6033 check send-proxy
        listen proxysql-without-proxy
            bind *:6031
            option tcp-check
            mode tcp
            timeout server 6h
            timeout client 6h
            balance roundrobin
            server proxysql-backend-2 192.168.1.123:6033 check
    noahwilliamsson committed Feb 28, 2021
    Configuration menu
    Copy the full SHA
    c3e187c View commit details
    Browse the repository at this point in the history