Jump to content
baka0815

TIdHTTPWebBrokerBridge: Require TLS

Recommended Posts

At first: I searched the forum but couldn't find a topic matching my case, however my search-fu might be lacking, so please send me to the right place, if this was asked before. Thanks!

 

I'm using a TIdHTTPWebBrokerBridge to serve incoming connections and that works flawlessly, with and without TLS (<= 1.2). However, if TLS is activated, I want to force the usage of TLS.

What I'm currently doing is to implement OnQuerySSLPort(APort: TIdPort; var VUseSSL: Boolean) ans set VUseSLL to True, so SSL/TLS is forced and connections without TLS are not possible.

But when I try to connect to the server without TLS (http://localhost:8080) I'm getting (via Bruno)

Error invoking remote method 'send-http-request': TypeError: Cannot read properties of undefined (reading 'data')

or "connection reset" via Firefox.

 

When debugging I see that an exception is raised in procedure TIdSSLSocket.Accept(const pHandle: TIdStackSocketHandle);

EIdOSSLAcceptError.RaiseException(fSSL, error, RSSSLAcceptError);

How am I supposed to implement a redirect to the correct HTTPS-URL (or raise an error that TLS is required or something along those lines=?

Share this post


Link to post
Posted (edited)

(This is for TIdHTTPServer component, hope to be useful for you component).

You must use the "TIdSSLIOHandlerSocketBase.PassThrough" property ... if you set it to FALSE then TLS is required, if you set to TRUE only clear connection (NO TLS) are managed.

Do it in the "create connection" event:

 

procedure TForm1.Server1Connect(AContext: TIdContext);
begin
  If AContext.Connection.IOHandler is TIdSSLIOHandlerSocketBase then
    TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler).PassThrough := false;     //If True the authentication is not managed (only in clear text) or is used for STARTTLS, if false it manages the TLS/SSL authentication
end;

 

Edited by DelphiUdIT

Share this post


Link to post
Posted (edited)

That's exactly what I'm doing with the implementation of OnQuerySSLPort().

  if AContext.Connection.IOHandler is TIdSSLIOHandlerSocketBase then begin
    TIdSSLIOHandlerSocketBase(AContext.Connection.IOHandler).PassThrough :=
      not DoQuerySSLPort(AContext.Connection.Socket.Binding.Port);
  end;
  inherited DoConnect(AContext);

This is the code where DoQuerySSLPort calls the event and sets it's Result to True, therefor setting PassThrough.

 

When I then try to connect via http://... (as said earlier https:// works flawlessly!) the exception raised is

error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

The log from Postman is just

Error: socket hang up

 

The reply from curl is

*   Trying [fe80::64b3:3bf5:dfb6:3b7c]:8080...
* Connected to server (fe80::64b3:3bf5:dfb6:3b7c) port 8080
> GET / HTTP/1.1
> Host: server:8080
> User-Agent: curl/8.4.0
> Accept: */*
>
* Empty reply from server
* Closing connection
curl: (52) Empty reply from server

But what I would like to get is either a redirect to https or at least deliver some error message to the client to know what's wrong.

Edited by baka0815

Share this post


Link to post
Posted (edited)

For me is working, but I have the github version of Indy (I don't think this change something).

I think that the "socket" is still trying to use TLS for connection, but I'm not sure about that and I don't know how to help you.

Look this article of @Remy Lebeau to redirect the connection from "http" to "https": https://www.atozed.com/forums/thread-367-post-834.html#pid834

Edited by DelphiUdIT

Share this post


Link to post
13 hours ago, baka0815 said:

What I'm currently doing is to implement OnQuerySSLPort(APort: TIdPort; var VUseSSL: Boolean) ans set VUseSLL to True, so SSL/TLS is forced and connections without TLS are not possible.

That is not the correct way to handle this.

13 hours ago, baka0815 said:

How am I supposed to implement a redirect to the correct HTTPS-URL (or raise an error that TLS is required or something along those lines=?

You need to accept non-TLS connections on the HTTP port, and for any request that is received on that port, send an HTTP redirect response specifying the desired HTTPS port.  That way, the client can then retry the same HTTP request on the HTTPS port using TLS.

9 hours ago, DelphiUdIT said:

You must use the "TIdSSLIOHandlerSocketBase.PassThrough" property ... if you set it to FALSE then TLS is required, if you set to TRUE only clear connection (NO TLS) are managed.

You don't need to handle that manually in TIdHTTPServer.  Use the OnQuerySSLPort event instead, and let TIdHTTPServer handle the PassThrough for you.  Any port that OnQuerySSLPort returns VUseSSL=True for will use PassThrough=False, and vice versa.

1 hour ago, DelphiUdIT said:

Look this article of @Remy Lebeau to redirect the connection from "http" to "https": https://www.atozed.com/forums/thread-367-post-834.html#pid834

☝️☝️☝️ This is the way!

Share this post


Link to post

Thank you both for the latest information, that looks promising!

However I'm not using different ports, but maybe I will still figure something out.

Share this post


Link to post
40 minutes ago, baka0815 said:

However I'm not using different ports, but maybe I will still figure something out.

In the article that I signal  in the last post there are also some suggestions to use only one port ... like you need.

Share this post


Link to post
2 hours ago, baka0815 said:

However I'm not using different ports, but maybe I will still figure something out.

You should use different ports for HTTP and HTTPS.  While it is technically possible to handle both HTTP and HTTPS on a single port, it requires extra coding to peek the raw TCP data before the HTTP server processes it. It is usually not worth the effort unless you are dealing with network restrictions.

Share this post


Link to post

In my case it's configurable what the port should be and if SSL/TLS is active for that port.

Because of that I want to redirect incoming non-TLS requests to the TLS variant or at least send an error message that TLS is required.

 

I'll take a look at the post later and come back if I have additional questions. Thank you!

Share this post


Link to post

I'm using a TIdHTTPWebBrokerBridge and therefore assigning OnCommandGet (via TIdHTTPWebBrokerBridgeAccess) or OnCommandOther didn't do anything, those events never happen.

 

What works for me is assigning OnConnect as in the link posted and to check if it's a TLS handshake and therefore setting PassThrough.

In the OnAction-event of the WebModule-Actions I then check if I wanted to have a TLS connection and return a 400 statuscode with a message that encryption is required.

 

Is that a feasible way or am I holding it the wrong way up?

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×