Configure mTLS for client to APISIX
This example includes the following procedures:
- Generate certificates;
- Configure the certificate in APISIX;
- Create and configure routes in APISIX;
- Test verification.
To make the test results clearer, the examples mentioned in this article pass some information about the client credentials upstream, including: , fingerprint
and common name
.
We need to generate three test certificates: the root, server, and client. Just use the following command to generate the test certificates we need via OpenSSL
.
Use the curl
command to request APISIX Admin API to set up SSL for specific SNI.
note
curl -X PUT 'http://127.0.0.1:9180/apisix/admin/ssls/1' \
--header 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
--header 'Content-Type: application/json' \
--data-raw '{
"sni": "test.com",
"cert": "<content of server.cer>",
"key": "<content of server.key>",
"client": {
"ca": "<content of ca.cer>"
}'
sni
: Specify the domain name (CN) of the certificate. When the client tries to handshake with APISIX via TLS, APISIX will match the SNI data inClientHello
with this field and find the corresponding server certificate for handshaking.cert
: The public key of the server certificate.key
: The private key of the server certificate.- : The public key of the client’s certificate. For demonstration purposes, the same
CA
is used here.
Use the curl
command to request the APISIX Admin API to create a route.
APISIX automatically handles the TLS handshake based on the SNI and the SSL resource created in the previous step, so we do not need to specify the hostname in the route (but it is possible to specify the hostname if you need it).
Also, in the curl
command above, we enabled the proxy-rewrite plugin, which will dynamically update the request header information. The source of the variable values in the example are the NGINX
variables, and you can find them here: .
Since we are using the domain test.com
as the test domain, we have to add the test domain to your DNS or local hosts
file before we can start the verification.
- If we don’t use
hosts
and just want to test the results, then you can do so directly using the following command.
curl --resolve "test.com:9443:127.0.0.1" https://test.com:9443/anything -k --cert ./client.cer --key ./client.key
- If you need to modify
hosts
, please read the following example (for Ubuntu).
Verify that the test domain name is valid
ping test.com
PING test.com (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=64 time=0.028 ms
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=2 ttl=64 time=0.037 ms
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=3 ttl=64 time=0.036 ms
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=4 ttl=64 time=0.031 ms
^C
--- test.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3080ms
Test results
You will then receive the following response body.
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "test.com",
"User-Agent": "curl/7.81.0",
"X-Amzn-Trace-Id": "Root=1-63256343-17e870ca1d8f72dc40b2c5a9",
"X-Forwarded-Host": "test.com",
"X-Ssl-Client-Fingerprint": "c1626ce3bca723f187d04e3757f1d000ca62d651",
"X-Ssl-Client-S-Dn": "CN=CLIENT",
"X-Ssl-Client-Serial": "5141CC6F5E2B4BA31746D7DBFE9BA81F069CF970"
},
"json": null,
"method": "GET",
"origin": "127.0.0.1",
"url": "http://test.com/anything"
Since we configured the plugin in the example, we can see that the response body contains the request body received upstream, containing the correct data.
Conclusion
For more information about the mTLS feature of Apache APISIX, you can read .