Skip to content

Instantly share code, notes, and snippets.

@tomfun
Last active June 7, 2023 14:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomfun/1ad3d2f873625ae865b4a82e0fc9f9bc to your computer and use it in GitHub Desktop.
Save tomfun/1ad3d2f873625ae865b4a82e0fc9f9bc to your computer and use it in GitHub Desktop.
how to: tls client nginx
#!/bin/sh
echo $1
echo "optional questions is: A challenge password, An optional company name, Enter Export Password, Enter Import Password"
mkdir -p client/$1
# Create the Client Key and CSR
# личный ключ клиента, только ему самому стоит его знать. если софт поддерживает пассфраз (как ниже), лучше его использовать.
openssl genrsa -des3 -out client/$1/key.key 2048
openssl rsa -in client/$1/key.key -out client/$1/key.nopass.key
# запрос на сертификат
openssl req -new -key client/$1/key.nopass.key -out client/$1/request.csr
echo " keys and request created"
ls -l client/$1
# Sign the client certificate with our CA cert. Unlike signing our own server cert, this is what we want to do.
# вот тут создаём сертификат, и подписываем нашим ЦА.
openssl x509 -req -days 720 -in client/$1/request.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client/$1/certificate.crt
echo " Combine your key and certificate in a PKCS#12 (P12) bundle"
echo " enter passphrase for created key"
# Для браузеров полезен п12 формат
openssl pkcs12 -export -clcerts -in client/$1/certificate.crt -inkey client/$1/key.key -out client/$1/certificate.p12
# Нам пригодится пем формат для клиента
openssl pkcs12 -in client/$1/certificate.p12 -out client/$1/certificate.pem -clcerts
echo " certificates created"
ls -l client/$1
echo " info for $1/certificate.crt"
openssl x509 -noout -text -in client/$1/certificate.crt
openssl x509 -noout -text -in client/$1/certificate.crt | grep --color=always "O=[^,]*\|CN=[^,/]*"
echo " info for $1/certificate.p12"
openssl pkcs12 -in client/$1/certificate.p12 -noout -info
chmod g-r client/$1/*
chmod o-r client/$1/*

easyrsa need to be for both: server and client

download easy rsa somewhere and use full path: ~/bin/EasyRSA-3.1.2/easyrsa

https://github.com/OpenVPN/easy-rsa/blob/master/README.quickstart.md

Server

install vpn

apt install openvpn

server.conf

port 1194
proto udp
dev tun

# private key
askpass /etc/openvpn/server/pass.txt
# tls auth (optional)
key-direction 0

server 10.50.8.0 255.255.255.0 # internal tun0 connection IP
ifconfig-pool-persist ipp.txt

keepalive 10 120

comp-lzo # Compression - must be turned on at both end
persist-key
persist-tun

#push "dhcp-option DNS 192.168.0.200"
#push "dhcp-option DOMAIN std.local"
#push "route 192.168.0.0 255.255.255.0"

status /var/log/openvpn-status.log

verb 3 # verbose mode

<dh>
-----BEGIN DH PARAMETERS-----
...
-----END DH PARAMETERS-----
</dh>
<cert>
Certificate:
    Data:
...
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
-----END ENCRYPTED PRIVATE KEY-----
</key>

<ca>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</ca>

<tls-auth>
-----BEGIN OpenVPN Static key V1-----
...
-----END OpenVPN Static key V1-----
</tls-auth>

DH

~/bin/EasyRSA-3.1.2/easyrsa gen-dh
cat pki/dh.pem

inline in server.conf

Server Keys, CA

~/bin/EasyRSA-3.1.2/easyrsa build-server-full server-name-hereServer
cat pki/inline/server-name-hereServer.inline

inline in server.conf

write key password in askpass /etc/openvpn/server/pass.txt file

sudo touch /etc/openvpn/server/pass.txt
sudo chmod 600 /etc/openvpn/server/pass.txt
sudo nano /etc/openvpn/server/pass.txt

systemd service

sudo systemctl start openvpn-server@server-name-here.service
for server.conf inside /etc/openvpn/server/ dir:

sudo systemctl start openvpn-server@server.service
sudo systemctl enable openvpn-server@server.service
sudo systemctl status openvpn-server@server.service

Client

cd /etc/openvpn/client
touch pass.txt
chmod 600 pass.txt
#touch server-name-here.conf
touch server.conf
chmod o-r server.conf

client.conf

 client
 remote 'server2.example.com' 1194 udp
 remote '192.168.0.1' 1194 udp
 remote '192.168.1.1' 1194 udp
# auth-user-pass
 cipher AES-128-CBC
 data-ciphers AES-256-GCM:AES-128-GCM:AES-128-CBC
 dev tun
 dev-type tun
 proto udp
 port 1194
 ping 30
 ping-restart 90
 comp-lzo
 nobind
 auth-nocache
 script-security 2
 persist-key
 persist-tun
 user nobody
 group nogroup

 # private key / pem password
 askpass /etc/openvpn/client/pass.txt
 # tls-auth
 key-direction 1
 # check cert type
 remote-cert-tls server
 # check server-name
 verify-x509-name server-name-hereServer name

<cert>
Certificate:
    Data:
        Version: 3 (0x2)
-----END CERTIFICATE-----
</cert>

<key>
-----BEGIN ENCRYPTED PRIVATE KEY-----
...
-----END ENCRYPTED PRIVATE KEY-----
</key>

<ca>
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
</ca>

<tls-auth>
-----BEGIN OpenVPN Static key V1-----
...
-----END OpenVPN Static key V1-----
</tls-auth>

server client certificate & key

~/bin/EasyRSA-3.1.2/easyrsa build-serverClient-full client-name-hereServerClient enter password (optional, use )

Certificate created at:
* ....pki/issued/client-name-hereServerClient.crt
...
* ....pki/inline/client-name-hereServerClient.inline

cat pki/inline/client-name-hereServerClient.inline inline in server.conf

write key password in askpass /etc/openvpn/client/pass.txt file

sudo touch /etc/openvpn/server/pass.txt
sudo chmod 600 /etc/openvpn/server/pass.txt
sudo nano /etc/openvpn/server/pass.txt

tla auth

use the same as in server config and keep it secret

systemd service

sudo systemctl start openvpn-client@server-name-here.service
for server.conf inside /etc/openvpn/server/ dir:

sudo systemctl start openvpn-server@server.service
sudo systemctl enable openvpn-server@server.service
sudo systemctl status openvpn-server@server.service

extra

https://std.rocks/vpn_openvpn_bullseye.html

Инструкция how to "Как доверять клиентам"

В интернете много ресурсов, информация бралась из:

Создаём ключи

# Create the CA Key and Certificate for signing Client Certs
# делаем совсем приватный ключ, создаём ЦА сертификат, им всё подписывается
# ну здесь можно и пассфраз ввести
openssl genrsa -des3 -out ca.key 4096
# а это мы будем использовать для проверки всего, что им подписано. значимость вводимой информации сомнительна.
openssl req -new -x509 -days 720 -key ca.key -out ca.crt

# Create the Server Key, CSR, and Certificate
# этот ключ мы отдадим серверу, и в итоге нам не нужна будет пасфраза
openssl genrsa -des3 -out server.key 2048
# делаем ключ без пасфразы
openssl rsa -in server.key -out server.nopass.key
# создаём запрос на сертификат для сервера. тут полезно ввести Common Name как имя хоста
openssl req -new -key server.nopass.key -out server.csr

# We're self signing our own server cert here.  This is a no-no in production.
# создаём сертификат для сервера. им и можно проверять тот ли это сервер
openssl x509 -req -days 720 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

# Create the Client Key and CSR
# личный ключ клиента, только ему самому стоит его знать. если софт поддерживает пассфраз (как ниже), лучше его использовать.
openssl genrsa -des3 -out client.key 2048
# запрос на сертификат
openssl req -new -key client.key -out client.csr

# Sign the client certificate with our CA cert.  Unlike signing our own server cert, this is what we want to do.
# вот тут создаём сертификат, и подписываем нашим ЦА.
openssl x509 -req -days 720 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt

# Для браузеров полезен п12 формат
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12

# Нам пригодится пем формат для клиента
openssl pkcs12 -in client.p12 -out client.pem -clcerts

Nginx

server {
#    listen 80;
    listen 443 ssl;
#    listen [::]:443 ssl;

    keepalive_timeout   60;
    ssl_certificate /home/tomfun/prj/tls/secure/server.crt; #сертификат сервера
    ssl_certificate_key /home/tomfun/prj/tls/secure/server.nopass.key; #ключ, его никому не даём
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS";

    ssl_client_certificate /home/tomfun/prj/tls/secure/ca.crt; # собственно ЦА, по нему мы определяем, правильный ли клиент у нас
    ssl_verify_client on; # этим мы отсекаем не наших клиентов, можно выключить это
#    add_header Strict-Transport-Security 'max-age=604800';

# ........... логи, имя сервера, прочее

    # ну и можно завернуть запрос внутри в нешефрованное соеденение
    location / {
        proxy_pass http://127.0.0.1:9200;
        # доп параметры, полезны для скриптов, совсем не обязательны
        #fastcgi_param SSL_VERIFIED $ssl_client_verify; #полезно, если мы пускаем и чужих клиентов
        #fastcgi_param SSL_CLIENT_SERIAL $ssl_client_serial;
        #fastcgi_param SSL_CLIENT_CERT $ssl_client_cert;
        #fastcgi_param SSL_DN $ssl_client_s_dn;
    }
}

Тестируем

const https = require('https');
const fs = require('fs');

var options = {
  hostname: ИМЯ_ХОСТА,
  port: 443,
  path: '/',
  method: 'GET',
  //rejectUnauthorized: false //можно отключить проверку доверенности сертификата
  key: fs.readFileSync('/home/tomfun/prj/tls/secure/client.key'),//мы свои, и ключ у нас есть
  passphrase: 'client',//и пасфраза
  cert: fs.readFileSync('/home/tomfun/prj/tls/secure/client.pem'),//и сертификат, который не жалко показывать
  ca: fs.readFileSync('/home/tomfun/prj/tls/secure/ca.crt')//и доверяем мы именно нашему серверу
};

https.get(options, (res) => {
  console.log('statusCode: ', res.statusCode);
  console.log('headers: ', res.headers);

  res.on('data', (d) => {
    process.stdout.write(String(d).substr(0, 100));
    process.stdout.write("\n");
  });

}).on('error', (e) => {
  console.error(e);
});

И всё работает
http://joxi.ru/v297DqOFGl7G1r

Есть и другой способ проверить работоспособность, у меня не вышло

openssl s_client -connect 127.0.0.1:443 -servername ИМЯ_ХОСТА -cert client.pem -key client.key
@tomfun
Copy link
Author

tomfun commented Aug 8, 2018

@tomfun
Copy link
Author

tomfun commented Aug 29, 2019

curl https://ИМЯ_ХОСТА/ --cert client.crt --key client.key -k -v

@tomfun
Copy link
Author

tomfun commented Jun 7, 2023

Просто проверка сертификата (без mTLS):

crt$ sudo openssl s_server -accept 0.0.0.0:443 -cert  ero.crt -key pki/private/ero-like.online.cloudflare.com.key -www
[sudo] password for tomfun:         
Enter pass phrase for pki/private/ero-like.online.cloudflare.com.key:
Using default temp DH parameters
ACCEPT

Connect:

openssl s_client -connect 127.0.0.1:443 -servername ero-like.online
or
curl -v --resolve "ero-like.online:443:127.0.0.1" https://ero-like.online
-k to suppress unknown CA

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment