pingcap / tidb

TiDB is an open-source, cloud-native, distributed, MySQL-Compatible database for elastic scale and real-time analytics. Try AI-powered Chat2Query free at : https://www.pingcap.com/tidb-serverless/
https://pingcap.com
Apache License 2.0
36.46k stars 5.74k forks source link

Add PROXY protocol support #3757

Closed blacktear23 closed 6 years ago

blacktear23 commented 6 years ago

Add PROXY protocol V1 and V2 support.

usage: tidb-server --proxy-protocol-networks "*" --proxy-protocol-header-timeout 5

Add --proxy-protocol-networks command parameter for PROXY protocol enable or disable. If you want to limit HAProxy server IP range, you can set --proxy-protocol-networks parameter to a CIDRs and split by ",". For example:

tidb-server --proxy-protocol-networks "192.168.1.0/24,192.168.2.0/24"

For more information about PROXY protocol please refer https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt

blacktear23 commented 6 years ago

@coocood After I read go-proxyproto I found this package's performance is not good as current. If you want, I think I can create a go package for proxyprotocol and the interface can be like this package.

coocood commented 6 years ago

@blacktear23 That would be great! And I would like to know the performance difference, can you do some benchmark and provide the result?

coocood commented 6 years ago

@blacktear23 Is the performance advantage is caused by not using a *bufio.Reader? But we prefer to use *bufio.Reader because reading client request is not the bottleneck and it makes the code much simpler.

blacktear23 commented 6 years ago

@coocood the performance problem for this package is check header bytes one by one and this is my first implements method that nagut not allowed. And his design is not fit for proxy protocol v2. And proxy protocol v2 is faster than v1 because we don't need to parse IPv4 or IPv6 address from string. As my suggestion, customer should use v2 if supported.

coocood commented 6 years ago

@blacktear23 I think checking byte one by one is needed if we want to support both proxy and non-proxy access.

blacktear23 commented 6 years ago

@coocood as proxy protocol spec said we must not guess the protocol is proxy protocol or not:

The receiver MUST be configured to only receive the protocol described in this
specification and MUST not try to guess whether the protocol header is present
or not. This means that the protocol explicitly prevents port sharing between
public and private access. Otherwise it would open a major security breach by
allowing untrusted parties to spoof their connection addresses. The receiver
SHOULD ensure proper access filtering so that only trusted proxies are allowed
to use this protocol.
coocood commented 6 years ago

@blacktear23 I got it, so we need to open another port for the proxy access.

coocood commented 6 years ago

@blacktear23 Any update?

blacktear23 commented 6 years ago

I have already move Proxy Protocol related code to my repository: https://github.com/blacktear23/go-proxyprotocol . And for another question: open Proxy Protocol port to serve Proxy Protocol connection, I have a question: shall we need this?. I think we can start two tidb-server process with different port setting and proxy protocol setting. In addition, I don't know when start two Server instance with different Listener will be OK.

coocood commented 6 years ago

@blacktear23 OK, start another TiDB server for non-proxy access is fine.

coocood commented 6 years ago

@blacktear23 We add vendor with glide, so please add the package entry in glide.yaml and run make update.

blacktear23 commented 6 years ago

When I run make update I got an error message:

[ERROR] Update failed for bitbucket.org/ww/goautoneg: bitbucket.org/ww/goautoneg contains uncommitted changes. Skipping update

Then make exit with error. And I found a lot of deleted file in git status. Is there has some problem on my glide.yaml ?

coocood commented 6 years ago

@blacktear23

The make update is easy to fail. Never mind, I'll send another PR to add the vendor.

coocood commented 6 years ago

make update just deletes the test file and updates glide.lock. I just realized we can make update after this PR is merged. No need to add the vendor first.

coocood commented 6 years ago

LGTM

@blacktear23 Thank you for your great work!

breezewish commented 6 years ago

LGTM

breezewish commented 6 years ago

/ok-to-test

breezewish commented 6 years ago

/run-all-tests

SteamedFish commented 5 years ago
  1. most proxy protocol implementations such as MariaDB, Percona server, apache(via mod_remoteip), allow user to specify a list of cider blocks(proxy-protocol-networks for MariaDB and Percona server,RemoteIPProxyProtocolExceptions for apache), IP in the list MUST use proxy protocol and IP not in the list MUST NOT use proxy protocol(but they can still connect without proxy protocol). some implementations, like nginx and TiDB, forces all IP addresses to use proxy protocol when enables proxy protocol options.
  2. the spec says that we "MUST not try to guess whether the protocol header is present or not", to prevent security issues, but there's no guessing when we provide a list and config IPs in the list to MUST use and IPs not in the list to MUST NOT use(but still able to connect). There's no security issues doing this way and it actually meet the spec requirement.
  3. allowing certain IP blocks to connect directly without haproxy will make certain tasks much easier to configure, such as:
    • monitoring individual TiDB nodes
    • make a certain TiDB node to do complex OLAP tasks without influence other OLTP nodes.
    • control individual TiDB nodes via script tasks in the local machine(such as a crontab script at each TiDB node

I think make IPs not in AllowedIPs to connect directly without proxy protocol is:

  1. very easy to implement. only need to modify two lines of code
  2. has some benefits
  3. meets the spec

So I think its good to do this way.

ciscoxll commented 5 years ago

@tiancaiamao PTAL.

coocood commented 5 years ago

@SteamedFish Good suggestion! Would you like to send a PR for this feature?

SteamedFish commented 5 years ago

@coocood PR is here https://github.com/blacktear23/go-proxyprotocol/pull/1