dlundquist / sniproxy

Proxies incoming HTTP and TLS connections based on the hostname contained in the initial request of the TCP session.
BSD 2-Clause "Simplified" License
2.53k stars 397 forks source link

unable to access the website when using sniproxy #237

Open shoaebkiyani opened 7 years ago

shoaebkiyani commented 7 years ago

Hi, i am having issues in accessing my (Apache) testing website mydomain.com over sniproxy. I am not able to access it when i run sniproxy otherwise it works fine. Using curl mydomain.com gives me error "curl: (7) Failed to connect to mydomain.com port 80: Connection refused". And with curl https://mydomain.com it gives me error "curl: (35) gnutls_handsake() failed: The TLS connection was non-properly terminated".

Here is my configuration file: user daemon

pidfile /tmp/sniproxy.pid

error_log { syslog daemon priority notice } listener 1.2.3.4:80 { protocol http table TableName

# Specify a server to use if the initial client request doesn't contain
# a hostname
fallback 192.0.2.5:80

} listener 1.2.3.4:443 { protocol tls table TableName

# Specify a server to use if the initial client request doesn't contain
# a hostname
fallback 192.0.2.5:443

}

table TableName {

Match exact request hostnames

example.com 192.0.2.10:4343

mydomain name

mydomain.com 1.2.3.4:8080 mydomain.com 1.2.3.4:4443

# If port is not specified the listener port will be used
example.net [2001:DB8::1:10]
# Or use regular expression to match
.*\\.com    [2001:DB8::1:11]:443
# Combining regular expression and wildcard will resolve the hostname
# client requested and proxy to it
.*\\.edu    *:443

}

dlundquist commented 7 years ago

This sounds like two seperate issues:

  1. You are unable to connect to port 80 on mydomain.com, this may be a firewall rule or mismatch between the IP address in the listener stanza, the DNS record and the IP configured on the host. SNIproxy must first accept the incoming connection before parsing the client request, you should see some access or error log item for each established connection.
  2. You are proxying HTTPS connections to HTTP. Since tables use only the first found, your second entry for mydomain.com 1.2.3.4:4443 is never matched. I would suggest either using a separate table for HTTP and HTTPS, you using the incoming port feature: if you don't specify a port in the table entry the destination port of the incomming connection is used, but this will only work if the backend server is hosted on another server. Otherwise you will recursively proxy to sniproxy until the maximum number of connections is reached: this is a good stress test of sniproxy but otherwise not very useful.
shoaebkiyani commented 7 years ago

Hi, Thanks for the answers. Now I made separate daemons for each of the protocol and tested them separately. Below are both daemons i.e. for HTTP & HTTPS. // HTTP Daemon user daemon pidfile /tmp/sniproxy.pid error_log { syslog daemon priority notice } listener 1.2.3.4:80{ proto http table http_hosts } table http_hosts{ .*.mydomain.com *

mydomain.com *

mydomain.com 1.2.3.4 *

mydomain.com 1.2.3.4:8080

} // HTTPS Daemon user daemon pidfile /tmp/sniproxy.pid error_log { syslog daemon priority notice } listener 1.2.3.4:443{ proto tls table https_hosts } table https_hosts{

.*.mydomain.com *

mydomain.com *

mydomain.com 1.2.3.4 *

mydomain.com 1.2.3.4:4443

} I checked all of them one by one and in some I got “curl: (35) gnutls_handsake() failed: The TLS connection was non-properly terminated" and in some it just keep on searching (no response). The following result is from the hostname that is uncommented. From curl mydomain.com I get “Backend not available” message and from curl https://mydomain.com I get “Handshake failed” message. I used openssl command as well & received the following message while connecting https://mydomain.com. CONNECTED(00000003) 140047067981464:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:769: no peer certificate available No client certificate CA names sent SSL handshake has read 7 bytes and written 324 bytes New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1 Cipher : 0000 Session-ID: Session-ID-ctx: Master-Key: Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None Start Time: 1491911808 Timeout : 300 (sec) Verify return code: 0 (ok) I also checked after making some changes in the /etc/hosts file by mentioning the port number along with the host name but still issue didn't resolved. I tried from every perspective that I could think of but don’t know what I am missing. I shall appreciate your further answers on this issue.

Thanks...!!

oakaigh commented 6 years ago

@dlundquist @shabiKi Maybe it's the problem of Perl-compatible Regular Expression (which needs clarification). Sort of like, this works:

# Section III Github
 www\.github\.com       13.229.188.59:443
 assets-cdn\.github\.com    151.101.76.133:443
 gist\.github\.com      13.229.188.59:443
 github\.com            13.229.188.59:443

But why this does not:

# Section III Github
 github\.com            13.229.188.59:443
 www\.github\.com       13.229.188.59:443
 assets-cdn\.github\.com    151.101.76.133:443
 gist\.github\.com      13.229.188.59:443

All domains of *.github.com are resolved to 13.229.188.59?

dlundquist commented 6 years ago

Table entries are evaluated in order, your regular expression are not anchored, so github\.com matches all the others. To match an exact website, you should anchor each end and double escape the dots. e.g. ^www\\.example\\.com$. The double backslashes are to escape the backslash from the tokenizer.

I think this is a bit cumbersome myself, but I'm hesitant to introduce a backwards incompatible change. In most cases, users do not need the full expressiveness of regular expressions and simply need to wildcard a subdomain. I've been considering a different approach where the hostname is split into labels (the parts separated by dots), and then tree of matching labels is build starting with the TLD. This could improve performance when preforming table lookups on tables with a large number of entries and would have a much simpler syntax.

oakaigh commented 6 years ago

@dlundquist actually a normal regular expression is much better somehow

*.github.com
github.*

while Perl compatible regex is still preserved in the future for advanced users.

oakaigh commented 6 years ago

292

dlundquist commented 6 years ago

@PantherJohn I don't understand what you are saying? *.github.com is not a formal regular expression since it begins with a Kleene star operator, I would refer to it as a wildcard expression. Your second example with the wildcard at the the end of the string is interesting, I wasn't planning on supporting wildcards at the end of strings because in Domain Names this crosses administrative trust boundaries (anyone can setup github.THEIR.MALICIOUS.DOMAIN) and for performance reasons: I was trying to solve the linear search of table entries.