Interestingly, I found that using the ca_info_file instead of the ca_file attribute makes it work fine. On Thu, Sep 4, 2025 at 10:20 PM Murali Krishnamoorthy <hibkmurali@gmail.com> wrote:
On Thu, Sep 4, 2025 at 11:55 AM Alan DeKok <alan.dekok@inkbridge.io> wrote:
On Sep 4, 2025, at 2:42 PM, Murali Krishnamoorthy <hibkmurali@gmail.com> wrote:
*(0) rest_auth_failure_log: ERROR: Request failed: 60 - SSL peer certificate or SSH remote key was not OK*
Hmm... unfortunately, that error is coming from curl. The REST module just uses the curl APIs to do the bulk of the work.
i.e. error 60 is the Curl error for when it cannot verify the certificate of the REST server.
Is there any external command I could use to verify what freeradius rest module is doing to get better debug?
I don't think there's any additional debugging you could see on the FreeRADIUS side. It just gets passes the data to Curl, and Curl returns "error 60". In order to enable more Curl debugging, you would have to edit rlm_rest, to add more Curl API calls.
Another possibility is that FreeRADIUS and the local "curl" command are using different versions of OpenSSL.
But in the end, FreeRADIUS passes data to Curl, and Curl returns error 60. The only solution here is to pass the right data into Curl.
We've used rlm_rest in many places, and have never run into this issue. So it looks like a local configuration problem.
I rechecked by using the same curl/openssl versions as the rlm_rest. It worked fine.
I edited rest.c to log info on the ssl cert file options we are setting in libcurl and enabled debug on libcurl. I see that, although we set ca_file to "/etc/certs/craas-ca.pem" and is also parsed correctly, libcurl is somehow using "/etc/ssl/certs.pem" instead and so cannot find the ca file. This feels like a bug. Full logs below.
FreeRADIUS Version 3.2.9 Copyright (C) 1999-2025 The FreeRADIUS server project and contributors There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE You may redistribute copies of FreeRADIUS under the terms of the GNU General Public License For more information about these matters, see the file named COPYRIGHT
FreeRADIUS is developed, maintained, and supported by InkBridge Networks. For commercial support, please email sales@inkbridgenetworks.com https://inkbridgenetworks.com/ Starting - reading configuration files ... including dictionary file /opt/share/freeradius/dictionary including dictionary file /opt/share/freeradius/dictionary.dhcp including dictionary file /opt/share/freeradius/dictionary.vqp including configuration file /opt/etc/raddb/radiusd.conf including configuration file /opt/etc/raddb/clients.conf including files in directory /opt/etc/raddb/mods-enabled/ including configuration file /opt/etc/raddb/mods-enabled/preprocess including configuration file /opt/etc/raddb/mods-enabled/pap including configuration file /opt/etc/raddb/mods-enabled/files including configuration file /opt/etc/raddb/mods-enabled/rest including configuration file /opt/etc/raddb/mods-enabled/realm including files in directory /opt/etc/raddb/sites-enabled/ including configuration file /opt/etc/raddb/sites-enabled/default main { security { allow_core_dumps = no } name = "radiusd" prefix = "/usr/local" localstatedir = "/usr/local/var" logdir = "/usr/local/var/log" run_dir = "/usr/local/var/run/radiusd" } main { name = "radiusd" prefix = "/usr/local" localstatedir = "/usr/local/var" sbindir = "/usr/local/sbin" logdir = "/usr/local/var/log" run_dir = "/usr/local/var/run/radiusd" libdir = "/usr/local/lib" radacctdir = "/usr/local/var/log/radacct" hostname_lookups = no max_request_time = 30 proxy_dedup_window = 1 cleanup_delay = 5 max_requests = 256 max_fds = 512 postauth_client_lost = no pidfile = "/usr/local/var/run/radiusd/radiusd.pid" checkrad = "/usr/local/sbin/checkrad" debug_level = 0 proxy_requests = yes log { stripped_names = no auth = no auth_badpass = no auth_goodpass = no msg_denied = "You are already logged in - access denied" } resources { } security { max_attributes = 0 reject_delay = 0.000000 delay_proxy_rejects = no status_server = no require_message_authenticator = "auto" limit_proxy_state = "auto" allow_vulnerable_openssl = "no" } unlang { group_stop_return = no policy_stop_return = no } } radiusd: #### Loading Realms and Home Servers #### radiusd: #### Loading Clients #### client radtest { ipaddr = 0.0.0.0/0 secret = <<< secret >>> proto = "*" limit { max_connections = 16 lifetime = 0 idle_timeout = 30 } } Shared secret for client radtest is short, and likely can be broken by an attacker. Found debugger attached Configuration version: e39d-75aa-fdaa-463e # Creating Auth-Type = PAP radiusd: #### Instantiating modules #### modules { # Loaded module rlm_preprocess # Loading module "preprocess" from file /opt/etc/raddb/mods-enabled/preprocess preprocess { with_ascend_hack = no ascend_channels_per_line = 23 with_ntdomain_hack = no with_specialix_jetstream_hack = no with_cisco_vsa_hack = no with_alvarion_vsa_hack = no } # Loaded module rlm_pap # Loading module "pap" from file /opt/etc/raddb/mods-enabled/pap pap { normalise = yes } # Loaded module rlm_files # Loading module "files" from file /opt/etc/raddb/mods-enabled/files files { usersfile = "/opt/etc/raddb/users" } # Loaded module rlm_rest # Loading module "rest" from file /opt/etc/raddb/mods-enabled/rest rest { connect_timeout = 4.000000 http_negotiation = "default" } # Loaded module rlm_realm # Loading module "IPASS" from file /opt/etc/raddb/mods-enabled/realm realm IPASS { format = "prefix" delimiter = "/" ignore_default = no ignore_null = no } # Loading module "suffix" from file /opt/etc/raddb/mods-enabled/realm realm suffix { format = "suffix" delimiter = "@" ignore_default = no ignore_null = no } # Loading module "bangpath" from file /opt/etc/raddb/mods-enabled/realm realm bangpath { format = "prefix" delimiter = "!" ignore_default = no ignore_null = no } # Loading module "realmpercent" from file /opt/etc/raddb/mods-enabled/realm realm realmpercent { format = "suffix" delimiter = "%" ignore_default = no ignore_null = no } # Loading module "ntdomain" from file /opt/etc/raddb/mods-enabled/realm realm ntdomain { format = "prefix" delimiter = "\" ignore_default = no ignore_null = no } # Instantiating module "preprocess" from file /opt/etc/raddb/mods-enabled/preprocess # Instantiating module "pap" from file /opt/etc/raddb/mods-enabled/pap # Instantiating module "files" from file /opt/etc/raddb/mods-enabled/files reading pairlist file /opt/etc/raddb/users # Instantiating module "rest" from file /opt/etc/raddb/mods-enabled/rest post-auth { uri = "https://auth.feature-devops.qa.xcloudiq.com:8443/auth/log-event " method = "post" body = "json" attr_num = no raw_value = no data = "{"Auth-Result": "FAILURE", "Message":"%{Reply-Message}", "User-Name": "%{User-Name}", "NAS-Identifier": "%{NAS-Identifier}", "NAS-Port-Type": "%{NAS-Port-Type}", "NAS-IP-Address": "%{NAS-IP-Address}", "NAS-Port": "%{NAS-Port}", "NAS-Port-Id": "%{NAS-Port-Id}", "Called-Station-Id": "%{Called-Station-Id}", "Calling-Station-Id": "%{Calling-Station-Id}", "EAP-Message": "%{EAP-Message}"}" auth = "none" require_auth = no timeout = 4.000000 chunk = 0 tls {
* ca_file = "/etc/certs/craas-ca.pem" certificate_file = "/etc/certs/client.pem" private_key_file = "/etc/certs/client.key"* check_cert = yes check_cert_cn = yes } body_uri_encode = yes } rlm_rest: libcurl version: libcurl/8.12.1 OpenSSL/3.3.4 zlib/1.3.1 brotli/1.1.0 zstd/1.5.6 c-ares/1.34.5 libidn2/2.3.7 libpsl/0.21.5 nghttp2/1.64.0 rlm_rest (rest): Initialising connection pool pool { start = 5 min = 5 max = 10 spare = 3 uses = 0 lifetime = 0 cleanup_interval = 30 idle_timeout = 60 retry_delay = 1 max_retries = 5 spread = no } rlm_rest (rest): Opening additional connection (0), 1 of 10 pending slots used rlm_rest (rest): Skipping pre-connect, connect_uri not specified rlm_rest (rest): Opening additional connection (1), 1 of 9 pending slots used rlm_rest (rest): Skipping pre-connect, connect_uri not specified rlm_rest (rest): Opening additional connection (2), 1 of 8 pending slots used rlm_rest (rest): Skipping pre-connect, connect_uri not specified rlm_rest (rest): Opening additional connection (3), 1 of 7 pending slots used rlm_rest (rest): Skipping pre-connect, connect_uri not specified rlm_rest (rest): Opening additional connection (4), 1 of 6 pending slots used rlm_rest (rest): Skipping pre-connect, connect_uri not specified # Instantiating module "IPASS" from file /opt/etc/raddb/mods-enabled/realm # Instantiating module "suffix" from file /opt/etc/raddb/mods-enabled/realm # Instantiating module "bangpath" from file /opt/etc/raddb/mods-enabled/realm # Instantiating module "realmpercent" from file /opt/etc/raddb/mods-enabled/realm # Instantiating module "ntdomain" from file /opt/etc/raddb/mods-enabled/realm } # modules radiusd: #### Loading Virtual Servers #### server { # from file /opt/etc/raddb/radiusd.conf } # server server default { # from file /opt/etc/raddb/sites-enabled/default # Loading authenticate {...} Compiling Auth-Type PAP for attr Auth-Type # Loading authorize {...} # Loading preacct {...} # Loading post-auth {...} Compiling Post-Auth-Type REJECT for attr Post-Auth-Type } # server default radiusd: #### Opening IP addresses and Ports #### listen { type = "auth" ipaddr = * port = 1812 } listen { type = "acct" ipaddr = * port = 1813 } Listening on auth address * port 1812 bound to server default Listening on acct address * port 1813 bound to server default Ready to process requests
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! BlastRADIUS check: Received packet with Message-Authenticator. Setting "require_message_authenticator = true" for client radtest
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! It looks like the client has been updated to protect from the BlastRADIUS attack. Please set "require_message_authenticator = true" for client radtest
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! (0) Received Access-Request Id 145 from 172.25.0.2:52483 to 172.25.0.20:1812 length 78 (0) Message-Authenticator = 0x9aed201100840d25636141144c32327d (0) User-Name = "testuser" (0) User-Password = "password123" (0) NAS-IP-Address = 172.25.0.2 (0) NAS-Port = 0 (0) # Executing section authorize from file /opt/etc/raddb/sites-enabled/default (0) authorize { (0) [preprocess] = ok (0) suffix: Checking for suffix after "@" (0) suffix: No '@' in User-Name = "testuser", looking up realm NULL (0) suffix: No such realm "NULL" (0) [suffix] = noop (0) pap: WARNING: No "known good" password found for the user. Not setting Auth-Type (0) pap: WARNING: Authentication will fail unless a "known good" password is available (0) [pap] = noop (0) } # authorize = ok (0) ERROR: No Auth-Type found: rejecting the user via Post-Auth-Type = Reject (0) Failed to authenticate the user (0) Using Post-Auth-Type Reject (0) # Executing group from file /opt/etc/raddb/sites-enabled/default (0) Post-Auth-Type REJECT { rlm_rest (rest): Reserved connection (0) (0) rest: Expanding URI components (0) rest: EXPAND https://auth.feature-devops.qa.xcloudiq.com:8443 (0) rest: --> https://auth.feature-devops.qa.xcloudiq.com:8443 (0) rest: EXPAND /auth/log-event (0) rest: --> /auth/log-event (0) rest: Sending HTTP POST to " https://auth.feature-devops.qa.xcloudiq.com:8443/auth/log-event"
*(0) rest: Setting CURLOPT_SSLCERT to '/etc/certs/client.pem'(0) rest: Setting CURLOPT_SSLKEY to '/etc/certs/client.key'(0) rest: Setting CURLOPT_ISSUERCERT to '/etc/certs/craas-ca.pem'* (0) rest: EXPAND {"Auth-Result": "FAILURE", "Message":"%{Reply-Message}", "User-Name": "%{User-Name}", "NAS-Identifier": "%{NAS-Identifier}", "NAS-Port-Type": "%{NAS-Port-Type}", "NAS-IP-Address": "%{NAS-IP-Address}", "NAS-Port": "%{NAS-Port}", "NAS-Port-Id": "%{NAS-Port-Id}", "Called-Station-Id": "%{Called-Station-Id}", "Calling-Station-Id": "%{Calling-Station-Id}", "EAP-Message": "%{EAP-Message}"} (0) rest: --> {"Auth-Result": "FAILURE", "Message":"", "User-Name": "testuser", "NAS-Identifier": "", "NAS-Port-Type": "", "NAS-IP-Address": "172.25.0.2", "NAS-Port": "0", "NAS-Port-Id": "", "Called-Station-Id": "", "Calling-Station-Id": "", "EAP-Message": ""} (0) rest: From rest_request_perform(): (0) rest: CURLOPT_SSLCERT(tls_certificate_file): /etc/certs/client.pem (0) rest: CURLOPT_SSLKEY(tls_private_key_file): /etc/certs/client.key (0) rest: CURLOPT_ISSUERCERT(tls_ca_file): /etc/certs/craas-ca.pem rlm_rest: libcurl: Host auth.feature-devops.qa.xcloudiq.com:8443 was resolved. rlm_rest: libcurl: IPv6: (none) rlm_rest: libcurl: IPv4: 3.150.3.32, 3.19.113.11 rlm_rest: libcurl: Trying 3.150.3.32:8443... rlm_rest: libcurl: ALPN: curl offers h2,http/1.1 rlm_rest: libcurl: TLSv1.3 (OUT), TLS handshake, Client hello (1): *rlm_rest: libcurl: CAfile: /etc/ssl/cert.pem * rlm_rest: libcurl: CApath: /etc/ssl/certs rlm_rest: libcurl: TLSv1.3 (IN), TLS handshake, Server hello (2): rlm_rest: libcurl: TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8): rlm_rest: libcurl: TLSv1.3 (IN), TLS handshake, Request CERT (13): rlm_rest: libcurl: TLSv1.3 (IN), TLS handshake, Certificate (11): rlm_rest: libcurl: TLSv1.3 (OUT), TLS alert, unknown CA (560): *rlm_rest: libcurl: SSL certificate problem: unable to get local issuer certificate * rlm_rest: libcurl: closing connection #0 (0) rest: ERROR: Request failed: 60 - SSL peer certificate or SSH remote key was not OK (0) rest: ERROR: Server returned no data rlm_rest (rest): Released connection (0) (0) [rest] = fail (0) } # Post-Auth-Type REJECT = fail (0) Sent Access-Reject Id 145 from 172.25.0.20:1812 to 172.25.0.2:52483 length 38 (0) Finished request Waking up in 4.9 seconds. (0) Cleaning up request packet ID 145 with timestamp +10 due to cleanup_delay was reached Ready to process requests