karlheyes / icecast-kh

KH branch of icecast
GNU General Public License v2.0
298 stars 106 forks source link

Cannot connect source over SSL #290

Open mlsomers opened 4 years ago

mlsomers commented 4 years ago

I have in my configuration (IP address changed to 4.3.2.1):

<listen-socket>
  <port>1234</port>
  <ssl>1</ssl>
  <bind-address>4.3.2.1</bind-address>
</listen-socket>

I can view the admin pages correctly and the secure lock in the browser is good. However when I try to connect to the server using Rocket Broadcaster Pro (which claims to support SSL with IceCast), it fails to connect.

The log (at level 4) gives this info:

[2020-04-12  02:26:11] DBUG connection/connection_uses_ssl Detected SSL on connection from 1.2.3.4
[2020-04-12  02:26:11] DBUG client/worker_add_pending_clients Added 1 pending clients to 00000000004a49d0
[2020-04-12  02:26:11] DBUG client/worker 00000000004a49d0 now has 1 clients
[2020-04-12  02:26:11] DBUG stats/stats_global_calc update global clients (1)
[2020-04-12  02:26:11] DBUG stats/stats_global_calc update global connections (44)
[2020-04-12  02:26:12] DBUG stats/stats_global_calc update global client_connections (40)
[2020-04-12  02:26:14] DBUG client/client_read_bytes reading from connection 43 from 1.2.3.4 has failed
[2020-04-12  02:26:14] DBUG client/worker 00000000004a49d0 now has 0 clients

As a workaround I can add a 2nd port without SSL for the source like this:

<listen-socket>
  <port>1235</port>
  <ssl>0</ssl>
  <bind-address>4.3.2.1</bind-address>
</listen-socket>

In that case the public facing part still works with ssl, but I would far rather use ssl for the source as well. Unfortunately the source does not have a fixed IP address, otherwise I would be able to protect the specific port with the firewall. This way it is too easy to hijack.

Any Idea why the log says "client/client_read_bytes reading from connection 43 from 1.2.3.4 has failed" ?

These are the client logs (from Rocket Broadcaster):

2020-04-12T02:26:12 Stream diagnostic for [name] started...
2020-04-12T02:26:12 [name]: Connecting
2020-04-12T02:26:15 [name]: Connection Refused
2020-04-12T02:26:17 Stream diagnostic for [name] failed.
2020-04-12T02:26:17 [name]: Disconnected
mlsomers commented 4 years ago

I looked into the source and found this:

/* helper function for reading data from a client */
int client_read_bytes (client_t *client, void *buf, unsigned len)
{
    int (*con_read)(struct connection_tag *handle, void *buf, size_t len) = connection_read;
    int bytes;

    if (len == 0)
        return 0;
    if (client->refbuf && client->pos < client->refbuf->len)
    {
        unsigned remaining = client->refbuf->len - client->pos;
        if (remaining > len)
            remaining = len;
        memcpy (buf, client->refbuf->data + client->pos, remaining);
        client->pos += remaining;
        if (client->pos >= client->refbuf->len)
            client_set_queue (client, NULL);
        return remaining;
    }
#ifdef HAVE_OPENSSL
    if (client->connection.ssl)
        con_read = connection_read_ssl;
#endif
    bytes = con_read (&client->connection, buf, len);

    if (bytes == -1 && client->connection.error)
        DEBUG2 ("reading from connection %"PRIu64 " from %s has failed", client->connection.id, &client->connection.ip[0]);

    return bytes;
}

So I'm wondering, was the build at https://karlheyes.github.io/ built with the HAVE_OPENSSL compiler directive? This one: 2.4.0-kh13 (win64)

I tried to build it myself in VisualStudio 2019 but after getting the latest version of all dependencies using NuGet, I'm left with 1468 errors when trying to compile... Maybe I should not have taken the latest versions?

Any way, replacing DEBUG2 with at least WARN2 would be a little helpful, wish I could put a break-point somewhere before to find out why client->connection.error is true, the reason does not seem to be logged currently :-( Anyone got a branch that is working in VisualStudio?

karlheyes commented 4 years ago

Firstly, you don't need the tag now, it's autodetected. The Windows builds that I do (mingw) have ssl enabled, in fact the ssl is detected as per your log. As you don't get other debug entries relating to the reading then the codes coming back from the ssl indicate that it's communicating lowlevel stuff until the socket gets closed by, I presume, the source. It has the hallmarks of a SSL cert issue (something not specified as expected) but invariably icecast does not get that much info from the lib on this.

The fact that browsers are ok make me wonder what is wrong, I would try curl as well to at least verify it eg curl -X SOURCE 'http://source:pw@4.3.2.1:1234/my stream' should get you past the first stage and timeout with no data. I can check again at the flow control as it may be tripping over a difference in api use.

I did use VS ages ago, but got annoyed with it, there's is no reason really for it not to build but will probably need a bunch of #defines to make sure different parts are enabled.

karl

mlsomers commented 4 years ago

Thanks for your reply!

I don't want to give up on getting it to compile in VS. Would you have a list of all #defines and their default values (defined or not)? Even if it's just a screenshot? I don't feel like a long trial-and-error session :-)

I tried the windows version of curl, but it seems to be different than the original versions. Did not get any farther than "Could not resolve host: 'https".

Using the Fiddler proxy I see that the same results except for the "reading from connection has failed" line. It just silently stops with "client/worker .... now has 0 clients". In fiddler the tunnel is established, but no traffic is going through at all, so I guess it may be a client problem after all (the client should at least try to send something through the established tunnel).

Nevertheless I still want to get it working in VS, even if it is only for building a "Profile Guided Optimized" version for my use-case.

karlheyes commented 4 years ago

You are welcome to try building it. The config.h.in will give you a template of the usual #defines to use in config.h The key build plan will be to define HAVE_CONFIG_H for all sources then config.h contains the defines to use as code switches. The win32 directory (yes it is misnamed) contains some windows specifics routines like service handling. Most of the config.h is for headers or functions defines but some deal with things like enabling openssl and curl. The annoying issue with those libs is bulding packages so you can use them. They tend to have varying build methods and options, which is why I ended up using mingw in the end.

karl