Настройка SSL/TLS#
В данном разделе рассмотрим, как настраивать SSL/TLS на примере взаимодействия между клиентом и SOWA, а затем - между SOWA и backend.
Настройка SSL/TLS на точке входа#
Необходимо сгенерировать сертификат, который будет использоваться как серверный сертификат SOWA. Для этого воспользуемся инструкцией, приведенной в разделе "Настройка и подготовка сертификатов".
Создать каталог resources в examples/proxies/.
Поместить туда файлы с сертификатом и ключом (SOWA_NONPRODUCTION_cert.pem и SOWA_NONPRODUCTION_cert.key).
Создать конфигурационный файл профиля и сохранить его в файле proxy_ssl.yml:
profile: proxy_ssl version: 2.0.3 system: wrk_count: 1 conn_count: 4096 optional: log_level: error service: service_main_proxy: - id: main url: / listen: - port: 11443 ssl: certificate: SOWA_NONPRODUCTION_cert.pem certificate_key: SOWA_NONPRODUCTION.key upstream_groups: - id: back_1 servers: - server: 127.0.0.1:10012 service_http_proxy: - id: 1 name: service_1 url: ^/hello upstream_group_id: back_1 use_main_upstream_groups: true allowed_queries: - method: getЗдесь для сервиса main, который является точкой входа в секции listen, определяются параметры ssl/tls - во-первых, само наличие секции ssl означает, что на данном порту ожидается ssl подключение, параметры certificate (файл сертификата в формате PEM) и certificate_key - закрытый ключ.
Добавить профиль в реестр командой add-profile.
Скопировать ключ и сертификат в ресурсную папку профиля.
Обратите внимание, что после конфигурирования данные артефакты будут удалены из каталога /sowa/profile_storage/custom/proxy_ssl.
[sowacfg@tkle-ish0038 proxies]$ cp resources/* /sowa/profile_storage/custom/proxy_ssl/Сконфигурировать профиль и запустить его. Отправить запрос по протоколу https c использованием опции insecure (т.к. серверный сертификат или его подписанты не были добавлены в доверенные).
[sowacfg@tkle-ish0038 proxies]$ curl -v https://localhost:11443/hello/world --insecure * About to connect() to localhost port 11443 (#0) * Trying 127.0.0.1... * Connected to localhost (127.0.0.1) port 11443 (#0) * Initializing NSS with certpath: sql:/etc/pki/nssdb * skipping SSL peer certificate verification * SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 * Server certificate: * subject: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU * start date: Apr 05 14:09:27 2021 GMT * expire date: Apr 05 14:09:27 2022 GMT * common name: SOWA_NONPRODUCTION * issuer: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
Рассмотрим теперь возможность двусторонней аутентификации - для этого в секции ssl нашего профиля пропишем опции verify_client и client_certificate.
В качестве значения опции verify_client могут быть одно из значений (on, optional, optional_no_ca) - подробнее об этом и других параметрах ssl/tls соединения рассказывается в разделе "Параметр listen".
Будет использоваться значение "on" для проверки сертификата клиента на то, что он подписан доверенным сертификатом.
В качестве доверенного, будет использоваться выпущенный нами сертификат, имя файла с которым нужно прописать в опции client_certificate. Получим следующий конфигурационный файл для нового профиля proxy_ssl_verify:
profile: proxy_ssl_verify
version: 2.0.3
system:
wrk_count: 1
conn_count: 4096
optional:
log_level: error
service:
service_main_proxy:
- id: main
url: /
listen:
- port: 11444
ssl:
certificate: SOWA_NONPRODUCTION_cert.pem
certificate_key: SOWA_NONPRODUCTION.key
verify_client: on
client_certificate: SOWA_NONPRODUCTION_cert.pem
upstream_groups:
- id: back_1
servers:
- server: 127.0.0.1:10012
service_http_proxy:
- id: 1
name: service_1
url: ^/hello
upstream_group_id: back_1
use_main_upstream_groups: true
allowed_queries:
- method: get
Создадим профиль, скопируем сертификаты в ресурсную папку профиля, сконфигурируем и попробуем отправить запрос на порт 11444:
[sowacfg@tkle-ish0038 proxies]$ curl -v https://localhost:11444/hello/world --insecure
* About to connect() to localhost port 11444 (#0)
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 11444 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* NSS: client certificate not found (nickname not specified)
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
* start date: Apr 05 14:09:27 2021 GMT
* expire date: Apr 05 14:09:27 2022 GMT
* common name: SOWA_NONPRODUCTION
* issuer: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
> GET /hello/world HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:11444
> Accept: */*
>
< HTTP/1.1 400 Bad Request
< Date: Tue, 06 Apr 2021 11:19:22 GMT
< Content-Type: text/html
< Content-Length: 229
< Connection: close
< Server: SOWA
<
<html>
<head><title>400 No required SSL certificate was sent</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>SOWA</center>
</body>
</html>
* Closing connection 0
Как видим, в этот раз ответ 200 не получен, а получена ошибка 400 - No required SSL certificate was sent.
Теперь повторим действия, но при подключении укажем сертификат, который был использован в качестве доверенного на слушателе SOWA.
[sowacfg@tkle-ish0038 proxies]$ curl -v https://localhost:11444/hello/world --insecure --cert resources/SOWA_NONPRODUCTION_cert.pem --key resources/SOWA_NONPRODUCTION.key
* About to connect() to localhost port 11444 (#0)
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 11444 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* NSS: client certificate from file
* subject: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
* start date: Apr 05 14:09:27 2021 GMT
* expire date: Apr 05 14:09:27 2022 GMT
* common name: SOWA_NONPRODUCTION
* issuer: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
* start date: Apr 05 14:09:27 2021 GMT
* expire date: Apr 05 14:09:27 2022 GMT
* common name: SOWA_NONPRODUCTION
* issuer: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
> GET /hello/world HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:11444
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 06 Apr 2021 11:26:38 GMT
< Content-Type: text/html
< Content-Length: 149
< Connection: keep-alive
< Server: SOWA
<
* Connection #0 to host localhost left intact
Сгенерируем теперь клиентский сертификат, и попробуем подключиться с его помощью:
[sowacfg@tkle-ish0038 proxies]$ openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem
Generating a 2048 bit RSA private key
..............+++
.........................+++
writing new private key to 'key.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:RU
State or Province Name (full name) []:Samara
Locality Name (eg, city) [Default City]:Samara
Organization Name (eg, company) [Default Company Ltd]:Stech
Organizational Unit Name (eg, section) []:EsEn
Common Name (eg, your name or your server's hostname) []:user
Email Address []:user@user.com
Результат проверки обращения к сервису hello/world с новыми сертификатами следующий:
[sowacfg@tkle-ish0038 proxies]$ curl -v https://localhost:11444/hello/world --insecure --cert certificate.pem --key key.pem
* About to connect() to localhost port 11444 (#0)
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 11444 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* NSS: client certificate from file
* subject: E=user@user.com,CN=user,OU=EsEn,O=Stech,L=Default City,ST=Samara,C=RU
* start date: Apr 05 14:09:27 2021 GMT
* expire date: Apr 05 14:09:27 2022 GMT
* common name: user
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
* start date: Apr 05 14:09:27 2021 GMT
* expire date: Apr 05 14:09:27 2022 GMT
* common name: SOWA_NONPRODUCTION
* issuer: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
> GET /hello/world HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:11444
> Accept: */*
>
< HTTP/1.1 400 Bad Request
< Date: Tue, 06 Apr 2021 11:36:01 GMT
< Content-Type: text/html
< Content-Length: 229
< Connection: close
< Server: SOWA
<
<html>
<head><title>400 The SSL certificate error</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
SOWA не верифицировала сертификат клиента.
Теперь создадим запрос на сертификат и подпишем его нашим доверенным сертификатом:
[sowacfg@tkle-ish0038 proxies]$ openssl genrsa -out client_signed.key 2048
Generating RSA private key, 2048 bit long modulus
......................................................................................+++
.................................................+++
e is 65537 (0x10001)
[sowacfg@tkle-ish0038 proxies]$ openssl req -new -key client_signed.key -out client_signed.cs
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:RU
State or Province Name (full name) []:Samara
Locality Name (eg, city) [Default City]:Samara
Organization Name (eg, company) [Default Company Ltd]:Stech
Organizational Unit Name (eg, section) []:EsEn.Sowa
Common Name (eg, your name or your server's hostname) []:user
Email Address []:user@user.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[sowacfg@tkle-ish0038 proxies]$ openssl x509 -req -in client_signed.csr -CA resources/SOWA_NONPRODUCTION_cert.pem -CAkey resources/SOWA_NONPRODUCTION.key -CAcreateserial -out client_signed.crt -days 5000
Signature ok
subject=/C=RU/ST=Samara/L=Samara/O=Stech/OU=EsEn.Sowa/CN=user/emailAddress=user@user.com
Getting CA Private Key
И теперь, повторим запрос на сервис с новым подписанным сертификатом:
[sowacfg@tkle-ish0038 proxies]$ curl -v https://localhost:11444/hello/world --insecure --cert ./client_signed.crt --key ./client_signed.key
* About to connect() to localhost port 11444 (#0)
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 11444 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* NSS: client certificate from file
* subject: E=user@user.com,CN=user,OU=EsEn.Sowa,O=Stech,L=Samara,ST=Samara,C=RU
* start date: Apr 06 11:48:39 2021 GMT
* expire date: Dec 14 11:48:39 2034 GMT
* common name: user
* issuer: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
* start date: Apr 05 14:09:27 2021 GMT
* expire date: Apr 05 14:09:27 2022 GMT
* common name: SOWA_NONPRODUCTION
* issuer: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
> GET /hello/world HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:11444
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 06 Apr 2021 11:50:38 GMT
< Content-Type: text/html
< Content-Length: 149
< Connection: keep-alive
< Server: SOWA
<
* Connection #0 to host localhost left intact
Hello world[sowacfg@tkle-ish0038 proxies]$
Как видно, запрос успешно выполнен.
Настройка SSL/TLS на точке выхода - поток SOWA - backend#
Сначала добавим сервис - заглушку, которая будет принимать соединения по TLS. Для этого в файле stubs/services/plain_service.yml добавим сервис hello_world_ssl_service.
- id: hello_world_ssl_service
optional:
response_code: 200
response_body: "Hello world"
response_headers:
- name: Content-Type
value: text/plain
url: ^/hello/world
listen:
- port: 10112
ssl:
certificate: SOWA_NONPRODUCTION_cert.pem
certificate_key: SOWA_NONPRODUCTION.key
После чего скопируем сертификат и ключ в ресурсную папку профиля /sowa/profile_storage/custom/sample_stub/, переконфигурируем и перезапустим профиль.
Создадим профиль прокси-сервиса proxy_ssl_verify_upstream на основе профиля proxy_ssl_verify:
profile: proxy_ssl_verify_upstream
version: 2.0.3
system:
wrk_count: 1
conn_count: 4096
optional:
log_level: error
service:
service_main_proxy:
- id: main
url: /
listen:
- port: 11445
ssl:
certificate: SOWA_NONPRODUCTION_cert.pem
certificate_key: SOWA_NONPRODUCTION.key
verify_client: on
client_certificate: SOWA_NONPRODUCTION_cert.pem
upstream_groups:
- id: back_1
servers:
- server: 127.0.0.1:10112
ssl: true
service_http_proxy:
- id: 1
name: service_1
url: ^/hello
upstream_group_id: back_1
use_main_upstream_groups: true
allowed_queries:
- method: get
Как видно, единственное изменение, которое было сделано (кроме прописывания новых портов) — это установка значения ssl: true в настройках группы backend.
Добавим данный профиль, скопируем сертификаты в ресурсную папку профиля, сконфигурируем и запустим.
Пример обращения к профилю:
[sowacfg@tkle-ish0038 proxies]$ curl -v https://localhost:11445/hello/world --insecure --cert ./client_signed.crt --key ./client_signed.key
* About to connect() to localhost port 11445 (#0)
* Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 11445 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* NSS: client certificate from file
* subject: E=user@user.com,CN=user,OU=EsEn.Sowa,O=Stech,L=Samara,ST=Samara,C=RU
* start date: Apr 06 11:48:39 2021 GMT
* expire date: Dec 14 11:48:39 2034 GMT
* common name: user
* issuer: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
* start date: Apr 05 14:09:27 2021 GMT
* expire date: Apr 05 14:09:27 2022 GMT
* common name: SOWA_NONPRODUCTION
* issuer: CN=SOWA_NONPRODUCTION,OU=00CA,O=Bank of the Russian Federation,L=Moscow,ST=Moskva,C=RU
> GET /hello/world HTTP/1.1
> User-Agent: curl/7.29.0
> Host: localhost:11445
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Tue, 06 Apr 2021 12:19:00 GMT
< Content-Type: text/plain
< Content-Length: 11
< Connection: keep-alive
< Server: SOWA
Запрос прошел успешно.
В случае, если необходимо включить проверку подлинности сертификата backend, то нужно определить следующие директивы для сервиса с идентификатором 1:
service_http_proxy:
- id: 1
name: service_1
url: ^/hello
upstream_group_id: back_1
use_main_upstream_groups: true
allowed_queries:
- method: get
optional:
proxy_ssl:
ssl_trusted_certificate: PEM цепочка доверенных сертификатов
ssl_verify: 'on'
Если требуется, чтобы соединение с backend устанавливалось с использованием не сертификата клиента (а другого, например, отдельного сертификата SOWA), то необходимо в этой же секции задать параметры сертификата. В данном случае сервис main_proxy отсутствует.
profile: proxy_ssl_verify_upstream
version: 2.0.3
system:
wrk_count: 1
conn_count: 4096
optional:
log_level: error
service_http_proxy:
- id: 1
name: service_1
url: ^/hello
upstream_group_id: back_1
use_main_upstream_groups: true
allowed_queries:
- method: get
optional:
proxy_ssl:
ssl_certificate: SOWA_NONPRODUCTION_cert.pem
ssl_certificate_key: SOWA_NONPRODUCTION.key
Подобное поведение необходимо для реализации концепции SSL-Offloading.
Про остальные параметры можно прочитать в разделе "Параметр upstream_ssl".