Son güncelleme tarihi 12 Eylül 2022
TLS, SNI destekli pure-ftpd FTPS Server Kurulumu yapabilmemiz için öncelikle tanımlardan başlayalım, pure-ftpd ftp server yazılımı anladık ama SNI ne, TLS ne? hadi bakalım.
FTP Server nedir?
File Transfer Protocol Server, resmi olarak TCP port 21 üzerinden iletişim kuran ve dosya transferinde kullanılan server uygulamalara verilen isimdir. RFC 959 içerisinde protokole ait tüm özellikler tanımlanmıştır.
TLS nedir?
Transport Layer Security teriminin baş harflerinden oluşan standarttır ve RFC-6066 güncel dökümanıdır ve TLS uzantısından bahsedilmektedir, SNI tanımı, işlevi bu döküman içerisindedir. TLS versiyonları farklı dökümanlarda tanımlanmaktadır. TLSv1.0 , TLSv1.1 , TLSv1.2 , TLSv1.3 linklerinden versiyonlar ve aralarındaki farkları inceleyebilirsiniz. Standartlar kısmında bu konuda detaylı bir yazı yayınlanabilir, yoksa merak etmeyin zamanı gelince yazılacaktır.
SNI nedir?
Server Name Indication (Sunucu Adı Göstergesi) teriminin baş harfleri kullanılarak oluşturulan kısaltmadır ve bir sunucu sistemde eğer aynı IP adresi üzerinde birden fazla alan adı mevcutsa, yazılım tarafında hangi alan adının talep edildiğini tanımlamaya yarayan terimdir.
Hızlı girişten sonra yukarıda yaptığımız tanımları birleştirelim ve sunucumuzu kurmaya başlayalım.
Bir FTP sunucusunda diğer suncularda olduğu gibi güvenliği ön planda tutmak gerekir, bunu yapmak için kriptolu iletişim kurabilen sunucu yapılandırmak gerekmektedir, TLS bize kriptolu iletişim kurabilen altyapıyı sağlamakta.
Peki bir FTP sunucusu kurduk ve yetkin bir CA tarafından onaylı SSL sertifikalarımızla birlikte TLS bağlantımız da aktif durumda ancak sunucumuzda birden fazla alan adı ile iletişim kuruluyor. Bu gibi durumlarda FTP server yazılımı genellikle tek bir sertifika üzerinden çalışacak şekilde ayarlanmakta benim gibi egzantrikler ise her domain kendi sertifikası ile şifreleme yapsa olmaz mı, kendi ftp.alanadım.com url bilgisini girdiğimde ssl hatası almadan girsem olmaz mı diye sorabilmekte 🙂 soruyu sorduktan sonra kendi cevabımı internette bulamayıp kendim türetmiş olmam da ilginç ama keyifli oldu. Bu beni egzantrik tiplemeler arasında bile egzantrik yapıyor sanırım… neyse.
PureFTP güzel dökümantasyona sahip bir program, bir miktar okuma yapmam gerekti.

Örnek olarak kullanmak için 2 adet alan adımın ftp subdomain A kaydına digitalocean üzerindeki bir Debian 11 sanal makina açarak (ftp.ysn.app hostname) bu sunucunun IP adres bilgisini ekledim.
Bu noktaya kadar kendiniz gelebiliyor olmalısınız ardından aşağıdaki adımları attığınızda elinizde tam işlevsel, Lets’n Crypt CA tarafından doğrulanmış SSL sertifikası ile her alan adına özel TLS bağlantı sağlayan bir FTP server olacak.
FTP Sunucusu Kurulumu İşlem Adımları:
- Server genel uygulamaların kurulumu.
- Firewall Yapılandırması
- Mysql yapılandırması
- pure-ftpd için veritabanı oluşturmak
- Veritabanımızda ftpd tablosunu oluşturmak
- FTP için sistem kullanıcılarını oluşturmak
- Sistem kullanıcılarını FTP kullanıcısı olarak eklemek
- pure-ftpd-mysql paketini pure-certd aracını içerecek şekilde derleme işlemi
- pure-ftpd-mysql paketinin kurulumu
- pure-ftpd yapılandırmak
- Süresi dolmuş olan DST_Root_CA_X3.crt ca-certificates.conf içerisinden temizlemek
- certbot aracı ile Lets’n Crypt SSL sertifikalarını almak
- pure-ftpd varsayılan sertifikayı oluşturmak
- CERTD_SNI_NAME değişkenini kullanarak pure-certd uygulamasının gerekli sertifika bilgisini okuyabilmesini sağlayan shell scripti yazmak
- Püf Noktası! pure-ftpd-wrapper scripti içerisine standartta olmayan satırı eklemek. ( Bu sayede pure-ftpd ve pure-certd iletişim kurabilmekte. )
- pure-certd için systemd unit file hazırlayıp sistem servisi olarak çalıştıralım.
- fail2ban jail konfigurasyonumuzu ekleyelim
- Hayırlı olsun.
1. Server genel uygulamaların kurulumu.
Aşağıdaki işlemlerin tümü root kullanıcısı ile yapılacaktır!
Öncelikle sunucumuzu güncelleyip yeniden başlatalım, eğer kernel güncellemesi yoksa yeniden başlatmaya gerek yok.
apt update -y apt upgrade -y reboot
Ardından pure-ftpd-mysql paketi ile birlikte kullanacağımız ve temel server yapılandırması üzerinde ihtiyaç duyabileceğimiz paketleri kuralım.
apt install -y sudo bash-completion ufw fail2ban htop reptyr screen httpie jq curl apt-transport-https net-tools dnsutils netcat fping certbot mariadb-server uidmap
2. Firewall Yapılandırması
Sistemimize kurduğumuz ufw firewall ile sistemimizin ihtiyaç duyacağı portları açıyoruz.
Uyarı! Eğer resmi port değerlerini değil de kendi belirlediğiniz portlar üzerinden uygulamaları yapılandıracaksanız/yapılandırdıysanız o portların erişimini açmayı unutmayın!
20,21 ftp
22 ssh
80 (http) bu portu sadece certbot aracını kullanırken açsak ta olur.
35000:50000 FTP Pasif Port Aralığımız için gerekli
son olarak ufw uygulamamızı aktif ediyoruz.
ufw allow ssh ufw allow http ufw allow 20/tcp ufw allow ftp ufw allow 35000:50000/tcp yes | ufw enable
3. Mysql yapılandırması
Mysql temel yapılandırması için mysql_secure_installation komutunu kullanıyoruz. Aşağıda verdiğim cevapların aynısını vermenizde bir sakınca yok.
Enter current password for root (enter for none): Switch to unix_socket authentication [Y/n] Y Change the root password? [Y/n] n Remove anonymous users? [Y/n] Y Disallow root login remotely? [Y/n] Y Remove test database and access to it? [Y/n] Y Reload privilege tables now? [Y/n] Y
4. pure-ftpd için veritabanı oluşturmak
mysql konsola erişim için:
mysql -u root
pureftpd veritabanını oluşturmak için:
CREATE DATABASE pureftpd; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP ON pureftpd.* TO 'pureftpd'@'localhost' IDENTIFIED BY '12345678'; GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP ON pureftpd.* TO 'pureftpd'@'localhost.localdomain' IDENTIFIED BY '12345678'; FLUSH PRIVILEGES;
Yukarıda mysql konsola eriştik ve SQL komutlarıyla pureftpd isminde parolası 12345678 olan bir veritabanı oluşturduk. Ürün olarak kullanacağınız sistemde haliyle parolanızı daha kuvvetli belirlemelisiniz ve veritabanına uzaktan erişecekseniz bir adet te remote kullanıcı oluşturmalısınız. Başka bir konu olduğundan burada bırakıyorum.
5. Veritabanımızda ftpd tablosunu oluşturmak
Halen daha mysql konsol içerisindeyiz.
USE pureftpd; CREATE TABLE ftpd ( User varchar(16) NOT NULL default '', status enum('0','1') NOT NULL default '0', Password varchar(64) NOT NULL default '', Uid varchar(11) NOT NULL default '-1', Gid varchar(11) NOT NULL default '-1', Dir varchar(128) NOT NULL default '', ULBandwidth smallint(5) NOT NULL default '0', DLBandwidth smallint(5) NOT NULL default '0', comment tinytext NULL, ipaccess varchar(15) NOT NULL default '*', QuotaSize smallint(5) NOT NULL default '0', QuotaFiles int(11) NOT NULL default 0, PRIMARY KEY (User), UNIQUE KEY User (User) ); \q
Tablo alanlarının açıklamasını isteyen olursa diye:
- User: The name of the virtual PureFTPd user (e.g. exampleuser).
status: 0 or 1. 0 means the account is disabled, the user cannot login. - Password: The password of the virtual user. Make sure you use MySQL’s MD5 function to save the password encrypted as an MD5 string:
- UID: The userid of the ftp user you created at the end of step two (e.g. 2001).
- GID: The groupid of the ftp group you created at the end of step two (e.g. 2001).
- Dir: The home directory of the virtual PureFTPd user (e.g. /home/www.example.com). If it does not exist, it will be created when the new user logs in the first time via FTP. The virtual user will be jailed into this home directory, i.e., he cannot access other directories outside his home directory.
- ULBandwidth: Upload bandwidth of the virtual user in KB/sec. (kilobytes per second). 0 means unlimited.
- DLBandwidth: Download bandwidth of the virtual user in KB/sec. (kilobytes per second). 0 means unlimited.
- comment: You can enter any comment here (e.g. for your internal administration) here. Normally you leave this field empty.
- ipaccess: Enter IP addresses here that are allowed to connect to this FTP account. * means any IP address is allowed to connect.
- QuotaSize: Storage space in MB (not KB, as in ULBandwidth and DLBandwidth!) the virtual user is allowed to use on the FTP server. 0 means unlimited.
- QuotaFiles: amount of files the virtual user is allowed to save on the FTP server. 0 means unlimited.
\q komutu ile mysql konsoldan çıkmayı unutmayalım.
6. FTP için sistem kullanıcılarını oluşturmak
Etkileşimsiz şekilde ekleme işlemini gerçekleştirip parolasını sonradan belirledim ancak adduser veya useradd diyerek etkileşimli şekilde de oluşturabilirsiniz size kalmış.
adduser --disabled-password --gecos "" ysnapp sudo -u ysnapp mkdir /home/ysnapp/ftp echo "ysnapp:eE3Q8PbD" | chpasswd echo "User ID = $(id ysnapp --user)" # 1000 echo "Group ID = $(id ysnapp --group)" # 1000 adduser --disabled-password --gecos "" turkiyehub sudo -u turkiyehub mkdir /home/turkiyehub/ftp echo "turkiyehub:eE3Q8PbD" | chpasswd echo "User ID = $(id turkiyehub --user)" # 1001 echo "Group ID = $(id turkiyehub --group)" # 1001 mkdir /home/ysnapp/ftp mkdir /home/turkiyehub/ftp
Sistem public olduğundan burada parolaları biraz kuvvetli verdim. pwgen ismindeki aracı hızlı parola üretmek için tavsiye ederim. pwgen -cns 8
7. Sistem kullanıcılarını FTP kullanıcısı olarak eklemek
mysql konsola bağlanarak ftp kullanıcılarımızı az önce oluşturduğumuz tabloya ekleyelim. Bu tablo, sistemdeki bütün ftp kullanıcılarını ve yetkilerini/sınırlarını belirlemeye yarıyor.
mysql -u root INSERT INTO pureftpd.ftpd ( `User`, status, Password, Uid, Gid, Dir, ULBandwidth, DLBandwidth, ipaccess, QuotaSize ) VALUES ( 'ysnapp', '1', MD5('eE3Q8PbD'), '1000', '1000', '/home/ysnapp/ftp', 0, 0, '*' ,0 ); INSERT INTO pureftpd.ftpd ( `User`, status, Password, Uid, Gid, Dir, ULBandwidth, DLBandwidth, ipaccess, QuotaSize ) VALUES ( 'turkiyehub', '1', MD5('eE3Q8PbD'), '1001', '1001', '/home/turkiyehub/ftp', 0, 0, '*' ,0 );
Sorguladığınızda aşağıdakine benzer bir çıktı alacaksınız.
use pureftpd; MariaDB [pureftpd]> select * from ftpd; +------------+--------+----------------------------------+------+------+----------------------+-------------+-------------+---------+----------+-----------+------------+ | User | status | Password | Uid | Gid | Dir | ULBandwidth | DLBandwidth | comment | ipaccess | QuotaSize | QuotaFiles | +------------+--------+----------------------------------+------+------+----------------------+-------------+-------------+---------+----------+-----------+------------+ | turkiyehub | 1 | 94ea920ae690cf1f902022d7289bd5f7 | 1001 | 1001 | /home/turkiyehub/ftp | 0 | 0 | NULL | * | 0 | 0 | | ysnapp | 1 | 94ea920ae690cf1f902022d7289bd5f7 | 1000 | 1000 | /home/ysnapp/ftp | 0 | 0 | NULL | * | 0 | 0 | +------------+--------+----------------------------------+------+------+----------------------+-------------+-------------+---------+----------+-----------+------------+ \q
8. pure-ftpd-mysql paketini pure-certd aracını içerecek şekilde derleme işlemi
Öncelikle apt paket yöneticisi aracılığı ile pure-ftpd-mysql paketini derlememiz için gerekli geliştirme kütüphaneleri ile birlikte pure-ftpd-mysql paketinin debian .deb paketlenebilir kaynak kodunu indirelim. Ardından derleme klasörüne geçelim.
apt build-dep pure-ftpd-mysql apt source pure-ftpd-mysql cd pure-ftpd-*
Derleme klasörü içerisinde debian dizininde rules isminde bir dosyamız var, paket üretilirken hangi işlemler yapılacağı bu dosyada yer almakta. Standart paket pure-certd aracı derlenmemiş olarak gelmekte bu sebepten kendimiz derlemeliyiz. Bunu yaparken ufak bir değişiklik yapıyoruz.
nano debian/rules
komutunu vererek rules dosyasını açalım ve sbin ile başlayan satırın sonuna pure-certd ekleyelim.

