-
Notifications
You must be signed in to change notification settings - Fork 180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Occurrence of " MbedTLS error code -29312: SSL - The connection indicated an EOF" results in termination of the HTTP.listen() loop #318
Comments
@mkoonen , sorry for the delay here; there's been a decent amount of refactoring done in MbedTLS.jl recently by @samoconnor (ref: JuliaLang/MbedTLS.jl#174). The updates are now in the latest MbedTLS.jl release; could you check w/ the latest release and see if your issue here has been fixed? |
@quinnj , thank you for your response. I executed the scenario as described before with the following configuration: Ubuntu Linux 18.04 x64
Julia version 1.0.1
julia> Pkg.status()
Status `~/.julia/environments/v1.0/Project.toml`
[cd3eb016] HTTP v0.7.1
[739be429] MbedTLS v0.6.4 After I have started nc dev.xxxxxxxx.com 8000
^C I get the following error message: ERROR: LoadError: EOFError: read end of file
Stacktrace:
[1] handshake(::MbedTLS.SSLContext) at /home/mkoonen/.julia/packages/MbedTLS/CwGUN/src/ssl.jl:69
[2] handshake! at /home/mkoonen/.julia/packages/MbedTLS/CwGUN/src/MbedTLS.jl:101 [inlined]
[3] getsslcontext(::Sockets.TCPSocket, ::SSLConfig) at /home/mkoonen/.julia/packages/HTTP/YjRCz/src/Servers.jl:228
[4] macro expansion at ./logging.jl:309 [inlined]
[5] #listenloop#48(::Base.Iterators.Pairs{Symbol,Bool,Tuple{Symbol},NamedTuple{(:verbose,),Tuple{Bool}}}, ::Function, ::Function, ::Sockets.TCPServer, ::SSLConfig, ::String, ::String, ::Int64, ::Bool, ::getfield(HTTP.Servers, Symbol("##42#47")), ::Base.RefValue{Int64}) at /home/mkoonen/.julia/packages/HTTP/YjRCz/src/Servers.jl:336
[6] (::getfield(HTTP.Servers, Symbol("#kw##listenloop")))(::NamedTuple{(:verbose,),Tuple{Bool}}, ::typeof(HTTP.Servers.listenloop), ::Function, ::Sockets.TCPServer, ::SSLConfig, ::String, ::String, ::Int64, ::Bool, ::getfield(HTTP.Servers, Symbol("##42#47")), ::Base.RefValue{Int64}) at ./none:0
[7] #listen#39(::Bool, ::Bool, ::SSLConfig, ::Int64, ::Function, ::Base.RefValue{Base.IOServer}, ::Bool, ::Base.RefValue{Int64}, ::Base.Iterators.Pairs{Symbol,Bool,Tuple{Symbol},NamedTuple{(:verbose,),Tuple{Bool}}}, ::typeof(HTTP.Servers.listen), ::getfield(Main, Symbol("##3#4")), ::Sockets.InetAddr{Sockets.IPv4}) at /home/mkoonen/.julia/packages/HTTP/YjRCz/src/Servers.jl:303
[8] (::getfield(HTTP.Servers, Symbol("#kw##listen")))(::NamedTuple{(:ssl, :sslconfig, :verbose),Tuple{Bool,SSLConfig,Bool}}, ::typeof(HTTP.Servers.listen), ::Function, ::Sockets.InetAddr{Sockets.IPv4}) at ./none:0
[9] #listen#36 at /home/mkoonen/.julia/packages/HTTP/YjRCz/src/Servers.jl:280 [inlined]
[10] (::getfield(HTTP.Servers, Symbol("#kw##listen")))(::NamedTuple{(:ssl, :sslconfig, :verbose),Tuple{Bool,SSLConfig,Bool}}, ::typeof(HTTP.Servers.listen), ::Function, ::Sockets.IPv4, ::Int64) at ./none:0
[11] #listen#37(::Base.Iterators.Pairs{Symbol,Any,Tuple{Symbol,Symbol,Symbol},NamedTuple{(:ssl, :sslconfig, :verbose),Tuple{Bool,SSLConfig,Bool}}}, ::Function, ::Function, ::String, ::Int64) at /home/mkoonen/.julia/packages/HTTP/YjRCz/src/Servers.jl:281
[12] (::getfield(HTTP.Servers, Symbol("#kw##listen")))(::NamedTuple{(:ssl, :sslconfig, :verbose),Tuple{Bool,SSLConfig,Bool}}, ::typeof(HTTP.Servers.listen), ::Function, ::String, ::Int64) at ./none:0
[13] top-level scope at none:0
[14] include at ./boot.jl:317 [inlined]
[15] include_relative(::Module, ::String) at ./loading.jl:1041
[16] include(::Module, ::String) at ./sysimg.jl:29
[17] include(::String) at ./client.jl:388
[18] top-level scope at none:0
in expression starting at /home/mkoonen/issues/julia/mbedtls/rca/server.jl:24 and |
It looks to me like Lines 33 to 42 in a81ff0a
Really, Base should have an abstract |
@samoconnor variable id and i=id are unused, in listen loop so exiting the catch and continue are equivalent. line 355: Tested with a ratelimit::5//1 and fast connections causing throttling and EOFError |
I am just confirming that this issue is still present in Julia 1.5 with latest HTTP and MbedTLS Given a server: using HTTP, MbedTLS, Pkg
Pkg.status()
# HTTP.Servers.SSLConfig("snakeoil.crt", "snakeoil.key") #Same behaviour on HTTP MbedTLS version
tlsconfig = SSLConfig("snakeoil.crt", "snakeoil.key")
@async try
HTTP.listen("127.0.0.1", 8085; sslconfig = tlsconfig) do http::HTTP.Stream
while !eof(http)
println("body data: ", String(readavailable(http)))
end
HTTP.setstatus(http, 101)
HTTP.startwrite(http)
write(http, "response body\n")
write(http, "more response body")
end
catch err
@error err exception = (err, catch_backtrace())
end
wait() And a client: using HTTP
clientoptions = (;
require_ssl_verification = false,
)
@info "First request to https is successful"
r = HTTP.request("GET", "https://127.0.0.1:8085"; clientoptions...)
println(r.status)
println(String(r.body))
try
@info "Second request to http request causes server listen() loop to error and exit"
HTTP.request("GET", "http://127.0.0.1:8085"; clientoptions...)
catch
@info "Subsequent requests to the server fail"
HTTP.request("GET", "https://127.0.0.1:8085"; clientoptions...)
end The client ouput is: [ Info: First request to https is successful
101
response body
more response body
[ Info: Second request to http request causes server listenloop to error and exit
[ Info: Subsequent requests to the server fail
ERROR: LoadError: IOError(Base.IOError("connect: connection refused (ECONNREFUSED)", -111) during request(https://127.0.0.1:8085))
Stacktrace: ...
IOError(Base.IOError("connect: connection refused (ECONNREFUSED)", -111) during request(http://127.0.0.1:8085))
Stacktrace: ... and the server output is: Status `/var/opt/testssl/Project.toml`
[cd3eb016] HTTP v0.8.19
[739be429] MbedTLS v1.0.2
┌ Error: MbedTLS error code -30976: SSL - Processing of the ClientHello handshake message failed
│ exception =
│ MbedTLS error code -30976: SSL - Processing of the ClientHello handshake message failed
│ Stacktrace:
│ [1] handshake(::MbedTLS.SSLContext) at /home/michaeladmin/.julia/packages/MbedTLS/VbsaQ/src/ssl.jl:83
│ [2] handshake! at /home/michaeladmin/.julia/packages/MbedTLS/VbsaQ/src/MbedTLS.jl:134 [inlined]
│ [3] getsslcontext(::Sockets.TCPSocket, ::SSLConfig) at /home/michaeladmin/.julia/packages/HTTP/IAI92/src/Servers.jl:89
│ [4] accept at /home/michaeladmin/.julia/packages/HTTP/IAI92/src/Servers.jl:83 [inlined]
│ [5] listenloop(::Function, ::HTTP.Servers.Server{SSLConfig,Sockets.TCPServer}, ::HTTP.Servers.var"#2#5"{Nothing,HTTP.Servers.var"#4#7"}, ::Base.RefValue{Int64}, ::Int64, ::Int64, ::Bool) at /home/michaeladmin/.julia/packages/HTTP/IAI92/src/Servers.jl:247
│ [6] listen(::var"#2#4", ::String, ::Int64; sslconfig::SSLConfig, tcpisvalid::Function, server::Nothing, reuseaddr::Bool, connection_count::Base.RefValue{Int64}, rate_limit::Nothing, reuse_limit::Int64, readtimeout::Int64, verbose::Bool) at /home/michaeladmin/.julia/packages/HTTP/IAI92/src/Servers.jl:234
│ [7] macro expansion at /var/opt/testssl/testserver.jl:12 [inlined]
│ [8] (::var"#1#3")() at ./task.jl:356
└ @ Main /var/opt/testssl/testserver.jl:22 |
Fixes #318. This is a bad bug. Basically, if you're running an ssl server, any client who sends a non-perfect https request (like simply a plain *http* request) would result in the server task throwing an error and closing. This is partly because the thrown error isn't super obvious, nested down a few calls in our overloaded `Sockets.accept(::Server{SSLConfig})` method. The fix proposed here is that we'll put a try-catch in the ssl handshaking code and if an error is thrown, we return `nothing`; in the server `listenloop`, if the accepted `io` is `nothing`, then we'll skip and try to accept the next connection.
I checked with release @quinnj : thanks for fixing this! |
Version Information
Julia Version 1.0.0 (2018-08-08), Ubuntu 18.04 x64 and
Given code
server.jl
:with a proven correct
tlsconfig
.Creation of error situation
Run
server.jl
. Execute:where
dev.xxxxxxxx.com
resolves correctly tolocalhost
.Oberved result is termination of
HTTP.listen()
because of an exception:I would expect only the execution flow w.r.t. the specific failing HTTPS-connection would be terminated and not the entire
HTTP.listen()
because there might be, e.g. in Azure, health probes that use HTTP to try to make a connection.Direction of a solution
If I change these lines in
Servers.jl
fromHTTP.jl
into
it works like expected for the test case I described in this issue. Next question for me would be if
is the exact/correct way to solve this?
The text was updated successfully, but these errors were encountered: