SSH

Selamlar, bu yazıda SSH protokolününün ne olduğundan, nasıl çalıştığından, nasıl yapılandırıldığından ve nasıl kullanıldığından bahsedeceğim. Öncelikle SSH protokolünün ne olduğundan başlayalım.

SSH nedir?

Türkçe karşılığı Güvenli Soket Kabuğu olan İngilizcedeki Secure Socket Shell'in baş harflerinden isimlendirilen SSH, kullanıcılara ağ üzerinden bir bilgisayara erişmenin güvenli yolunu sağlayan bir network (ağ) protokolüdür. SSH, güçlü bir parola veya key (anahtar) doğrulaması ile ağ üzerindeki iki bilgisayar arasında şifreli iletişimi sağlar. Genelde sistem yöneticileri tarafından sistemleri uzaktan yönetmek için kullanılır. Güvenli olmayan uzaktan bağlantı uygulamalarının yerini almak üzere oluşturulmuştur.

SSH ne işe yarar?

  • Uzak sistemlerde komut çalıştırmak

  • Dosya aktarmak

  • Ağlar arası tünel açmak


SSH nasıl çalışır?

SSH, bağlantının görüntülendiği SSH client (istemci) ile bağlantının çalıştırıldığı SSH server (sunucu) bağlantısını sağlayan client-server modelini kullanır. SSH, TCP/IP protokolleri ile çalışır.

SSH server, bağlantı için varsayılan olarak 22 portunu dinler ve TCP protokolünü kullanır.

SSH güvenlidir çünkü public key encryption (açık anahtar şifrelemesi) ile şifreleme ve kimlik doğrulama kullanır. Public key encryption, verilerin anahtarla şifrelenmesi yöntemidir. Public key (açık anahtar) oluşturulur ve bu key SSH server tarafına kopyalanır. Bu işlemlerden sonra yapacağınız her SSH bağlantısında server ve client taraflarındaki public keyler karşılaştırılır ve parola girmeden bağlantı sağlanır. Bağlantı sağlandığında kullanıcı, uzaktaki sunucuda komut çalıştırabilir.

SSH kurulumu ve yapılandırılması

Şimdi gelelim SSH kurulumuna, config dosyasının yapılandırılmasına ve bağlantının yapılmasına. Anlatırken Ubuntu Server 22.04 sistemini kullanacağım.

Öncelikle aşağıdaki komut ile Ubuntu Server'da openssh-server kuralım.

sudo apt install openssh-server

openssh-server başarıyla kurulduktan sonra aşağıdaki komutu yazarak openssh-server'ın çalışma durumunu kontrol edebilirsiniz.

sudo service ssh status

Görselde aktif olduğunu görüyoruz. Eğer openssh-server aktif değilse service ssh start komutu ile aktif halde çalıştırabilirsiniz. SSH config üzerinde hiçbir yapılandırma yapmadan, varsayılan yapılandırma ile SSH bağlantısı yapabiliriz.

SSH bağlantısı nasıl yapılır?

IPv4 üzerinden parola ile SSH bağlantısı nasıl yapılır?

  • SSH server IPv4 adresi: 10.10.67.102

  • SSH client IPv4 adresi: 10.10.67.41

Client üzerinden bağlantı için komut kullanımı ssh <user>@<host> -p <port> şeklindedir. Komutu yazarak ubuntu kullanıcısı ile SSH sunucusuna 22 portundan SSH bağlantısı isteği gönderelim.

Port belirtmezsek varsayılan olarak 22 portunu kullanır.

sudo ssh [email protected] -p 22
root@mozlercelik:~# ssh [email protected] -p 22
[email protected]'s password: 
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-102-generic x86_64)
...
Last login: Thu Apr 11 20:59:33 2024 from 10.10.67.41
ubuntu@ubuntu:~$ 

Komutu yazdıktan sonra parola sordu ve ubuntu kullanıcının parolasını yazarak ssh bağlantısı yaptık.

IPv6 üzerinden parola ile SSH bağlantısı nasıl yapılır?

  • SSH server; IPv6 adresi: fe80::20c:29ff:fed8:205c interface: ens33

  • SSH client; IPv6 adresi: fe80::7883:fa7a:b0eb:5e0 interface: eth0

Client üzerinden bağlantı için komut kullanımı IPv4 bağlantısı için ssh <user>@<host> -p <port> şeklinde demiştik. Yine aynı formatta kullanacağız fakat IPv6 adresinin yanında % işareti ile interface belirtmemiz gerekiyor. Yine ubuntu kullanıcısı ile SSH sunucusuna 22 portundan SSH bağlantı isteği gönderelim.

