Link servers SSL fingerprint validation

This forum is for everyone having trouble with linking two UnrealIRCd servers

Moderator: Supporters

Locked
HeXiLeD
Posts: 51
Joined: Mon Jan 16, 2017 8:07 pm
Location: online

Link servers SSL fingerprint validation

Post by HeXiLeD »

After addressing the Using Let's Encrypt with UnrealIRCd topic a few questions rose...

In regards to:
https://www.unrealircd.org/docs/Using_L ... validation

Correct me if i am wrong but fingerprint validation is it not more effective to prevent a man in the middle attack than just having a valid certificate. An attacker couple simply use another valid certificate to still do the man in the middle attack and the server linking would not know the difference. The server linking would only know that the certificate is as valid as any other valid certificate.
(This will not work with Let's Encrypt since certificates are renewed every 30-90 days)
Which is one of he pains of lets encrypt...

This leads me to the link block:
https://www.unrealircd.org/docs/Configu ... Link_block
https://www.unrealircd.org/docs/Tutoria ... ng_servers

In this example:

Code: Select all

link irc1.test.net {
[..]
    password "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF";
};
My main question is:
How does the server makes the distinction between what is a text password and the actual cryptography fingerprint ?

The question rises while I wonder how the servers know the difference in the following examples:

Real fingerprint example:

Code: Select all

password "00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF";
Text password looking like a fingerprint:

Code: Select all

password "00:XX:69:22:69:33:77::88:99:II:RR:OO:CC:KK:IT";
Is the method of verification done actually by reading the opposite server cryptography fingerprint when the server connects and matching it with what is set in the password field or just making that verification based on the fact that fingerprints are usually encoded into hexadecimal strings, non-truncated MD5 or SHA-* hashes.

Although not very important right now, two other things also come into mind in regards to this question: preimage attack & collision attack

There are also a couple details that could be enhanced in the link block but it will be addressed later.
Constructive criticism leads to evolution and progress. Negative criticism leads to obsolescence. We are not in the 90's IRC world anymore.
CertFP: d985d21f89fe2977b593c4d381a1a86802e62990d9328d893db76d59f9935244
Syzop
UnrealIRCd head coder
Posts: 2112
Joined: Sat Mar 06, 2004 8:57 pm
Location: .nl
Contact:

Re: Link servers SSL fingerprint validation & lets encrypt

Post by Syzop »

You ask how UnrealIRCd detects the password type (real password, fingerprint, etc). I could answer that but the source is a more neutral answer: https://github.com/unrealircd/unrealirc ... auth.c#L58
If you type something in the configuration file (link::password) that is not an SSL fingerprint then it is not considered an SSL fingerprint. If you do type an SSL fingerprint then yes it is only matched against the SSL fingerprint (and not some other password). Hope that clears things up. On a side note, you can also explicitly specify password ".." { sslclientcertfp; }; if you wish to force it for some reason.

What I'd like to see is that users will use "real" certificates. And if they use Let's Encrypt then they have no choice but to disable SSL fingerprint in password and use link::verify-certificate.

Not using link::verify-certificate or SSL fingerprints in passwords mean you are not verifying the certificate and then you are vulnerable to a MitM attack. More about this can be found in https://www.unrealircd.org/docs/Link_security
An attacker couple simply use another valid certificate to still do the man in the middle attack and the server linking would not know the difference. The server linking would only know that the certificate is as valid as any other valid certificate.
No, the name on the certificate must match. See link::verify-certificate.
PeGaSuS
Official supporter
Posts: 96
Joined: Tue Jun 27, 2017 4:42 pm
Contact:

Re: Link servers SSL fingerprint validation & lets encrypt

Post by PeGaSuS »

if I do understand things well, for the matter of server <-> server linking we could use the self signed certificate as it's almost impossible (for my little knowledge) to duplicate the certificate fingerprint (correct me if I'm wrong).
If that's correct we just need the listen block properly set with Let's Encrypt certificate and we're done.
Then, we can use a cronjob to use the 'renew-hook' to renew the certificate and then automatically rehash UnrealIRCd.
Worth to mention that we can run user commands as root using

Code: Select all

su user -c 'command goes here'
I do have a cronjob for Let's Encrypt that checks the IRC certificate every 15 days and it's the following

Code: Select all

0 0 */15 * * certbot -d irc.example.com --quiet --renew-hook "su -c unrealircd '/home/unrealircd/unrealircd/unrealircd rehash'" 
The above cronjob will only rehash the IRCd of the certificate was renewed. The "--quiet" option is to tell certbot to not wait for user input.
IRC Network: PTirc - GitHub: TehPeGaSuS - Help and support: #unreal-support
HeXiLeD
Posts: 51
Joined: Mon Jan 16, 2017 8:07 pm
Location: online

