Search code examples
haproxysnowflake-cloud-data-platform

HAProxy settings for connecting to Snowflake Data


I've been trying to connect to Snowflake using the ODBC driver via a proxy but have so far been unable to. I'm using HAProxy to do this.

This is from odbc.ini, where I've configured my DSN:

[ODBC Data Sources]
SnowflakeDSII = Snowflake

[SnowflakeDSII]
Server = <account>.<region>.snowflakecomputing.com
Port = 443
UID = <username>
PWD = <password>
Schema =
Warehouse =
Driver = /opt/snowflake/snowflakeodbc/lib/universal/libSnowflake.dylib
Description = Snowflake DSII
Locale = en-US
Tracing = 0
proxy = http://127.0.0.1:8000

This is my HAProxy config:

global
  log stdout format raw local0 info

defaults
  log global
  # timeouts
  timeout connect 3600s
  timeout client 3600s
  timeout server 3600s
  maxconn 4000

frontend snowflake_proxy
  mode tcp
  option tcplog

  bind 0.0.0.0:8000
  default_backend snowflake

backend snowflake
  mode tcp
  option tcp-check
  server server0 <account>.<region>.snowflakecomputing.com:443 check

On running iodbctest, I'm seeing this error:

OOB curl_easy_perform() failed: Failure when receiving data from the peer
1: SQLDriverConnect = [Snowflake][Snowflake] (4)
      REST request for URL https://<account>.<region>.snowflakecomputing.com:443/session/v1/login-request?requestId=0fe536ed-4d6c-4858-b468-52a6757248a7&request_guid=5477913c-989a-4da3-bbbc-b62a68391749 failed: CURLerror (curl_easy_perform() failed) - code=56 msg='Failure when receiving data from the peer' osCode=36 osMsg='Operation now in progress'.
     (4) SQLSTATE=HY000
1: ODBC_Connect = [Snowflake][Snowflake] (4)
      REST request for URL https://<account>.<region>.snowflakecomputing.com:443/session/v1/login-request?requestId=0fe536ed-4d6c-4858-b468-52a6757248a7&request_guid=5477913c-989a-4da3-bbbc-b62a68391749 failed: CURLerror (curl_easy_perform() failed) - code=56 msg='Failure when receiving data from the peer' osCode=36 osMsg='Operation now in progress'.
     (4) SQLSTATE=HY000

I've also tried configuring HAProxy to act as just a simple HTTP proxy. This is my HAProxy configuration for that:

global
  log stdout format raw local0 info

defaults
  log global
  # timeouts
  timeout connect 3600s
  timeout client 3600s
  timeout server 3600s
  maxconn 4000

frontend snowflake_proxy
  mode http
  option httplog

  bind 0.0.0.0:8000
  default_backend snowflake

backend snowflake
  mode http
  option http-server-close
  option http_proxy

With the above HAProxy config, I'm seeing this error:

OOB curl_easy_perform() failed: Failure when receiving data from the peer
1: SQLDriverConnect = [Snowflake][Snowflake] (4)
      REST request for URL https://<account>.<region>.snowflakecomputing.com:443/session/v1/login-request?requestId=01ccf8d9-895b-47d1-9102-41f7524ec436&request_guid=773e75b3-9137-4862-a5e1-3bf49e076a1d failed: CURLerror (curl_easy_perform() failed) - code=56 msg='Failure when receiving data from the peer'.
     (4) SQLSTATE=HY000
1: ODBC_Connect = [Snowflake][Snowflake] (4)
      REST request for URL https://<account>.<region>.snowflakecomputing.com:443/session/v1/login-request?requestId=01ccf8d9-895b-47d1-9102-41f7524ec436&request_guid=773e75b3-9137-4862-a5e1-3bf49e076a1d failed: CURLerror (curl_easy_perform() failed) - code=56 msg='Failure when receiving data from the peer'.
     (4) SQLSTATE=HY000

From HAProxy's logs:

127.0.0.1:64824 [31/Jan/2020:13:28:19.888] snowflake_proxy snowflake/<NOSRV> -1/-1/-1/-1/0 400 211 - - PR-- 1/1/0/0/3 0/0 "CONNECT <account>.<region>.snowflakecomputing.com:443 HTTP/1.1"
127.0.0.1:64825 [31/Jan/2020:13:28:21.890] snowflake_proxy snowflake/<NOSRV> -1/-1/-1/-1/0 400 211 - - PR-- 1/1/0/0/3 0/0 "CONNECT <account>.<region>.snowflakecomputing.com:443 HTTP/1.1"
127.0.0.1:64826 [31/Jan/2020:13:28:25.894] snowflake_proxy snowflake/<NOSRV> -1/-1/-1/-1/0 400 211 - - PR-- 1/1/0/0/3 0/0 "CONNECT <account>.<region>.snowflakecomputing.com:443 HTTP/1.1"
127.0.0.1:64829 [31/Jan/2020:13:28:33.898] snowflake_proxy snowflake/<NOSRV> -1/-1/-1/-1/0 400 211 - - PR-- 1/1/0/0/3 0/0 "CONNECT <account>.<region>.snowflakecomputing.com:443 HTTP/1.1"
127.0.0.1:64830 [31/Jan/2020:13:28:33.903] snowflake_proxy snowflake/<NOSRV> -1/-1/-1/-1/0 400 211 - - PR-- 1/1/0/0/3 0/0 "CONNECT sfctest.client-telemetry.snowflakecomputing.com:443 HTTP/1.1"

Has anyone had any luck doing something similar? Would you be able to share relevant parts of your HAProxy config please?


Solution

  • Because of the requirement for SSL pass-through to be configured on the proxy, HAProxy might be difficult if not impossible to configure and use as a forwarding proxy for Snowflake's ODBC driver.

    The reason is stated in this SO answer:

    I captured packets , using proxy to visit a https website , curl will start a HTTP CONNECT method to establish a tunnel. The tunnel should be between curl client and proxy, but TCP proxy will delivery all messages to web server, so web server will reset the connection.

    A forward proxy should not just delivery messages between client and web server.It should understand the HTTP CONNECT method

    HAProxy when doing SSL pass-through behaves as a TCP proxy, and so does not parse the underlying messages. However it needs to first set up the tunnel before doing so and that requires responding to the HTTP CONNECT method.