sudo ssh ubuntu@fe80::20c:29ff:fed8:205c%eth0 -p 22
root@mozlercelik:~# ssh ubuntu@fe80::20c:29ff:fed8:205c%eth0 -p 22
ubuntu@fe80::20c:29ff:fed8:205c%eth0's password: 
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-102-generic x86_64)
...
Last login: Thu Apr 11 21:29:35 2024 from fe80::7883:fa7a:b0eb:5e0%ens33
ubuntu@ubuntu:~$

Komutu yazdıktan sonra yine parola sordu ve ubuntu kullanıcının parolasını yazarak ssh bağlantısı yaptık.

Public key ile SSH bağlantısı

Öncelikle client üzerinde key oluşturmamız lazım. Aşağıdaki komut ile public key oluşturabiliriz. Dosya ismi ve parola soracak, enter'a basarak varsayılan dosya ile boş parola girebiliriz.

ssh-keygen

Çıktı aşağıdaki gibi:

root@mozlercelik:~# ssh-keygen
Generating public/private ed25519 key pair.
Enter file in which to save the key (/root/.ssh/id_ed25519): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /root/.ssh/id_ed25519
Your public key has been saved in /root/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:sESR7k3F7W+tS9sIAQr9//PcU3YYhYFa5VSsZ+1xcgc root@mozlercelik
The key's randomart image is:
+--[ED25519 256]--+
|      oo . . o+=.|
|     ...  o +oE o|
|     .+ ...+  .+.|
|     ..+.o... +.B|
|     ..oS . .. X+|
|      . .  . .+ *|
|            o..oo|
|             +o*.|
|              =+*|
+----[SHA256]-----+

Public key'imiz oluştu. Şimdi oluşan public key'imizi SSH server'a kopyalayalım. Aşağıdaki komut ile kopyalayabiliriz.

ssh-copy-id [email protected]

Oluşturduğumuz public key server'daki ubuntu kullanıcısı için kaydedilecek ve server'a ubuntu kullanıcısı ile parola kullanmadan bağlanabileceğiz. Yukarıdaki komutun çıktısı aşağıdaki gibi:

root@mozlercelik:~# ssh-copy-id [email protected]
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_ed25519.pub"
The authenticity of host '10.10.67.102 (10.10.67.102)' can't be established.
ED25519 key fingerprint is SHA256:ePx9uC5wDEjD0LTmE6xud8z5zKpLMR3wIOtgv8Qgnt8.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '[email protected]'"
and check to make sure that only the key(s) you wanted were added.

ssh-copy-id komutunu çalıştırdıktan sonra kopyalamak için parola sordu. Bağlanmaya çalıştığımız ubuntu kullanıcısının parolasını girdik ve kopyalama başarılı oldu. Hadi parola olmadan bağlanmayı deneyelim. ssh [email protected] komutunu çalıştıralım.

root@mozlercelik:~# ssh [email protected]
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-102-generic x86_64)
...
Last login: Thu Apr 11 21:01:11 2024 from 10.10.67.41
ubuntu@ubuntu:~$ 

Yukarıdaki çıktıda görüldüğü gibi parola sormadı ve direkt olarak bağlantı sağladık. Eğer oluşturduğunuz public key'i kopyalarken root kullanıcısı ile kopyalarsanız root ile parolasız bağlanabilirsiniz. Tabii ki öncelikle yapılandırmanızda root yetkileri ile bağlantıya izin vermelisiniz.

SSH yapılandırması nasıl yapılır?

SSH server'da yapılandırma yapmak için sshd_config dosyasını düzenlememiz lazım. Yapılandırma için /etc/ssh/sshd_config dosyasını açalım ve düzenleyelim.

sudo vi /etc/ssh/sshd_config

Birçok parametre var ben sadece en önemli gördüğüm parametrelerden bahsedeceğim.

...
Match all
Port 22
ListenAddress 0.0.0.0
ListenAddress ::
PermitRootLogin no
PasswordAuthentication no
AllowUsers ubuntu mozlercelik
AllowGroups ubuntu yavuzlar

Match User mozlercelik
PasswordAuthentication yes
...

Dosyayı açık ve yukarıdaki parametreleri uyguladık. Bazı parametreler yorum satırı olabilir veya dosya içerisinde olmayabilir, sizin eklemeniz lazım. Dosyada değişlik yaptıktan sonra kaydedip dosyayı kapatalım. Değişikliklerin uygulanması için SSH servisini yeniden başlatmamız gerekiyor. Aşağıdaki komutu kullanarak SSH servisini yeniden başlatabilirsiniz.

service ssh restart

Eğer yanlış yapılandırma yapmadıysanız hatasız olarak yeniden başlatılacaktır. Aktiflik durumundan emin olmak için service ssh status komutunu kullanarak kontrol edebiliriz. Şimdi parametreleri yakından inceleyelim.