Re: Link servers SSL fingerprint validation & lets encrypt

Post by HeXiLeD »

I may have it some issues with these features or something is not working well in my setup.

In these examples I use different ssl certs for linking servers, other to link servers and other certs to allow connections and right now some of this is not working.

Unrealircd 4.0.13

The listen block:

Code: Select all

# https://unrealircd.org/docs/Listen_block

# ip
# Simply set ip to * (an asterisk) to bind to all available IP's on the machine,
# OR specify an IP to only bind to that IP address (this latter is usually required at shell providers).port

# This is the port you want to listen on, like 6667. You can also specify a port range, like 6667-6669.
# options block (optional)

# You can specify options for the port. Valid options are:

# ssl: TLS/SSL encrypted port
# clientsonly: port is only for clients
# serversonly: port is only for servers

# listen {
#        ip <ip>;
#        port <port>;
#       options {
#               <option>;
#               <option>;
#               ...
#       };
# };

# Servers links only

listen  {       ip      *;
                port    <some port>;

                options {       ssl;
                                serversonly;
                        };

                        ssl-options {   certificate     "ssl/links_listen.crt";
                                        key             "ssl/links_listen.key";
                                    };
        };
To generate certs (either manually or by cron job I use a script:)

Code: Select all

echo "This will generate self signed ssl certificates for this listen server block to accept links hubs/leafs";
echo "";
rm -r links_listen.key links_listen.crt
openssl req -x509 -nodes -days 1096 -utf8 -newkey rsa:4096-sha512 -keyout links_listen.key -out links_listen.crt -subj /CN=local_net_name
chmod 400 links_listen.key links_listen.crt
echo
echo "Add this fingerprint to password field sslclientcertfp of the remote server link block described at https://unrealircd.org/docs/Link_block for higher control";
echo "Example: password "08:02:D0:D8:AB:30..." { sslclientcertfp; }; and set verify-certificate no;"
echo
openssl x509 -in links_listen.crt -sha256 -noout -fingerprint
The link block:

Code: Select all

# https://unrealircd.org/docs/Link_block
# https://unrealircd.org/docs/Tutorial:_Linking_servers
# https://unrealircd.org/docs/Authentication_types
# https://www.unrealircd.org/docs/Troubleshooting:_linking_servers
# https://www.unrealircd.org/docs/Link_security

# If you are linking servers we recommend you to follow our Tutorial: Linking servers instead.
# The link block is, however, shown below for reference.

# link <server-name> {
#    /* Below, often you will have both an incoming { } and outcoming { } sub-block.
#     * However you may also choose to have only 1 of them if you always link in the same direction.
#     */
#    incoming {
#        mask 1.2.3.*;
#    };
#    outgoing {
#        bind-ip <ip-to-bind-to>; /* optional now */
#        hostname irc1.some.net; /* may also be an IP */
#        port 6697; /* or move the hostname & ip into one item ? irc1.some.net:6697 */
#        options { ssl; autoconnect; }; /* optional, but recommended */
#    };
#    password "some-password"; /* either a plaintext password that's the same for both sides or an SSL fingerprint (or certificate) */
#    password "E7:4D:46:F1:9F:F4:68:F5:E8:E3:49:CC:28:5D:F9:65:85:BA:4F:16:B6:49:02:E3:34:E6:E7:6A:FE:76:A7:98" { sslclientcertfp; };
#    verify-certificate [yes|no]; /* optional, default is 'no' but is less secure */
#    hub <hub-mask>; /* optional */
#    leaf <leaf-mask>; /* optional */
#    leaf-depth <depth>; /* optional */
#    class <class-name>;
#    ciphers <ssl-ciphers>; /* optional */
#    options {
#        quarantine; /* is a generic option. optional. */
#    };
# };