./configure --with-mysql --with-tls --with-everything dpkg-buildpackage -uc -us
Yukarıdaki komutları verdikten sonra derleme işlemimiz tamamlanmış demektir.

9. pure-ftpd-mysql paketinin kurulumu
apt install -y -f ../pure-ftpd-common_1.0.49-4.1_all.deb ../pure-ftpd-mysql_1.0.49-4.1_amd64.deb
Paketlerimizi kurduktan sonra güncelleme almaması için paketleri apt ile hold konumuna çekelim, aksi taktirde pure-certd aracı olmayan varsayılan paket depodan yüklenecektir. Versiyon yükseltmek te bir seçenek ancak bir güncelleme geldiğini bilmemiz gerek. Güncelleme geldiğinde 8. ve 9. adımları tekrarlamanız yeterli.
echo "pure-ftpd-common hold" | dpkg --set-selections echo "pure-ftpd-mysql hold" | dpkg --set-selections
10. pure-ftpd yapılandırmak
4. adımda oluşturduğumuz veritabanı ve kullanıcı bilgilerini pure-ftpd okuyabilmesi için gerekli alanlara yazalım. Veritabanı varsayılan tablo ismi users (biz ftpd yaptık) olduğundan MySQL sorgularında da gerekli düzeltmeleri yaparak açıklama satırı olan alanları da düzenleyelim.
nano /etc/pure-ftpd/db/mysql.conf MYSQLUser pureftpd MYSQLPassword 12345678 MYSQLDatabase pureftpd MYSQLGetPW SELECT Password FROM ftpd WHERE User='\L' MYSQLGetUID SELECT Uid FROM ftpd WHERE User='\L' MYSQLGetGID SELECT Gid FROM ftpd WHERE User='\L' MYSQLGetDir SELECT Dir FROM ftpd WHERE User='\L' MySQLGetQTAFS SELECT QuotaFiles FROM ftpd WHERE User='\L' MySQLGetQTASZ SELECT QuotaSize FROM ftpd WHERE User='\L' MySQLGetBandwidthUL SELECT ULBandwidth FROM ftpd WHERE User='\L' MySQLGetBandwidthDL SELECT DLBandwidth FROM ftpd WHERE User='\L' MySQLTransactions On
Gerekli config dosyalarını oluşturalım, burada karşılaştığım bir durum var bu yüzden /etc/pure-ftpd/pure-ftpd.conf
dosyasındansa /etc/pure-ftpd/conf/
… dizininde yeralan ve wrapper tarafından okunan dosyaları tercih ediyorum, size de aynısını tavsiye ederim.
echo "0.0.0.0,21" > /etc/pure-ftpd/conf/Bind echo "yes" > /etc/pure-ftpd/conf/ChrootEveryone echo "yes" > /etc/pure-ftpd/conf/CreateHomeDir echo "/var/run/ftpd-certs.sock" > /etc/pure-ftpd/conf/ExtCert echo "UTF-8" > /etc/pure-ftpd/conf/FSCharset echo "$(curl ifconfig.me)" > /etc/pure-ftpd/conf/ForcePassiveIP echo "1000" > /etc/pure-ftpd/conf/MinUID echo "/etc/pure-ftpd/db/mysql.conf" > /etc/pure-ftpd/conf/MySQLConfigFile echo "yes" > /etc/pure-ftpd/conf/NoAnonymous echo "yes" > /etc/pure-ftpd/conf/PAMAuthentication echo "35000 50000" > /etc/pure-ftpd/conf/PassivePortRange echo "/etc/pure-ftpd/pureftpd.pdb" > /etc/pure-ftpd/conf/PureDB echo "2" > /etc/pure-ftpd/conf/TLS echo "HIGH" > /etc/pure-ftpd/conf/TLSCipherSuite echo "133 022" > /etc/pure-ftpd/conf/Umask echo "no" > /etc/pure-ftpd/conf/UnixAuthentication
echo "/var/run/ftpd-certs.sock" > /etc/pure-ftpd/conf/ExtCert
bu satır bizim SNI ile farklı sertifikaları kullanabilmemizi sağlayacak.
11. Süresi dolmuş olan DST_Root_CA_X3.crt ca-certificates.conf içerisinden temizlemek
nano /etc/ca-certificates.conf mozilla/D-TRUST_Root_Class_3_CA_2_EV_2009.crt #mozilla/DST_Root_CA_X3.crt mozilla/DigiCert_Assured_ID_Root_CA.crt
nano /etc/ca-certificates.conf dosyası içerisinde mozilla/DST_Root_CA_X3.crt satırını açıklama satırı yaptıktan sonra:
update-ca-certificates
komutunu vererek ca veritabanını güncelliyoruz.
FileZilla gibi uygulamalar gerçek olmasına rağmen süresi dolmuş sertifikaları gördükleri zaman biraz sinir bozucu olabiliyorlar…
12. certbot aracı ile Lets’n Crypt SSL sertifikalarını almak
certbot -d ftp.ysn.app certonly --standalone certbot -d ftp.turkiyehub.com certonly --standalone
Sisteminizdeki herbir domain için aynı işlemi tekrarlayın.

