diff --git a/docker-compose.yml b/docker-compose.yml index a225749..e7bac22 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,7 +36,12 @@ services: - ./server/run.sh:/app/run.sh tests: - build: ./tests + build: + context: ./tests + args: + faraday_gem_ref: ${FARADAY_GEM_REF:-master} + faraday_http_gem_ref: ${FARADAY_HTTP_GEM_REF:-master} + socksify_gem_ref: ${FARADAY_SOCKSIFY_GEM_REF:-master} depends_on: - server - proxy @@ -45,9 +50,9 @@ services: environment: - HTTP_HOST=faraday-live.localhost - PROXY_HOST=live-proxy.localhost - - FARADAY_ADAPTER=${TEST_ADAPTER:-} - - FARADAY_METHOD=${TEST_METHOD:-} - - SERVER_PROTOCOL=${TEST_PROTO:-} + - TEST_ADAPTER=${TEST_ADAPTER:-} + - TEST_METHOD=${TEST_METHOD:-} + - TEST_PROTO=${TEST_PROTO:-} volumes: - certca:/root/.local/share/mkcert/:ro - certdata:/certs:ro diff --git a/docs/dev.md b/docs/dev.md index f7b9675..186dff0 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -38,7 +38,9 @@ This runs tests against these webservers and proxies: 1. HTTP server on port 80 (`TEST_PROTO=http`) 2. Self-signed HTTPS server on port 443 (`TEST_PROTO=unverified`) 3. Verified and valid HTTPS server on port 443 (`TEST_PROTO=https`) -4. Proxy server (`TEST_PROTO=proxy`) +4. HTTP proxy server (`TEST_PROTO=http_proxy`) +5. SOCKS proxy server (`TEST_PROTO=socks_proxy`) +6. LEGACY: Only HTTP proxy server (`TEST_PROTO=proxy`) You can choose to run one or more explicitly: diff --git a/proxy/Dockerfile b/proxy/Dockerfile index 9900d25..231d35f 100644 --- a/proxy/Dockerfile +++ b/proxy/Dockerfile @@ -1,5 +1,6 @@ FROM golang:1.12.3 RUN go get -u github.com/elazarl/goproxy +RUN go get -u github.com/armon/go-socks5 # no auth, http EXPOSE 8080 @@ -13,6 +14,12 @@ EXPOSE 9080 # auth:pass, https EXPOSE 9080 +# no auth, socks +EXPOSE 6000 + +# auth:pass, socks +EXPOSE 6001 + WORKDIR /app COPY . ./ RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o proxy . diff --git a/proxy/main.go b/proxy/main.go index 5db204c..26def33 100644 --- a/proxy/main.go +++ b/proxy/main.go @@ -5,6 +5,8 @@ import ( "flag" "log" "net/http" + + socks5 "github.com/armon/go-socks5" ) var ( @@ -15,6 +17,24 @@ var ( func main() { flag.Parse() + unauthSocks, err := socks5.New(&socks5.Config{}) + if err != nil { + panic(err) + } + + authSocks, err := socks5.New(&socks5.Config{ + Credentials: socks5.StaticCredentials(map[string]string{ + "faraday": "live", + }), + }) + if err != nil { + panic(err) + } + + log.Println("Starting Socks Proxy servers on :6000, :6001...") + go unauthSocks.ListenAndServe("tcp", ":6000") + go authSocks.ListenAndServe("tcp", ":6001") + servers := &ServerList{} servers.Add(":8080", newProxy("http_proxy")) servers.Add(":9080", newProxy("http_auth_proxy")) @@ -39,7 +59,7 @@ func (l *ServerList) Listen() { } func (l *ServerList) listen(srv *http.Server) { - log.Printf("Starting Proxy server on %s...", srv.Addr) + log.Printf("Starting HTTP Proxy server on %s...", srv.Addr) if srv.TLSConfig == nil { srv.ListenAndServe() return diff --git a/tests/Dockerfile b/tests/Dockerfile index c4be577..d8d1f55 100644 --- a/tests/Dockerfile +++ b/tests/Dockerfile @@ -2,22 +2,28 @@ FROM ruby:2.6.2 as build ENV LANG C.UTF-8 WORKDIR /app -COPY Gemfile . -COPY Gemfile.lock . # install all non-git gems RUN gem install bundler -v '~> 2.0.1' --no-document -RUN bundle install --without development test -j4 --retry 3 -ARG faraday_gem_ref=master -ARG faraday_http_gem_ref=master +COPY Gemfile . +COPY Gemfile.lock . + +RUN bundle install --without development test -j4 --retry 3 # install just the non-git gems. These will change more frequently. RUN echo "gem 'faraday', git: 'https://github.com/lostisland/faraday'," >> Gemfile +ARG faraday_gem_ref=master RUN echo " ref: '$faraday_gem_ref', require: 'faraday'" >> Gemfile + RUN echo "gem 'faraday-http', git: 'https://github.com/lostisland/faraday-http'," >> Gemfile +ARG faraday_http_gem_ref=master RUN echo " ref: '$faraday_http_gem_ref', require: 'faraday/http'" >> Gemfile +RUN echo "gem 'socksify', git: 'https://github.com/astro/socksify-ruby'," >> Gemfile +ARG socksify_gem_ref=master +RUN echo " ref: '$socksify_gem_ref'" >> Gemfile + RUN bundle install \ # Remove unneeded files (cached *.gem, *.o, *.c) && rm -rf /usr/local/bundle/cache/*.gem \ diff --git a/tests/spec/insecure_spec.rb b/tests/spec/insecure_spec.rb index 21385d2..679f860 100644 --- a/tests/spec/insecure_spec.rb +++ b/tests/spec/insecure_spec.rb @@ -10,15 +10,30 @@ proxy: :http_proxy, server: :http, } - end if ServerProtocols.proxy? + end if ServerProtocols.http_proxy? + + describe "#{adapter} using Socks proxy with HTTP server" do + include_examples 'a proxied connection', adapter, { + proxy: :socks_proxy, + server: :http, + } + end if ServerProtocols.socks_proxy? && adapter.socks_proxy? describe "#{adapter} using authenticated HTTP proxy with HTTP server" do include_examples 'a proxied connection', adapter, { proxy: :http_auth_proxy, server: :http, - auth: "faraday:live", + auth: "faraday:live", + } + end if ServerProtocols.http_proxy? + + describe "#{adapter} using authenticated Socks proxy with HTTP server" do + include_examples 'a proxied connection', adapter, { + proxy: :socks_auth_proxy, + server: :http, + auth: "faraday:live", } - end if ServerProtocols.proxy? + end if ServerProtocols.socks_proxy? && adapter.socks_proxy? describe "#{adapter} with unverified HTTPS server" do let(:url_kind) { :https } diff --git a/tests/spec/secure_spec.rb b/tests/spec/secure_spec.rb index fe53cac..feb6d14 100644 --- a/tests/spec/secure_spec.rb +++ b/tests/spec/secure_spec.rb @@ -10,15 +10,30 @@ proxy: :http_proxy, server: :https, } - end if ServerProtocols.proxy? + end if ServerProtocols.http_proxy? - describe "#{adapter} using HTTP proxy with HTTPS server" do + describe "#{adapter} using authenticated HTTP proxy with HTTPS server" do include_examples 'a proxied connection', adapter, { proxy: :http_auth_proxy, server: :https, auth: "faraday:live", } - end if ServerProtocols.proxy? + end if ServerProtocols.http_proxy? + + describe "#{adapter} using Socks proxy with HTTPS server" do + include_examples 'a proxied connection', adapter, { + proxy: :socks_proxy, + server: :https, + } + end if ServerProtocols.socks_proxy? && adapter.socks_proxy? + + describe "#{adapter} using authenticated Socks proxy with HTTPS server" do + include_examples 'a proxied connection', adapter, { + proxy: :socks_auth_proxy, + server: :https, + auth: "faraday:live", + } + end if ServerProtocols.socks_proxy? && adapter.socks_proxy? describe "#{adapter} using HTTPS proxy with HTTPS server" do it "fails to connect" do @@ -29,7 +44,7 @@ end expect { conn.get 'wat' }.to raise_error(Faraday::ConnectionFailed) end - end if ServerProtocols.proxy? && !adapter.https_proxy_bug? + end if ServerProtocols.http_proxy? && !adapter.https_proxy_bug? describe "#{adapter} using authenticated HTTPS proxy with HTTPS server" do it "fails to connect" do @@ -40,5 +55,5 @@ end expect { conn.get 'wat' }.to raise_error(Faraday::ConnectionFailed) end - end if ServerProtocols.proxy? && !adapter.https_proxy_bug? + end if ServerProtocols.http_proxy? && !adapter.https_proxy_bug? end diff --git a/tests/spec/support/adapters.rb b/tests/spec/support/adapters.rb index 07ff6de..e76c4ee 100644 --- a/tests/spec/support/adapters.rb +++ b/tests/spec/support/adapters.rb @@ -28,7 +28,7 @@ def self.adapter_keys end def self.explicit_adapters - ENV['FARADAY_ADAPTER'].to_s.split(',').map! do |key| + ENV['TEST_ADAPTER'].to_s.split(',').map! do |key| key.strip! key.downcase! key.to_sym @@ -52,6 +52,7 @@ def to_s :connect_with_response_body, # enables CONNECT tests WITH response body :unverified_https_bug, # https://github.com/technoweenie/faraday-live/issues/4 :https_proxy_bug, # https://github.com/technoweenie/faraday-live/issues/6 + :socks_proxy, ].each do |feature| define_method("#{feature}?") { @features.include?(feature) } end @@ -81,7 +82,7 @@ def connect_method? :trace_method, :connect_with_response_body), :net_http => Adapter.new(:net_http, - :trace_method, :connect_with_response_body), + :socks_proxy, :trace_method, :connect_with_response_body), :patron => Adapter.new(:patron, :unverified_https_bug), diff --git a/tests/spec/support/examples/proxy.rb b/tests/spec/support/examples/proxy.rb index 3cd722b..ca4564e 100644 --- a/tests/spec/support/examples/proxy.rb +++ b/tests/spec/support/examples/proxy.rb @@ -25,7 +25,12 @@ end # proxy does not modify https requests - expected = server_url_kind == :https ? '' : "goproxy (#{proxy_url_kind})" + expected = case proxy_url_kind + when :socks_proxy, :socks_auth_proxy + "" + else + server_url_kind == :https ? "" : "goproxy (#{proxy_url_kind})" + end include_examples 'common request tests', server_url_kind, adapter, response_header: { 'Via' => expected, diff --git a/tests/spec/support/http_methods.rb b/tests/spec/support/http_methods.rb index 1d22018..c920b35 100644 --- a/tests/spec/support/http_methods.rb +++ b/tests/spec/support/http_methods.rb @@ -29,7 +29,7 @@ def self.http_methods! end def self.explicit_methods - ENV['FARADAY_METHOD'].to_s.split(',').map! do |key| + ENV['TEST_METHOD'].to_s.split(',').map! do |key| key.strip! key.downcase! key.to_sym diff --git a/tests/spec/support/protocols.rb b/tests/spec/support/protocols.rb index b14728f..0433a35 100644 --- a/tests/spec/support/protocols.rb +++ b/tests/spec/support/protocols.rb @@ -13,8 +13,12 @@ def self.unverified_https? protocols.include?(:unverified) end - def self.proxy? - protocols.include?(:proxy) + def self.http_proxy? + protocols.include?(:proxy) || protocols.include?(:http_proxy) + end + + def self.socks_proxy? + protocols.include?(:socks_proxy) end def self.test?(*protos) @@ -34,7 +38,7 @@ def self.protocols! end def self.explicit_protocols - ENV['SERVER_PROTOCOL'].to_s.split(',').map! do |key| + ENV['TEST_PROTO'].to_s.split(',').map! do |key| key.strip! key.downcase! key.to_sym diff --git a/tests/spec/support/urls.rb b/tests/spec/support/urls.rb index 4cd6ffd..86aa2aa 100644 --- a/tests/spec/support/urls.rb +++ b/tests/spec/support/urls.rb @@ -33,4 +33,14 @@ def self.https_auth_proxy_server(auth = nil) auth += "@" if auth "http://#{auth}#{ENV['PROXY_HOST']}:9443" end + + def self.socks_proxy_server(auth = nil) + auth += "@" if auth + "socks://#{auth}#{ENV['PROXY_HOST']}:6000" + end + + def self.socks_auth_proxy_server(auth = nil) + auth += "@" if auth + "socks://#{auth}#{ENV['PROXY_HOST']}:6001" + end end