link    remote.server.name {
#                               password  "18:AC:75:AA:2B:48:35:23:CF:A2:68:4F:2D:9D:E6:33:06:C4:3F:32:AF:37:B5:49:7A:4D:C5:02:5F:B1:EE:09" { sslclientcertfp; };
# Resuls in:                    Link denied (Authentication failed [Bad password?])
#
#                               password "18:AC:75:AA:2B:48:35:23:CF:A2:68:4F:2D:9D:E6:33:06:C4:3F:32:AF:37:B5:49:7A:4D:C5:02:5F:B1:EE:09";
# SHA256 Resuls in:             Link denied (Authentication failed [Bad password?])

# SHA1  Resuls in: 
                                #password "36:EA:DC:1C:C5:44:5C:57:74:60:B4:0F:40:DB:64:7D:55:7A:E7:3B";
                                #passwords length may not exceed 48

                                #password "36:EA:DC:1C:C5:44:5C:57:74:60:B4:0F:40:DB:64:7D:55:7A:E7:3B" { sslclientcertfp; };
                                # loads with no problems but Link denied (Authentication failed [Bad password?])

                               password "1234567890"; # works

                                #verify-certificate     no; # unreal *.14 and up
                                class                   servers;
                                #hub                    *;
                                leaf                    *;

                                incoming {      mask            *; };

                                outgoing {      bind-ip         *;
                                                hostname       some.remote.address;
                                                port            some-port;

                                        options {       ssl;
                                                        #autoconnect;
                                                };

                                        ssl-options {   ciphers         ECDHE-RSA-AES256-GCM-SHA384;
                                                        protocols       TLSv1.2;
                                                    };
                                         };
                           };
Problem:
As described in the link block conf, the usage of certificate fingerprints is not working. I am only able to link if using a text password set equal on both servers. I am also not able to link if i set a password equal on both servers that look like a hexadecimal fingerprint just to test.

Note that the remote link exchanges certificate fingerprints as required.

I have tested this between two servers while one only reloaded and rehash and the test server restarted on every change.
Constructive criticism leads to evolution and progress. Negative criticism leads to obsolescence. We are not in the 90's IRC world anymore.
CertFP: d985d21f89fe2977b593c4d381a1a86802e62990d9328d893db76d59f9935244
PeGaSuS
Official supporter
Posts: 96
Joined: Tue Jun 27, 2017 4:42 pm
Contact:

Re: Link servers SSL fingerprint validation & lets encrypt

Post by PeGaSuS »

using

Code: Select all

openssl x509 -sha256 -fingerprint -noout -in server.cert.pem
worked fine with me thought.
but your syntax is

Code: Select all

openssl x509 -in links_listen.crt -sha256 -noout -fingerprint
Could be that? The command I'm using is provided by UnrealIRCd on https://www.unrealircd.org/docs/Tutoria ... ng_servers
Note that I don't really know if the order of things matters
IRC Network: PTirc - GitHub: TehPeGaSuS - Help and support: #unreal-support
Syzop
UnrealIRCd head coder
Posts: 2112
Joined: Sat Mar 06, 2004 8:57 pm
Location: .nl
Contact:

Re: Link servers SSL fingerprint validation & lets encrypt

Post by Syzop »

HeXiLeD, you have to authenticate both sides:
So if on server1 you have a link block to server2 with autoconnect then it should connect to server2 on <port> and the SSL certificate of server2 on <port> should match the link::password specified in server1 conf. Similarly, the link::outgoing::ssl-options::certificate (and key) on server1 regarding server2 should match the link::password on server2 regarding server1.
Ok this is quickly becoming confusing, but you hopefully get the idea. I'm off to bed :D
PeGaSuS
Official supporter
Posts: 96
Joined: Tue Jun 27, 2017 4:42 pm
Contact:

Re: Link servers SSL fingerprint validation & lets encrypt

Post by PeGaSuS »

Basically, SSL certfp of server1 on link block of server2 and SSL certfp of server2 on link block of server1.

Code: Select all

/* Server 1 */
link server2 {
...
password "certfp of server2";
...
};
######
/* Server 2 */
link server1 {
...
password "certfp of server1";
...
};
Last edited by PeGaSuS on Fri Sep 08, 2017 7:00 pm, edited 1 time in total.
IRC Network: PTirc - GitHub: TehPeGaSuS - Help and support: #unreal-support
HeXiLeD
Posts: 51
Joined: Mon Jan 16, 2017 8:07 pm
Location: online

Re: Link servers SSL fingerprint validation & lets encrypt

Post by HeXiLeD »

The syntax of openssl in this case is irrelevant.

@ Syzop you are correct.
* On server one I have the link block with the ssl cert fingerprint of server 2
* On server two I have the link block with the ssl cert fingerprint of server 1

When server 1 receives connection, it should read the fingerprint of server 2 and match it with what is has on it's link block
When server 2 receives connection, it should read the fingerprint of server 1 and match it with what is has on it's link block

This is basically what is specified here: https://www.unrealircd.org/docs/Tutoria ... realIRCd_4

Result: Link denied (Authentication failed [Bad password?])

ssl-options in link block and listen block match as you stated.
Constructive criticism leads to evolution and progress. Negative criticism leads to obsolescence. We are not in the 90's IRC world anymore.
CertFP: d985d21f89fe2977b593c4d381a1a86802e62990d9328d893db76d59f9935244
Syzop
UnrealIRCd head coder
Posts: 2112
Joined: Sat Mar 06, 2004 8:57 pm
Location: .nl
Contact:

Re: Link servers SSL fingerprint validation & lets encrypt

Post by Syzop »

Could you show the following for both servers:
* set::ssl block (if any)
* listen blocks
* link block to the other server
Without censoring of the link::outgoing::port, censoring IP is fine.

Or email me at [email protected] if you don't want it in public (in that case maybe do show me the IP).

Just for what it's worth: I do know SSL fingerprints are working fine in 4.0.13. Several people use it, including myself on two networks. So it's probably something obvious somewhere.. :)
HeXiLeD
Posts: 51
Joined: Mon Jan 16, 2017 8:07 pm
Location: online

Re: Link servers SSL fingerprint validation & lets encrypt

Post by HeXiLeD »

As I was preparing the requested reply I went over configs and configs and eventually found out the problem while re-doing configs form scratch and deciding to test other stuff.

The listen blocks are set like in this example:
servers listen links block only
https://www.unrealircd.org/docs/Configu ... sten_block

Code: Select all

listen  {       ip      *;
                port    1234;

                options {       ssl;
                                serversonly;
                        };
                        ssl-options { certificate     "ssl/links_listen.crt";
                                       key            "ssl/links_listen.key";
                                    };
        };
Nothing wrong with the links blocks. The certs are served as per port specification and confirmed from the wan side with:
openssl s_client -connect ip:1234 < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin -sha256
The link block however was where the issue was:
https://www.unrealircd.org/docs/Configu ... Link_block

Code: Select all

ssl-options {  ciphers         ECDHE-RSA-AES256-GCM-SHA384;
               protocols       TLSv1.2;
};


While it should have been:

Code: Select all

ssl-options {  ciphers         ECDHE-RSA-AES256-GCM-SHA384;
               protocols       TLSv1.2;
               certificate     "ssl/links_listen.crt"; 
               key             "ssl/links_listen.key";
};
In order to instruct the link to use such specific certificates.

So what caused the problem ? The RTFM caused it. There is no information in the wiki in regards to this detail. All my configs always have matching wiki/docs url references.

No syntax examples here: https://www.unrealircd.org/docs/Tutoria ... ng_servers
No syntax examples here: https://www.unrealircd.org/docs/Configu ... Link_block
No syntax examples here: https://www.unrealircd.org/docs/Link_security
No syntax examples here: https://unrealircd.org/docs/Authentication_types
No syntax examples here: https://www.unrealircd.org/docs/Trouble ... ng_servers

.. and there is also no reference to such additional options. for such configuration explaining that the use of sslclientcertfp needs to be matched with key and path certificate in ssl-options.

The only closest reference done on the wiki in regards to load specific certificates is done for
https://www.unrealircd.org/docs/Set_blo ... ertificate which is a different setup way to vague to be related to link blocks.

Was there ever any documentation with these specifics ?
Not even on the bug tracker where the problem was mentioned: https://bugs.unrealircd.org/view.php?id=4679

RTFM.... I wasted hours. hours... around this....

Anyway... thank you for your attention.
Constructive criticism leads to evolution and progress. Negative criticism leads to obsolescence. We are not in the 90's IRC world anymore.
CertFP: d985d21f89fe2977b593c4d381a1a86802e62990d9328d893db76d59f9935244
Syzop
UnrealIRCd head coder
Posts: 2112
Joined: Sat Mar 06, 2004 8:57 pm
Location: .nl
Contact:

Re: Link servers SSL fingerprint validation & lets encrypt

Post by Syzop »

First of all, I can fully understand how frustrating it can be if something doesn't work after hours of trying. I know the feeling (from other software).

The default certificate/key is specified via set::ssl::certificate / key. You can override these in listen::ssl-options and link::outgoing::ssl-options if you wish. How could UnrealIRCd know you want to use ssl/links_listen.crt&.key in your link { } block if you don't specify them in your link { } block? (Nor use it as the default certificate in the set { } block)

Also, from what I gather you are using the same certificate and key on both servers. That is kinda unusual and less secure, but possible.
As you can see in the Tutorial: Linking servers you normally would use one certificate on one side, and the other one on the other side. Perhaps you already know this and were just testing quickly, but I have to mention it here in case anyone reads it :)

I've updated the thread title since it's almost exclusively about SSL fingerprints.
Syzop
UnrealIRCd head coder
Posts: 2112
Joined: Sat Mar 06, 2004 8:57 pm
Location: .nl
Contact:

Re: Link servers SSL fingerprint validation

Post by Syzop »

Actually come to think of it, this should go in the "Linking servers" section :)
Locked