Curl request error (52) from docker container but works on host - windows

I am running a Linux (Debian based) docker container on a Windows host.
I have a device with an HTTP based API that I want to interface with from the container.
When I run the curl command to the devices API under WSL from my host machine, it responds correctly.
<username>#<hostname>:/mnt/c/Users/$ curl -H "Authorization: Basic YWRtaW46aGVybW9zYTA=" http://172.16.255.33/Set.cmd?CMD=GetPower -v
* Trying 172.16.255.33:80...
* TCP_NODELAY set
* Connected to 172.16.255.33 (172.16.255.33) port 80 (#0)
> GET /Set.cmd?CMD=GetPower HTTP/1.1
> Host: 172.16.255.33
> User-Agent: curl/7.68.0
> Accept: */*
> Authorization: Basic YWRtaW46aGVybW9zYTA=
>
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Connection: close
<
<html>p61=1,p62=1,p63=0,p64=0</html>
* Closing connection 0
However, when I do the same curl command from my container, I get the error (52) Empty reply from server
root#9af1adf97ba7:/# curl -H "Authorization: Basic YWRtaW46aGVybW9zYTA=" http://172.16.255.33/Set.cmd?CMD=GetPower -v
* Trying 172.16.255.33:80...
* Connected to 172.16.255.33 (172.16.255.33) port 80 (#0)
> GET /Set.cmd?CMD=GetPower HTTP/1.1
> Host: 172.16.255.33
> User-Agent: curl/7.74.0
> Accept: */*
> Authorization: Basic YWRtaW46aGVybW9zYTA=
>
* Empty reply from server
* Connection #0 to host 172.16.255.33 left intact
curl: (52) Empty reply from server
In Wireshark, I see the device is setting the RST flag in its response when queried from the container. No such reset in the response when queried from my host machine.
I am starting my container using these arguments:
docker run -it -p 80:80 <image-name> bash
When I start to run the container on a Linux host using the same args, the curl request succeeds (as a test, I have to run this app on a Windows host).
I have tried both WSL2 based and Hyper-V based versions of Docker on Windows.
Under WSL2 container, I get no response from the device.
Under Hyper-V based container, I get the issue described above.
I've spent about a day Googling and trying various things, and I am out of ideas at this point.
Thanks.

Related

Webservice does not work after being packaged into a Docker image

I write a simple webservice in ruby with sinatra. If I run ruby app.rb it runs on localhost:4567. I write a Dockerfile to make an image and expose port 4567.
However, when I run the docker image the webservice runs but if I try to connect (with curl and browser) to port 4567, it says Connection reset by peer.
Anyone has any suggestion? Because I do not know what to check in this case. I have tried some vague things but still..
The webservice runs normally outside docker.
EDIT 1:
I have pushed the image to eivor/ruby. If you run it and go to browser to check it would say connection reset. Yes I tried docker run -p 4567:4567 eivor/ruby as said before posting the question.
EDIT 2: Here is the app.rb
require 'sinatra'
require 'referal' # this is the gem that calculate reward points to users
require 'json'
require 'byebug'
get '/' do
'hello, world!'
end
# inside docker image, even get / returns connection reset by peer
# not to mention post data to it
post '/' do
data = JSON.parse(request.body.read)
input = []
data.each do | key, value |
input << value
end
invs, users = input.reduce([[],[]]) do | results, instruction |
results = classify(instruction, results[0], results[1])
results
end
res = export(users)
# byebug
puts res
end
post '/text' do
#data = request.body.readlines
#byebug
#processed = #data.map{ |s| process(s) }
#invs, #users = #processed.reduce([[],[]]) do | results, instruction |
results = classify(instruction, results[0], results[1])
results
end
#jsn = export(#users)
puts #jsn
end
Here is the Dockerfile, i build a lightweight ruby from alpine
FROM alpine:3.5
ENV BUILD_PACKAGES bash curl-dev ruby-dev build-base git libstdc++ tzdata ca-certificates
ENV RUBY_PACKAGES ruby>2.3 ruby-irb ruby-rake ruby-io-console ruby-bigdecimal ruby-json
RUN apk update && apk upgrade
RUN apk add $BUILD_PACKAGES && apk add $RUBY_PACKAGES
RUN apk add ruby-bundler>1.17
RUN echo 'gem: --no-document' > /etc/gemrc && rm -rf /var/cach/apk/*
RUN gem install bundler
RUN mkdir /usr/app
WORKDIR /usr/app
RUN git init
COPY . /usr/app
RUN bundle install
RUN bundle exec rake install
EXPOSE 4567
CMD ["ruby", "./app.rb"]
If I run outside docker with command ruby app.rb or bundle exec rerun app.rb it works normally. But using docker image, it does not. I run the command:
docker run -p 4567:4567 eivor/ruby
The server runs,
[2019-03-14 16:59:59] INFO WEBrick 1.3.1
[2019-03-14 16:59:59] INFO ruby 2.3.8 (2018-10-18) [x86_64-linux-musl]
== Sinatra (v2.0.5) has taken the stage on 4567 for development with backup from WEBrick
[2019-03-14 16:59:59] INFO WEBrick::HTTPServer#start: pid=1 port=4567
but when I try to access with browser or curl, it says connection reset by peer. If I try to post with curl, the data is actually sent but it does not respond, it hangs up on me instead.
curl -v localhost:4567 --data-binary #test/input
* Rebuilt URL to: localhost:4567/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 4567 (#0)
> POST / HTTP/1.1
> Host: localhost:4567
> User-Agent: curl/7.58.0
> Accept: */*
> Content-Length: 369
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 369 out of 369 bytes
* Recv failure: Connection reset by peer
* stopped the pause stream!
* Closing connection 0
curl: (56) Recv failure: Connection reset by peer
This issue is happening because Sinatra by default (development environment) listen on 127.0.0.1 which not works in case of external connection to container
:bind - server hostname or IP address
String specifying the hostname or IP address of the interface to listen on when the :run setting is enabled. The default value in the development environment is 'localhost' which means the server is only available from the local machine. In other environments the default is '0.0.0.0', which causes the server to listen on all available interfaces.
So if you will continue on running in development mode, you need to change it to 0.0.0.0, for example:
docker run -p 4567:4567 --name stack eivor/ruby bash -c 'ruby ./app.rb -o 0.0.0.0'
Which can be used in Dockerfile as:
CMD ["ruby", "./app.rb", "-o", "0.0.0.0"]
Or you can use the following within your script:
set :bind, '0.0.0.0'
Then from outside the container you can get the result:
curl -v localhost:4567
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 4567 (#0)
> GET / HTTP/1.1
> Host: localhost:4567
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/html;charset=utf-8
< Content-Length: 13
< X-Xss-Protection: 1; mode=block
< X-Content-Type-Options: nosniff
< X-Frame-Options: SAMEORIGIN
< Server: WEBrick/1.3.1 (Ruby/2.3.8/2018-10-18)
< Date: Thu, 14 Mar 2019 17:17:20 GMT
< Connection: Keep-Alive
<
* Connection #0 to host localhost left intact
hello, world!
For more configuration check the following: CONFIGURING SETTINGS
Have a look at this article: https://docs.docker.com/config/containers/container-networking/
In few words - try to publish your exposed ports via -p argument.
For example:
$ docker run -it -p 4567 my-local-image
From the documentation:
Flag value Description
-p 8080:80 Map TCP port 80 in the container to port 8080 on the Docker host.
You need to map the TCP port 4567 in the container to a port on the Docker host. For example, to map it to port 8080:
$ docker run -it -p 8080:4567 image-goes-here

Hostname was NOT found in DNS cache for port 8080 but fine on port 80?

I am testing an API I have made using Springboot from my laptop (192.168.1.217:8080) and I am trying to get a cURL request via SSH from my Raspberry Pi.
Here is the error I am receiving when I try to send the request via port 8080 which it seems to not like:
pi#raspberrypi:~ $ curl -v 192.168.1.217:8080/api
* Hostname was NOT found in DNS cache
* Trying 192.168.1.217...
However cURL does work for the same IP but with port 80:
pi#raspberrypi:~ $ curl -v 192.168.1.217
* Rebuilt URL to: 192.168.1.217/
* Hostname was NOT found in DNS cache
* Trying 192.168.1.217...
* Connected to 192.168.1.217 (192.168.1.217) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.38.0
> Host: 192.168.1.217
> Accept: */*
>
< HTTP/1.1 302 Found
< Date: Thu, 30 Mar 2017 17:20:43 GMT
* Server Apache/2.4.23 (Win32) OpenSSL/1.0.2h PHP/5.5.38 is not blacklisted
< Server: Apache/2.4.23 (Win32) OpenSSL/1.0.2h PHP/5.5.38
< X-Powered-By: PHP/5.5.38
< Location: http://192.168.1.217/dashboard/
< Content-Length: 0
< Content-Type: text/html
<
* Connection #0 to host 192.168.1.217 left intact
pi#raspberrypi:~ $
I've tried looking around but to no avail... anybody have any suggestions as to why I cannot find my own hostname in the DNS cache?
Cheers
No, Hostname was NOT found in DNS cache is not the problem. You can clearly see on the next line, in both examples, that after saying that curl is trying to connect to 192.168.1.217. Your problem is that nothing is answering on port 8080 on that IP address (while an Apache server is answering on port 80 there).
If you're getting a long pause and then a timeout rather than a quick "Connection refused", you almost certainly need to open port 8080 in the local firewall on your server machine.
curl without a protocol prefix presumes HTTP port 80.
To use another port, where it does not make that assumption, all you need to do is change your command's URL to be like this:
curl -v http://192.168.1.217:8080/api
Here is a decent article on the subject: Using CURL For Testing Web Applications

Gitlab CI - Failed to register runner

I've setup my gitlab installation from source, secured it with letsencrypt and deployed it under https://gitlab.mydomain.com. I can access the website and create repositories, etc. but I can't find a way to register a gitlab ci runner for the installation.
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci):
https://gitlab.mydomain.com/ci
Please enter the gitlab-ci token for this runner:
xxxxxxxx-xxxxxxxx
Please enter the gitlab-ci description for this runner:
[server]: test
Please enter the gitlab-ci tags for this runner (comma separated):
test
ERROR: Registering runner... failed runner=xxxxxxx
status=couldn't execute POST against https://gitlab.mydomain.com/ci/api/v1/runners/register.json:
Post https://gitlab.mydomain.com/ci/api/v1/runners/register.json:
read tcp [ipv6address]:33518->[ipv6address]:443: read: connection reset by peer
PANIC: Failed to register this runner. Perhaps you are having network problems
My gitlab system is working fine and I really ran out of explanations why there would be a connection reset by peer. When I try to curl the address from the error message directly, it returns a correct response.
curl -v https://gitlab.mydomain.com/ci/api/v1/runners/register.json
* Trying ipv6address...
* Connected to gitlab.mydomain.com (ipv6address) port 443 (#0)
* found 174 certificates in /etc/ssl/certs/ca-certificates.crt
* found 700 certificates in /etc/ssl/certs
* ALPN, offering h2
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_256_GCM_SHA384
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: mydomain.com (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject: CN=mydomain.com
* start date: Wed, 18 May 2016 14:35:00 GMT
* expire date: Tue, 16 Aug 2016 14:35:00 GMT
* issuer: C=US,O=Let's Encrypt,CN=Let's Encrypt Authority X3
* compression: NULL
* ALPN, server did not agree to a protocol
> GET /ci/api/v1/runners/register.json HTTP/1.1
> Host: gitlab.mydomain.com
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 405 Method Not Allowed
< Server: nginx
< Date: Sun, 29 May 2016 09:14:09 GMT
< Content-Type: application/json
< Content-Length: 2
< Connection: keep-alive
< Allow: OPTIONS, POST
< Cache-Control: no-cache
< Status: 405 Method Not Allowed
If the runner and gitlab are running on the same host you can get around this problem by entering a the first question the following instead what is given in the docs:
http://gitlab:port
where gitlab is the container name and port the left port number of the container. If you are using gitlab internal ssl certs you specify https instead of http. This always solves this problem when I get it.
For those that are using docker:
The issue its about docker network.
If you try
"$docker container inspect $id"
You are going to see the IPAddress of gitlab container.
Point to that ip adress on first question to works fine.
Problem went away after updating gitlab to 8.8.3 and gitlab-multi-ci-runner to the most recent version.
I also started my gitlab nginx configuration files from scratch.
In the end, I can't tell which change exactly solved the problem.
I had so far many errors and issue starting with Error 404, 403 and endings with problem with post request.
For me, problem seems to be incompatibility between GitLab and ci-runner.
Solution, same on post issue, was install older version of ci-runner:
sudo apt install gitlab-ci-multi-runner=1.11.1
I've solved it by installing gitlab-ci-multi-runner=1.11.1.

Webrick proxy + cURL returns bad request

I'm going nuts, I have a very simple WEBrickProxy (WEBrick 1.3.1, with Ruby 1.9.3), and I want to try it out with curl. Here is the proxy:
require 'webrick'
require 'webrick/httpproxy'
server = WEBrick::HTTPProxyServer.new(:BindAddress => "localhost", :Port => 8888)
trap('INT') { server.shutdown }
server.start
And here is the cURL command
curl --proxy localhost:8888 http://www.google.de -v
But the curl command always returns a bad request:
* About to connect() to proxy localhost port 8888 (#0)
* Trying ::1...
* connected
* Connected to localhost (::1) port 8888 (#0)
> GET http://www.google.de HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host: www.google.de
> Accept: */*
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 400 Bad Request
< Content-Type: text/html; charset=ISO-8859-1
< Server: WEBrick/1.3.1 (Ruby/1.9.3/2012-10-12)
< Date: Mon, 18 Mar 2013 13:44:27 GMT
< Content-Length: 295
< Connection: close
<
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD><TITLE>Bad Request</TITLE></HEAD>
<BODY>
<H1>Bad Request</H1>
bad URI `http://www.google.de'.
<HR>
<ADDRESS>
WEBrick/1.3.1 (Ruby/1.9.3/2012-10-12) at
23tuxmb.local:8888
</ADDRESS>
</BODY>
</HTML>
* Closing connection #0
curl --version returns on my Mac OS X 10.8
curl 7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IPv6 Largefile NTLM NTLM_WB SSL libz
I can't find out where the error is, and I tried that piece of code a couple of weeks ago, and I can remember that it worked.
The weird thing is, that when I configure my Mac to globally use that proxy (inside the System Settings -> Network -> Advanced -> Proxies -> Web Proxy), everything works. A request with Chrome or any other application is routed through the proxy (and I see this inside the Terminal log of the proxy).
So, can anyone reproduce this issue? Is it a curl bug? Or a Webrick related issue?
EDIT
More information: The output of the ruby script itself when curl tries to connect is
[2013-03-18 17:16:32] ERROR bad URI `http://www.amazon.de'.
localhost - - [18/Mar/2013:17:16:32 CET] "GET http://www.amazon.de HTTP/1.1" 400 286
- -> http://www.amazon.de
thx!
If you add a trailing slash to the URL you request, does it work then? Ie a command line like this:
curl --proxy localhost:8888 http://www.google.de/ -v
(this is a curl bug reported in bug #1206, and fixed in git and next release...)

How do I use Tor with cURL (in Windows)?

I have Vidalia installed, set up Chrome to use port 8118 for the proxy and I've checked my connection through https://check.torproject.org/ but I'm having difficulties getting this work with the command-line tool cURL. This is what I try:
C:\>curl -v --proxy localhost::9050 http://google.com
* About to connect() to proxy localhost port 0 (#0)
* Failed to connect to ↕: Address not available
* No error
* Trying 127.0.0.1... Failed to connect to 127.0.0.1: Address not available
* No error
* couldn't connect to host
* Closing connection #0
curl: (7) Failed to connect to ↕: Address not available
Solved:
curl -v --socks4a localhost:9050 http://check.torproject.org/
Use --socks5 (two dashes). -socks5 is not a valid parameter for curl, so curl is interpreting it as a hostname.
Turns out this entire mess was just syntax problems. A proper command is here:
curl -v --socks4a localhost:9050 http://check.torproject.org/
With TWO dashes before socks4a and ONE colon before the port.
More updated response using socks5.
curl -v --socks5 localhost:9150 http://check.torproject.org/
So, using port 9150 for socks 5.

Resources