Match

Match ...

Kullanıcıya özel yapılandırma yapmak için Match parametresi kullanılabilir. Eğer kullanılmazsa yapılandırmalar tüm kullanıcılar için geçerli olur. Match all parametresi altında yazılan parametreler tüm kullanıcılar, gruplar, hostlar vb. için geçerli olur. Kullanıcıya veya kullanıcılara özel parametre belirtmek için Match User ... parametresi kullanılır. Aynı zamanda gruplara özel yapılandırma da yapılabilir. Örnek kullanım:

Match all
...
Match User mozlercelik
...
Match User ubuntu, mozlercelik
...
Match Group yavuzlar
...

Port

Port ...

SSH bağlantısının hangi port üzerinden yapılacağını belirtiyoruz. Varsayılan olarak 22 ayarlanmıştır. Silinirse 22 portu üzerinden bağlantı yapılabilir.

ListenAddress

ListenAddress [hostname|address]:port

SSH bağlantısının hangi adres ve port üzerinden bağlantıları kabul edileceğini belirtmek için kullanılır.

  • IPv4 adresleri için tüm interface'ler üzerinden bağlantıların kabul edilmesi için 0.0.0.0

  • IPv6 adresleri için tüm interface'ler üzerinden gelen bağlantıların kabul edilmesi için :: kullanılır.

Bu parametreyi biraz daha detaylandıralım. SSH sunucusu üzerinde ip addr show komutunu çalıştıralım.

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:d8:20:5b brd ff:ff:ff:ff:ff:ff
    altname enp2s1
    inet 10.10.67.102/24 brd 10.10.67.255 scope global ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fed8:205d/64 scope link 
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fed8:205c/64 scope link 
       valid_lft forever preferred_lft forever

Komutu çalıştırdık ve sunucu üzerindeki interface'leri görüntüledik. Yukarıdaki interface ve IP adreslerine göre aşağıdaki kullanımları inceleyelim.

  • ListenAddress 10.10.67.102 şeklinde kullandığımızda sadece 10.10.67.102 adresi üzerinden bağlantı sağlanabilir.

  • ListenAddress fe80::20c:29ff:fed8:205c%ens33 şeklinde kullandığımızda sadece ens33 interface'i üzerindeki fe80::20c:29ff:fed8:205c IPv6 adresi üzerinden bağlantı sağlanabilir.

Bu ayarlara göre IPv6 kullanarak sunucuya bağlanmaya çalışalım.

root@mozlercelik:~# ssh ubuntu@fe80::20c:29ff:fed8:205d%eth0
ssh: connect to host fe80::20c:29ff:fed8:205d%eth0 port 22: Connection refused
                                                                                                                                                                                                                
root@mozlercelik:~# ssh ubuntu@fe80::20c:29ff:fed8:205c%eth0
ubuntu@fe80::20c:29ff:fed8:205c%eth0's password: 
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-102-generic x86_64)

Last login: Thu Apr 11 20:00:34 2024 from fe80::7883:fa7a:b0eb:5e0%ens33
ubuntu@ubuntu:~$

Yukarıda görüldüğü gibi sadece ListenAddress parametresi ile verilen IPv6 adresi üzerinden bağlantı sağlayabiliyoruz. Diğer IPv6 adresi üzerinden bağlanmaya çalıştığımızda Connection refused hatası ile karşılaşıyoruz.

PermitRootLogin

PermitRootLogin yes|no|prohibit-password|forced-commands-only

SSH üzerinden root yetkileriyle bağlantı yapılıp yapılamayacağı ayarlanır. Varsayılan olarak prohibit-password ayarlanmıştır. yes - root yetkileri ile SSH bağlantısını kabul eder. no - root yetkileri ile SSH bağlantılarını engeller. prohibit-password - root yetkileri ile parolalı bağlantı kurulamaz. Root yetkileriyle sadece public key ile bağlantı sağlanabilir. forced-commands-only - Public key kullanılarak root yetkileriyle bağlantı kurulabilir ve sadece ForceCommand parametresi ile verilen komutlar çalıştırılabilir.

PasswordAuthentication

PasswordAuthentication no|yes

Parola ile SSH bağlantısı yapılıp yapılamayacağını belirtmek için kullanılır. yes - Kullanıcıların parola ile SSH bağlantısını kabul eder. no - Kullanıcıların parola ile SSH bağlantısı yapmasına izin vermez.

AllowUsers

AllowUsers ...

SSH bağlantısına izin verilen kullanıcıları belirlemek için kullanılır. Boşluklarla ayırarak kullanıcılar belirtilir. Varsayılan olarak tüm kullanıcılarla bağlantı yapılmasına izin verilir. Örnek kullanım:

