Merhabalar,

Son dönemde özellikle istio’nun da yaygınlaşmasıyla sıkça karşımıza çıkan mTLS’i anladığım kadarıyla açıklamak isterim.

Öncelikle günümüzdeki TLS kavramında bahsedelim; karşılıklı olarak her makinenin ortak bir sertifika authority’den imzalamış olduğu rootCA client üzerinde bulunur ve karşılıklı kurulan TLS connection üzerinde istemci, sunucuyu tanımlamış ve doğrulandığından emin olmuş şekilde aradaki connection icin el sıkışmış olur (tls-handshake).

Ancak buradaki yapıdaki sunucu client hakkında kimin olduğuna dair bir bilgiye sahip değil.Normal kullanıcılar için bu durumun farkında olmasak bile dışarıya açık noktalara (endpoint) sahip bir yapi da client tarafında ne döndüğünü de bilmemiz gerektigi durumlar karışımıza çıkabiliyor.

Dışarı açık endpoint kavramı da internal network içerisinde birbirine çağrı yapan servisler arasında bile olabilir.

MTLS/TwoWayTLS/ISTIO-MTLS ….. etc

Yaklasik 2 yil once istio nedir diye gezinirken karsima cikan bir terim acikcasi kendisi tam tanimina gelin su diagrama bir goz atalim ;

Baktigimizda normal HTTPS uzerinden bir connection kurmak istedigimizde server ve client arasinda birbiri arasindaki sifrelemenin dogru olmasi icin public olarak bulunan clienttaki sertifika ile server’a gidilir.

Server evet bu benim private key ile imzalandi ok dedikten sonra arada iletisim TLS uzerinden devam eder.Buradaki ana nokta client ilk basta serveri dogrulamasi ancak server clientin kim oldugunu bilmiyor.

MTLS burada clienta da gidip kim oldugunu soruyor ve kendisi icin client tarafindaki keyi ile bu sefer clientta kendi bildigi private key ile iletisim kurabilecek mi diye bakiyor. Buradaki public key ve private key uzerinden imzalanmis sertifika aslinda yapboz parcalari gibi olmak zorunda, yoksa ne ile gidersek gidelim bir bit degisse bile key uyumsuzlugundan connection kuramayabiliriz.

Simdi gelin bir endpointe nasil client sertifikalarini da isin icerisine dahil ederek istek atabiliyoruz ona bakalim burada sevgili kardesimiz Nginx isin icerisinde, bunun katkilari ve side-car evrendeki karsiligina da buradan goz kirpiyor olacagiz.

Ilk olarak yapmamiz gereken bir ust sayfadaki CA kismina bir goz atmak ve bizim sertifikalarimiz imzalayacak olacak referans sertifikalari olusturuyoruz.

$ openssl genrsa -des3 -out ca.key 4096$ openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

Bu iki arkadas ile daha sonra server side icin ilgili CN ile yeni sertifikalar turetip imzaliyoruz (CSR :Certificate Signing Request).

$ openssl genrsa -des3 -out mysite.key 4096$ openssl genrsa -des3 -out mysite.com.key 4096  262  openssl req -new -key mysite.com.key -out mysite.com.csr  264  $ openssl x509 -req -days 365 -in user.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out user.crt

Simdi burada cok kisa duruyoruz. Buraya kadar her sey normal selfsigned ve kendi icimizde kullandigimiz bir authority tarafindan bir sertifika imzaladik ve bunu Nginx uzerinde terminate edecegiz.

Simdi ilgili konfigleri olusturalim.Bu konfigler sayfanin cok buyuk kismini kaplayacagi icin hepsini eklemiyorum ama gist olarak linkleri birakacagim.

server {  
....
.....
listen 443;
ssl on;
server_name mysite.com;
proxy_ssl_server_name on;
ssl_certificate /etc/nginx/certs/mysite.com.crt;
ssl_certificate_key /etc/nginx/certs/mysite.com.key;
.........
}

Burada yaptigimiz islem su nginx’e hey nginx, senin handshake yaparken server’i sordular mi verecegin sertifika burada => `ssl_certificate` Key uzerinden karsilastirma yapacagin zamanda `ssl_certificate_key` buraya bak deyip olaylara basliyoruz.

Bu configler disinda ekstra bir konfig yok (bi index.html eklemekte fayda var) gelin simdi bir curl atalim ne oluyor gorelim :

curl --cacert ca.crt https://mysite.com 

Burada attigimiz istegin yasam dongusunde ortak imzalayan CA’in public sertifikasi ile nginx’e gidiyorum.

Burada ilk adimda oldugu gibi sadece server gercekten guvenilir mi sorusunu sormus oluyoruz ve 200 OK gayet guzel donuyor.

Iste simdi isin rengini biraz degistirmek icin nginx configlerimizde hareketimizi yapiyoruz.

ssl_client_certificate /etc/nginx/certs/ca.crt;
ssl_verify_client on;

Bu iki arkadasi ekliyorum ve diyorumki sana gelen clientlerin da sertifikalarini kontrol et.

Ayni sekilde bir daha istek gonderiyorum ve Nginx bana 400 donerek nerede senin certifikan diyor, iste bu durumda bende

$ curl --cacert ca.crt https://mysite.com$ <html>... 400 No required SSL certificate was sent ...</html>

Yani ….

Ardından clienta şu argumanlari geçiyorum:

curl --cacert ca.crt --key user.key --cert user.crt https://mysite.com

Kendi CA ile kullanıcıya ait key ve sertifika ile adrese gidiyorum ve bana istediğim cevabı alıyorum.

Burada özet olarak anlatmaya çalıştığım kısım server tarafının güvenilirliğinden emin olurken TLS termination sırasında araya bir katman daha ekleyip ikincil bir sertifika ile cikip bu sefer client acaba guvenilir mi diye karsi bir sertifika isteyebiliyoruz.

Peki ya envoy, istio…. ?

Asagidaki gorsele bakacak olursak service kismi asil konteynirlarimizi kapsiyor burada public sertifikalari biribirine cagri yapan servislere yuklememize gerek yok.

Hali hazirda bir merkezi sertifika yoneticisi ile istio icinde tum envoylara yani side-car vazifesi goren arkadaslara bu sertifiklar dagiliyor ve envoylar birbiri arasinda istersek mtls uzerinden konusuyor ve trafik servislere yine TCP uzerinden ulasiyor.

Istio Genel Dizayn

Istio aslinda bizim hali hazirda yaptigimiz isi bir reverse proxy ile tum networku extend ederek basarmis oluyor (OPEN-CLOSED Principle).

Son olarak,

Mtl gunumuzdeki zero-trust yaklasimin bir urunu aslinda, bazi belgelerde ortada bir key olmadan sertifika uzerinden reverse proxy yapilabilecek auth islemleri icin, IOT cihazlarina ozel sertifikalardan olmak uzere bir cok genis kullanim alani mevcut.

Bu yazida anladiklarimi ve uyguladiklarimin bir ozetini anlatmaya calistim umarim aktarabildim.

Kaynakca

NginxConfiguration: https://gist.github.com/WoodProgrammer/5a51cc287b3f3883295150669c53cbaf

PythonRubyLinux(❤)

PythonRubyLinux(❤)