Skip to content

Commit a6de4f6

Browse files
committed
feat: provide a bunch more ways to specify proxies
and behaviour when behind proxies
1 parent 2d3bc77 commit a6de4f6

File tree

3 files changed

+52
-8
lines changed

3 files changed

+52
-8
lines changed

shard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: connect-proxy
2-
version: 1.2.2
2+
version: 1.3.0
33
license: MIT
44
crystal: ">= 0.36.1"
55

spec/connect_spec.cr

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,27 @@ describe ConnectProxy do
1818
response = client.exec("GET", "/")
1919
response.success?.should eq(true)
2020
end
21+
22+
it "connect to a website with CRL checks disabled" do
23+
ConnectProxy.verify_tls = true
24+
ConnectProxy.disable_crl_checks = true
25+
26+
host = URI.parse("https://github.com/")
27+
client = ConnectProxy::HTTPClient.new(host, ignore_env: true)
28+
proxy = ConnectProxy.new("51.38.71.101", 8080)
29+
client.set_proxy(proxy)
30+
response = client.exec("GET", "/")
31+
response.success?.should eq(true)
32+
end
33+
34+
it "connect to a website with TLS disabled" do
35+
ConnectProxy.verify_tls = false
36+
37+
host = URI.parse("https://github.com/")
38+
client = ConnectProxy::HTTPClient.new(host, ignore_env: true)
39+
proxy = ConnectProxy.new("51.38.71.101", 8080)
40+
client.set_proxy(proxy)
41+
response = client.exec("GET", "/")
42+
response.success?.should eq(true)
43+
end
2144
end

src/connect-proxy.cr

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,23 @@ require "socket"
33
require "base64"
44
require "openssl"
55

6+
{% if compare_versions(Crystal::VERSION, "1.0.1") < 0 %}
7+
abstract class OpenSSL::SSL::Context
8+
def add_x509_verify_flags(flags : OpenSSL::SSL::X509VerifyFlags)
9+
param = LibSSL.ssl_ctx_get0_param(@handle)
10+
ret = LibCrypto.x509_verify_param_set_flags(param, flags)
11+
raise OpenSSL::Error.new("X509_VERIFY_PARAM_set_flags)") unless ret == 1
12+
end
13+
end
14+
{% end %}
15+
616
# Based on https://github.com/net-ssh/net-ssh/blob/master/lib/net/ssh/proxy/http.rb
717
class ConnectProxy
8-
PROXY_PASS = ENV["PROXY_PASSWORD"]?
9-
PROXY_USER = ENV["PROXY_USERNAME"]?
18+
class_property username : String? = ENV["PROXY_USERNAME"]?
19+
class_property password : String? = ENV["PROXY_PASSWORD"]?
20+
class_property proxy_uri : String? = ENV["https_proxy"]? || ENV["http_proxy"]? || ENV["HTTPS_PROXY"]? || ENV["HTTP_PROXY"]?
21+
class_property verify_tls : Bool = ENV["PROXY_VERIFY_TLS"]? != "false"
22+
class_property disable_crl_checks : Bool = ENV["PROXY_DISABLE_CRL_CHECKS"]? == "true"
1023

1124
# The hostname or IP address of the HTTP proxy.
1225
getter proxy_host : String
@@ -21,17 +34,17 @@ class ConnectProxy
2134
# Simple check for relevant environment
2235
#
2336
def self.behind_proxy?
24-
!!(ENV["https_proxy"]? || ENV["http_proxy"]? || ENV["HTTP_PROXY"]? || ENV["HTTPS_PROXY"]?)
37+
!!proxy_uri
2538
end
2639

2740
# Grab the host, port
2841
#
2942
def self.parse_proxy_url
30-
proxy_url = ENV["https_proxy"]? || ENV["http_proxy"]? || ENV["HTTP_PROXY"]? || ENV["HTTPS_PROXY"]
43+
proxy_url = proxy_uri.not_nil!
3144

3245
uri = URI.parse(proxy_url)
33-
user = uri.user || PROXY_USER
34-
pass = uri.password || PROXY_PASS
46+
user = uri.user || username
47+
pass = uri.password || password
3548
host = uri.host.not_nil!
3649
port = uri.port || URI.default_port(uri.scheme.not_nil!).not_nil!
3750
creds = {username: user, password: pass} if user && pass
@@ -48,7 +61,7 @@ class ConnectProxy
4861
# * :user => the user name to use when authenticating to the proxy
4962
# * :password => the password to use when authenticating
5063
def initialize(host, port, auth : NamedTuple(username: String, password: String)? = nil)
51-
auth = {username: PROXY_USER.as(String), password: PROXY_PASS.as(String)} if !auth && PROXY_USER && PROXY_PASS
64+
auth = {username: self.class.username.as(String), password: self.class.password.as(String)} if !auth && self.class.username && self.class.password
5265
@credentials = Base64.strict_encode("#{auth[:username]}:#{auth[:password]}").gsub(/\s/, "") if auth
5366
@proxy_host = host.gsub(/^http[s]?\:\/\//, "")
5467
@proxy_port = port
@@ -129,6 +142,14 @@ class ConnectProxy
129142
socket = {% if compare_versions(Crystal::VERSION, "0.36.0") < 0 %} @socket {% else %} @io {% end %}
130143
return if socket && !socket.closed?
131144

145+
if tls = @tls
146+
if !ConnectProxy.verify_tls
147+
tls.verify_mode = OpenSSL::SSL::VerifyMode::NONE
148+
elsif ConnectProxy.disable_crl_checks
149+
tls.add_x509_verify_flags OpenSSL::SSL::X509VerifyFlags::IGNORE_CRITICAL
150+
end
151+
end
152+
132153
{% if compare_versions(Crystal::VERSION, "0.36.0") < 0 %}
133154
begin
134155
@socket = proxy.open(@host, @port, @tls, **proxy_connection_options)

0 commit comments

Comments
 (0)