Download raw body.
nc: Add ALPN TLS option
On Wed, May 28, 2025 at 06:26:34AM +0200, Theo Buehler wrote:
> On Wed, May 28, 2025 at 01:34:34PM +1000, David Leadbeater wrote:
> > The only way to test alpn in base is with openssl s_client, which has
> > some quirks. Here's a diff adding -T alpn=value to nc.
>
> Thanks. This makes sense to me. I think it would be helpful to print the
> selected ALPN in report_tls(): if tls_alpn was set via -T, display what
> tls_conn_alpn_selected() returns (if it is non-NULL).
>
> I believe there's incorrect behavior in libtls (present since ALPN
> support was added): if there's no protocol overlap, per RFC 7301, 3.2,
> a server should abort the handshake with a no_application_protocol alert.
> See tlsext_alpn_server_process() for the corresponding logic in libssl:
That bug has been fixed a while back.
Regarding report_tls() I simply meant something like this:
$ nc -Talpn="http/1.0,http/1.1" -cvz archive.org 443
Connection to archive.org (207.241.224.2) 443 port [tcp/https] succeeded!
TLS handshake negotiated TLSv1.3/TLS_AES_256_GCM_SHA384 with host archive.org
Peer name: archive.org
Subject: /CN=*.archive.org
Issuer: /C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
Valid From: Mon Dec 23 15:18:32 2024
Valid Until: Sat Jan 24 15:18:32 2026
Cert Hash: SHA256:ec16a4ca76fc33bc14b714b16aa2255aa12939c567f680c25268722473bbc50e
OCSP URL: http://ocsp.godaddy.com/
OCSP Stapling: good
response_status=0 cert_status=0 crl_reason=0
this update: Mon Jun 23 21:39:51 2025
next update: Fri Jun 27 21:38:51 2025
revocation:
Selected application layer protocol: http/1.1
I'm going to commit this in a few days unless I hear objections.
Index: nc.1
===================================================================
RCS file: /cvs/src/usr.bin/nc/nc.1,v
diff -u -p -r1.100 nc.1
--- nc.1 28 May 2025 03:57:13 -0000 1.100
+++ nc.1 24 Jun 2025 12:38:34 -0000
@@ -265,6 +265,10 @@ for further details);
which allows the supported TLS protocols to be specified (see
.Xr tls_config_parse_protocols 3
for further details).
+.Cm alpn ,
+which allows the TLS ALPN to be specified (see
+.Xr tls_config_set_alpn 3
+for further details).
Specifying TLS options requires
.Fl c .
.Pp
Index: netcat.c
===================================================================
RCS file: /cvs/src/usr.bin/nc/netcat.c,v
diff -u -p -r1.232 netcat.c
--- netcat.c 21 May 2025 08:46:42 -0000 1.232
+++ netcat.c 24 Jun 2025 12:52:41 -0000
@@ -108,6 +108,7 @@ char *tls_expectname; /* required name
char *tls_expecthash; /* required hash of peer cert */
char *tls_ciphers; /* TLS ciphers */
char *tls_protocols; /* TLS protocols */
+char *tls_alpn; /* TLS ALPN */
FILE *Zflag; /* file to save peer cert */
int recvcount, recvlimit;
@@ -534,6 +535,8 @@ main(int argc, char *argv[])
errx(1, "%s", tls_config_error(tls_cfg));
if (tls_config_set_ciphers(tls_cfg, tls_ciphers) == -1)
errx(1, "%s", tls_config_error(tls_cfg));
+ if (tls_alpn != NULL && tls_config_set_alpn(tls_cfg, tls_alpn) == -1)
+ errx(1, "%s", tls_config_error(tls_cfg));
if (!lflag && (TLSopt & TLS_CCERT))
errx(1, "clientcert is only valid with -l");
if (TLSopt & TLS_NONAME)
@@ -1677,6 +1680,7 @@ process_tls_opt(char *s, int *flags)
{ "noverify", TLS_NOVERIFY, NULL },
{ "noname", TLS_NONAME, NULL },
{ "protocols", -1, &tls_protocols },
+ { "alpn", -1, &tls_alpn },
{ NULL, -1, NULL },
};
@@ -1722,7 +1726,7 @@ void
report_tls(struct tls *tls_ctx, char *host)
{
time_t t;
- const char *ocsp_url;
+ const char *alpn_proto, *ocsp_url;
fprintf(stderr, "TLS handshake negotiated %s/%s with host %s\n",
tls_conn_version(tls_ctx), tls_conn_cipher(tls_ctx), host);
@@ -1774,6 +1778,9 @@ report_tls(struct tls *tls_ctx, char *ho
tls_peer_ocsp_result(tls_ctx));
break;
}
+ if ((alpn_proto = tls_conn_alpn_selected(tls_ctx)) != NULL)
+ fprintf(stderr, "Selected application layer protocol: %s\n",
+ alpn_proto);
}
void
nc: Add ALPN TLS option