AllowUsers ubuntu mozlercelik

Bu örnek kullanımda sadece ubuntu ve mozlercelik kullanıcılarının SSH ile bağlantı yapmasına izin verilmektedir.

AllowGroups

AllowGroups ...

SSH bağlantısına izin verilen kullanıcı gruplarını belirlemek için kullanılır. Boşluklarla ayırarak gruplar belirtilir. Varsayılan olarak tüm gruplara ait kullanıcıların bağlantı yapılmasına izin verilir.

AllowGroups ubuntu yavuzlar

Bu örnek kullanımda sadece ubuntu ve yavuzlar gruplarındaki kullanıcıların SSH ile bağlantı yapmasına izin verilmektedir.


SSH tünelleme nedir?

Client'ın direkt olarak erişemediği hedef makineye, başka bir makine üzerinden sanki aynı ağ üzerindeymiş gibi erişebilmesidir. Örnek olarak yukarıdaki görseli inceleyelim. Yukarıdaki sistem hakkında bildiklerimiz:

  • Client makine internette

  • server 1, server 2 ve database, firewall arkasında kendi ağlarındalar.

  • Server 2 firewall üzerinden internete çıkabiliyor ve 22 portunda SSH servisi çalışıyor.

Bu senaryoda client, server 1'e 80 portundan erişmek istiyor. Bu bağlantı nasıl olabilir? Client ile server 1 farklı ağlarda olduklarından bağlantı kurulamıyor. Bu sebeple client, server 2 üzerinden SSH tünellemesi yaparak server 1'e erişebiliyor. Server 1, sadece kendi ağından gelen istekleri karşılayabiliyor ve tünelleme yapıldığında server 1, gelen paketin server 2'den geldiğini görüyor, gelen isteği karşılayabiliyor.

SSH tünelleme nasıl yapılır?

Yukarıdaki simülasyon üzerinde örnek yapalım. Client makine yani bizim makinemiz ile 8000 portunda HTTP server çalıştıran sunucuya bağlantı kuralım. Aşağıda topoloji hakkında bilgiler mevcut:

  • Client (biz):

    10.10.67.185

  • Ara sunucu

    • interface 1

      10.10.67.102

      ssh/22 açık

    • interface 2 192.168.1.1

  • Hedef sunucu 192.168.1.10 http/8000 açık

10.10.67.102 IP adresine sahip makineden hedef sunucuya istek atalım.

Aynı ağda oldukları için iki makine haberleşebiliyor. Şimdi tünelleme yaparak client tarafından ulaşmaya çalışalım. Aşağıdaki komutu client üzerinde çalıştırıyoruz.

ssh -L 4444:192.168.1.10:8000 [email protected]

Yukarıdaki kodu parçalayıp inceleyelim. ssh -L dport:shost:sport user@tunnelip

  • ssh: SSH komutu.

  • -L: client üzerinde hangi portta dinleyeceğimizi belirtiyoruz.

  • dport: client üzerindeki port.

  • shost: Hedef sunucu. Hangi sunucu ile iletişim kurmak istiyorsak onu yazıyoruz.

  • sport: Hedef sunucu üzerinde iletişim kuracağımız port.

  • user: Tünelleme yapacağımız ara sunucudaki kullanıcı adı.

  • tunnelip: Tünelleme yapacağımız ara sunucunun adresi.

Yukarıdaki komuta göre client'ın 4444 portuna 192.168.1.10 IP adresine sahip sunucunun 8000 portunu bağladık. Client üzerinde 4444 portuna attığımız her istek hedef sunucunun 8000'in portuna gidecek ve dönen cevabı tünel üzerinden bize iletecek. Hadi deneyelim:

Tünelleme yapmadan önce (client): Tünelleme yapmadan önce client makinede 4444 portuna istek atıyoruz ve port üzerinde bir şey olmadığı için bağlanılamıyor.

Tünelleme yaptıktan sonra (client): Açtığımız tünel sayesinde hedef makinedeki 8000 portuna client'ın 4444 portundan ulaşabilmeliyiz. Tünelleme yaptıktan sonra client makinede 4444 portuna istek atıyoruz ve aşağıdaki sonucu alıyoruz. En başta ara sunucu üzerinden attığımız isteğin sonucu ile aynı. Bu demek oluyor ki tünelleme başarılı olmuş ve tünel üzerinden erişim sağlayabiliyoruz.

Yazının sonuna geldin! Umarım yazdıklarım faydalı olmuştur. Saygılarımla,

Kaynaklar

sshd_config için tüm parametreler ve açıklamaları: https://man7.org/linux/man-pages/man5/sshd_config.5.html ssh-keygen komutu için detaylı bilgi: https://www.ssh.com/academy/ssh/keygen

Last updated