#!/usr/bin/env python3 # # InspIRCd -- Internet Relay Chat Daemon # # Copyright (C) 2024 Sadie Powell # # This file is part of InspIRCd. InspIRCd is free software: you can # redistribute it and/or modify it under the terms of the GNU General Public # License as published by the Free Software Foundation, version 2. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # import os import re import socket import ssl import sys import textwrap CC_BOLD = "\x1B[1m" if sys.stdout.isatty() else "" CC_RESET = "\x1B[0m" if sys.stdout.isatty() else "" CC_GREEN = "\x1B[1;32m" if sys.stdout.isatty() else "" CC_RED = "\x1B[1;31m" if sys.stdout.isatty() else "" if len(sys.argv) < 3: program = os.path.basename(__file__) print(f"Usage: {program} [selfsigned]", file=sys.stderr) sys.exit(1) hostip = sys.argv[1] if re.match(r"[^A-Za-z0-9.:-]", hostip): print(f"Error: invalid hostname or IP address: {hostip}", file=sys.stderr) sys.exit(1) port = sys.argv[2] if not port.isnumeric() or int(port) < 1 or int(port) > 65535: print(f"Error: invalid TCP port: {port}", file=sys.stderr) sys.exit(1) self_signed = len(sys.argv) > 3 and sys.argv[3] == "selfsigned" try: print(f"Checking whether {CC_BOLD}{hostip}/{port}{CC_RESET} is reachable ... ", end="", flush=True) sock = socket.create_connection((hostip, int(port)), 30) print(f"{CC_GREEN}yes{CC_RESET}") except socket.error as error: print(textwrap.dedent(f""" {CC_RED}no{CC_RESET} It seems like the server endpoint you specified is not reachable! Make sure that: * You have specified a tag in your config for this endpoint. * You have rehashed or restarted the server since adding the tag. * If you are using a firewall incoming connections on TCP port {port} are allowed. * The endpoint your server is listening on is not local or private. The error provided by the socket library was: {error} See https://docs.inspircd.org/4/configuration/#bind for more information. """).strip()) sys.exit(1) data = b"" try: print(f"Checking whether {CC_BOLD}{hostip}/{port}{CC_RESET} is using plaintext ... ", end="", flush=True) sock.settimeout(5) data = sock.recv(1, socket.MSG_PEEK) except socket.timeout: pass # The server is probably using deferred sockets except socket.error as error: print(textwrap.dedent(f""" {CC_RED}error{CC_RESET} It seems like the server dropped the connection before sending anything! Make sure that: * The endpoint you specified is actually your IRC server. * If you are using a firewall incoming data on TCP port {port} are allowed. * The IP address you are connecting from has not been banned from the server. The error provided by the socket library was: {error} See https://docs.inspircd.org/4/configuration/#bind for more information. """).strip()) sys.exit(1) if re.match(br"[A-Z:@]", data): print(textwrap.dedent(f""" {CC_RED}yes{CC_RESET} It appears that the server endpoint is using plaintext! Make sure that: * You have one or more of the following modules loaded: - ssl_gnutls - ssl_openssl * The value of is the same as an field. * The value of for your used TLS profile is set to "gnutls" if using the ssl_gnutls module or "openssl" if using the ssl_openssl module. * If you have your TLS configuration in a file other than inspircd.conf then that file is included by inspircd.conf. See the following links for more information: https://docs.inspircd.org/4/modules/ssl_gnutls/#configuration https://docs.inspircd.org/4/modules/ssl_openssl/#configuration """).strip()) sys.exit(0) try: print(f"{CC_GREEN}no{CC_RESET}") print(f"Checking whether {CC_BOLD}{hostip}/{port}{CC_RESET} can have an TLS session negotiated ... ", end="", flush=True) context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) context.check_hostname = not self_signed context.verify_mode = ssl.CERT_NONE if self_signed else ssl.CERT_REQUIRED context.load_default_certs() context.wrap_socket(sock, server_hostname=hostip) except ssl.SSLError as error: print(textwrap.dedent( f""" {CC_RED}no{CC_RESET} It appears that something is wrong with your server. Make sure that: * You are not using an old version of GnuTLS or OpenSSL which only supports deprecated algorithms like SSLv3. * If you are using a self-signed certificate (not recommended) that you passed the `selfsigned` argument to this script. The error provided by the TLS library was: {error} """).strip()) sys.exit(0) print(textwrap.dedent(f""" {CC_GREEN}yes{CC_RESET} It seems like TLS is working fine on your server. If you are having trouble connecting try using a different client or connecting from a different host. You may also find running some of the following commands to be helpful: gnutls-cli-debug --port {port} {hostip} openssl s_client -connect {hostip}:{port} -debug -security_debug If you need any help working out what is wrong then visit our support channel at ircs://irc.teranova.net/inspircd. """).strip())