Burada dikkat etmeniz gereken nokta DNS A kaydı için sorguladığınızda bu işlemi yaptığınız sunucuya erişiyor olmalısınız!
Sertifikalarımızı en geç 3 ayda bir yenilememiz gerekmekte bu sebepten certbot aracı için bir adet cron job ekleyelim.
crontab -e # en alta bu satırı ekledikten sonra editörümüzü kaydedip kapatalım. 12 saatte bir sertifika yenileme kontrolü yapılmakta. 0 0,12 * * * /usr/bin/certbot renew -q
13. pure-ftpd varsayılan sertifikayı oluşturmak
cd /etc/letsencrypt/live/ftp.ysn.app cat fullchain.pem privkey.pem | tee /etc/ssl/private/pure-ftpd.pem chmod 600 /etc/ssl/private/pure-ftpd.pem # diffie hellman parametresi oluşturma işlemi 1 ila 30dk arası olabilmekte, sabır. openssl dhparam -out /etc/ssl/private/pure-ftpd-dhparams.pem 4096
14. CERTD_SNI_NAME değişkenini kullanarak pure-certd uygulamasının gerekli sertifika bilgisini okuyabilmesini sağlayan shell scripti yazmak
Aşağıdaki shell scripti aynen kopyalayıp yapıştırın,
nano /bin/pure-cert-check.sh
#! /usr/bin/sh #echo "$(env)" > /root/sni_log echo 'action:strict' echo 'cert_file:/etc/letsencrypt/live/'${CERTD_SNI_NAME}'/fullchain.pem' echo 'key_file:/etc/letsencrypt/live/'${CERTD_SNI_NAME}'/privkey.pem' echo 'end'
Uyarı: konumunu farklı lokasyonda belirleyecekseniz pure-certd parametresini de düzenlemeyi unutmayın!
Not: eğer local bir sistemde çalışıyorsak ve self-signed ssl kullanacaksak;
echo ‘action:strict‘ yerine echo ‘action:fallback‘ olarak kullanmalıyız, böylece doğrulanabilir bir ssl bulamadığında varsayılan sertifikaya dönebilir. Production makinada bunu strict tutmak faydamıza.
pure-cert-check.sh scriptimizi çalıştırılabilir yapalım.
chmod +x /bin/pure-cert-check.sh
15. Püf Noktası! pure-ftpd-wrapper scripti içerisine standartta olmayan satırı eklemek. ( Bu sayede pure-ftpd ve pure-certd iletişim kurabilmekte. )
nano /usr/sbin/pure-ftpd-wrapper
NoTruncate ile başlayan satırı bulun ve bir altına 'ExtCert' => [ '-3 %s', \&parse_string],
satırını ekleyin. Bu satırda olması şart değil ancak son satıra eklediğimde çalışmadı ve rastgele buraya ekledim.

