docker-flow / docker-flow-proxy

Docker Flow Proxy
https://docker-flow.github.io/docker-flow-proxy/
MIT License
317 stars 189 forks source link

reqMode=tcp doesn't seem to forward correctly in haproxy #70

Closed NikolajOugaard closed 5 years ago

NikolajOugaard commented 5 years ago

I am trying to launch a MSSQL database in a container using DFP as proxy. MSSQL database uses port 1433 for connectivity. If I create a service on my local machine like this:

docker service create --name mssql -p 1433:1433 --env="SA_PASSWORD=Qwerty!234" --env="ACCEPT_EULA=true" microsoft/mssql-server-linux:latest

I can now connect to the MSSQL database:

sqlcmd -S localhost,1433 -U sa

with password Qwerty!234

When I try to use DFP to achieve the same thing I run into problems. I create the DFP setup:

docker network create --driver overlay proxy docker service create --name swarm-listener --network proxy --mount "type=bind,source=/var/run/docker.sock,target=/var/run/docker.sock" -e DF_NOTIFY_CREATE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/reconfigure -e DF_NOTIFY_REMOVE_SERVICE_URL=http://proxy:8080/v1/docker-flow-proxy/remove --constraint "node.role==manager" vfarcic/docker-flow-swarm-listener docker service create --name proxy -p 80:80 -p 443:443 --network proxy -e LISTENER_ADDRESS=swarm-listener -e DEBUG=true vfarcic/docker-flow-proxy

I then add the 1433 port to the proxy configuration:

docker service update --publish-add 1433:1433 proxy

And finally I create the MSSQL database:

docker service create --name mssql --network proxy --label com.df.notify=true --label com.df.distribute=true --label com.df.serviceDomain=mssql.domain.local --label com.df.port=1433 --label com.df.srcPort=1433 --label com.df.reqMode=tcp --env="SA_PASSWORD=Qwerty!234" --env="ACCEPT_EULA=true" microsoft/mssql-server-linux

Now I cannot connect to the database. I get logon timeouts:

sqlcmd -S mssql.domain.local,1433 -U sa

mssql.domain.local I have setup in my local Windows hosts file to point to 127.0.0.1

First looking at the haproxy configuration ( /cfg/haproxy.conf ) by sh'ing into the proxy container I see:

frontend tcpFE_1433
    bind *:1433
    mode tcp
    option tcplog
    log global
    acl domain_mssql1433_0 hdr_beg(host) -i mssql.domain.local
    use_backend mssql-be1433_0 if domain_mssql1433_0

But looking at the debug logs from the DFP proxy container I see:

2018/09/19 07:28:40 HAPRoxy: 10.255.0.2:34136 [19/Sep/2018:07:28:40.791] tcpFE_1433 tcpFE_1433/<NOSRV> -1/-1/0 0 SC 1/1/0/0/0 0/0 Indicating that the request doesn't get forwarded to the backend haproxy configuration.

NikolajOugaard commented 5 years ago

The haproxy frontend config tcpFE_1433 has mssql.domain.local and not mssql.domain.dk as written above. ( This is now irrelevant since I've edited the issue to reflect the correct host value )

thomasjpfan commented 5 years ago

I am unable to reproduce the incorrect host issue. Can you post the DFSL logs?

NikolajOugaard commented 5 years ago

I am sorry if I wasn't clear in my own comment regarding the mssql.domain.local host. My point was that there is no error in the tcpFE_1433 haproxy frontend. It was a copy / paste error on my behalf. The tcpFE_1433 haproxy frontend configuration contains the correct mssql.domain.local host ( I've edited the original issue to reflect the correct host )

However here are the DFSL logs:

swarm-listener.1.9b61nuakeeye@linuxkit-00155d183529    | 2018/09/20 08:24:29 Starting Docker Flow: Swarm Listener
swarm-listener.1.9b61nuakeeye@linuxkit-00155d183529    | 2018/09/20 08:24:29 Sending notifications for running services and nodes
swarm-listener.1.9b61nuakeeye@linuxkit-00155d183529    | 2018/09/20 08:26:19 Sending service created notification to http://proxy:8080/v1/docker-flow-proxy/reconfigure?distribute=true&port=1433&replicas=1&reqMode=tcp&serviceDomain=mssql.domain.local&serviceName=mssql&srcPort=1433
thomasjpfan commented 5 years ago

Can you post the whole haproxy config? I want to see if there are any conflicts.

NikolajOugaard commented 5 years ago

Here is the complete haproxy.cfg

global
    pidfile /var/run/haproxy.pid
    tune.ssl.default-dh-param 2048
    log 127.0.0.1:1514 local0

    # disable sslv3, prefer modern ciphers
    ssl-default-bind-options no-sslv3
    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS

    ssl-default-server-options no-sslv3
    ssl-default-server-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS

resolvers docker
    nameserver dns 127.0.0.11:53

defaults
    mode    http
    balance roundrobin

    option  http-keep-alive
    option  forwardfor
    option  redispatch

    errorfile 400 /errorfiles/400.http
    errorfile 403 /errorfiles/403.http
    errorfile 405 /errorfiles/405.http
    errorfile 408 /errorfiles/408.http
    errorfile 429 /errorfiles/429.http
    errorfile 500 /errorfiles/500.http
    errorfile 502 /errorfiles/502.http
    errorfile 503 /errorfiles/503.http
    errorfile 504 /errorfiles/504.http

    maxconn 5000
    timeout connect 5s
    timeout client  20s
    timeout server  20s
    timeout queue   30s
    timeout tunnel  3600s
    timeout http-request 5s
    timeout http-keep-alive 15s

frontend services
    bind *:80
    bind *:443
    mode http

    option httplog
    log global

frontend tcpFE_1433
    bind *:1433
    mode tcp
    option tcplog
    log global
    acl domain_mssql1433_0 hdr_beg(host) -i mssql.domain.local
    use_backend mssql-be1433_0 if domain_mssql1433_0

backend mssql-be1433_0
    mode tcp
    log global
    server mssql mssql:1433
NikolajOugaard commented 5 years ago

Having spoken to different people that know a lot more about the tcp protocol than I do, my impression is that this might not be possible. They claim that the tcp protocol do not have the information about the original host since only the IP is transfered. There isn't a request header ( like there is in http ) that contain the host name. So where should the tcp transport protocol get the needed host information from?

thomasjpfan commented 5 years ago

That is correct. TCP does not include a HTTP header, thus hdr_beg should not work on a TCP request.

NikolajOugaard commented 5 years ago

This doesn't seem possible so DFP really cannot forward requests on tcp the same way it does on http. I'll close this issue.