Komutu nasıl buldun sorusuna gelince, man pure-ftpd
tabii olarak. Terminalde çalıştığını test ettikten sonra önümde duran perl scripti modifiye etmek bebek oyuncağı.
Bu bilgi sanki devlet sırrıymış gibi ne pure-ftpd sitesindeki dökümanlarda ne de internette araştırdığım kadarıyla yok arkadaşlar, saygılarımla.

Son olarak test maksatlı olarak uygulamalarımızı çalıştıralım. Detay için man pure-certd
pure-certd --run /bin/pure-cert-check.sh --socket /var/run/ftpd-certs.sock --pidfile /var/run/pure-certd.pid -B systemctl restart pure-ftpd-mysql.service
Bu aşamada sistemi test edebiliriz, ftp bağlantımızı sunucumuza yaptığımızda talep edilen domain için olan ssl sertifikası ile bağlantı çalışmalı. Yerel bir sistemde self signed ssl ile bu işlemi test ediyorsanız action:fallback ve active mode bağlantı ile ftp bağlantısı kurmanız faydanıza.
Testimiz bittikten sonra;
pkill pure-certd
komutu ile çalışan pure-certd işlemini bitirelim.
16. pure-certd için systemd unit file hazırlayıp sistem servisi olarak çalıştıralım.
Aşağıdaki dosyayı nano /etc/systemd/system/pure-certd.service
içerisine ekleyin.
[Unit] Description=Start pure-certd Daemon After=network.target Before=pure-ftpd-mysql.service [Service] ExecStart=/usr/sbin/pure-certd --run /bin/pure-cert-check.sh --socket /var/run/ftpd-certs.sock --pidfile /var/run/pure-certd.pid RestartSec=5 Restart=always [Install] WantedBy=multi-user.target
Son olarak servisi aktifleştirip pureftp ve certd süreçlerini yeniden başlatalım.
systemctl enable pure-certd.service systemctl start pure-certd.service systemctl restart pure-ftpd-mysql.service systemctl status pure-*
Artık sistemimiz açıldığı andan itibaren ftps sunucumuz sni destekli şekilde çalışacaktır.

17. fail2ban jail konfigurasyonumuzu ekleyelim
echo -e "[pure-ftpd]\nenabled = true" >> /etc/fail2ban/jail.d/defaults-debian.conf systemctl restart fail2ban.service
18. Hayırlı olsun.



syslog içerisinde SNI bilgisi görüntülenebilmekte ancak pure-certd aracı bu bilgiyi işlevsel hale getirmekte.

Allah’a emanet olun.
Yorumlar kapatıldı.