Bảo mật SSH cho server trên production

Giới thiệu

  • Đối với những ai từng làm việc với server đều biết ssh là 1 công cụ không thể thiếu để chúng ta có thể quản lý, thao tác đối với những remote server. Tuy nhiên ssh cũng là 1 phương tiện được các hacker lợi dụng để chiếm quyền kiểm soát của server, một khi hacker đã chiếm quyền kiểm soát server thì mức độ nguy hiểm là ko thể đo lường được, cũng giống như trộm đã lẻn được vào nhà chúng ta vậy.
  • Bài viết này sẽ giới thiệu những phương pháp thiết lập cũng như nguyên tắc để đảm bảo cho chúng ta sử dụng ssh một cách an toàn, hạn chế tối đa những tấn công với mục đích xấu của những hacker.

Nguyên lý hoạt động + những file config quan trọng của ssh service

Nguyên lý hoạt động

  • ssh là 1 giao thức bảo mật sử dụng để kết nối đến server Linux từ xa. ssh cung cấp giao diện dạng văn bản (text-based), sau khi bạn kết nối được đến ssh server thì mọi command bạn chạy trên local sẽ được thực thi trên ssh server. Khi kết nối đến ssh server thì ta được nhét vào 1 shell session của ssh server, ssh connection hoạt động trên cơ chế Client-Server. Trên Client cần phải có ssh client còn phía server thì cần ssh daemon ( ssh daemon sẽ luôn chạy để lắng nghe kết nối vào ssh server, mọi kết nối vào ssh server luôn được xác thực trước ).
  • ssh sử dụng mã hoá đối xứng (Symmetric Encryption, ví dụ AES, Blowfish, 3DES, CAST128, Arcfour) để mã hoá message và mã hoá bất đối xứng (Asymmetric Encryption, ví dụ RSA,
    DSA, DH) để xác thực người dùng.

Những file config quan trọng của ssh service

Dưới đây sẽ liệt kê các file config quan trọng liên quan tới vấn đề bảo mật cho ssh service:

  • /etc/ssh/sshd_config: file config cho sshd (ssh server), file này ta có thể config vị trí đặt file cho các file hosts key (~/.ssh/known_hosts) hoặc file authorized_keys (~/.ssh/authorized_keys)
  • /etc/ssh/ssh_config: file config cho ssh client file này là config chung cho tất cả user trên máy đó, còn file ~/.ssh/config sẽ dùng để config cho từng user riêng
  • ~/.ssh/config: tham khảo trên
  • /etc/sysconfig/iptables: ko liên quan đến sshd nhưng file này quy định các rule về firewall cho hệ thống, sẽ dùng để thiết lập firewall cho sshd
  • /etc/hosts.deny,/etc/hosts.allow: 2 file này là lưu config các host được phép truy cập or bị cấm truy cập vào server, được sử dụng bởi tcpd (tcp wrapper) và sshd. Ta chạy command man 5 hosts_access để xem syntax config cho file này.

Check list bảo mật cho ssh service

Bảng sau đây sẽ liệt kê ra các phương pháp bảo mật cho ssh service, sẽ có 2 loại là

  • [Nên]: chúng ta nên áp dụng biện pháp này ngay lập tức
  • [Tùy]: áp dụng sẽ bảo mật tốt hơn nhưng không nhất thiết phải sử dụng (vì có thể gây ra sự phiền toái trong quá trình vận hành server). Nên suy xét tình hình hệ thống để xem có áp dụng hay không.
Phân loại Giải thích sơ qua
Network 1.1 Triệt hạ những service không cần thiết [Nên]
Network 1.2 Chỉ cho phép một số host được quyền truy cập vào server [Nên]
Network 1.3 Giới hạn số lượng ssh access vào ssh server [Tùy]
Network 1.4 Giới hạn truy cập từ chính ssh server ra ngoài [Tùy]
SSH service 2.1 Chỉ cho phép ssh protocol version 2 mới được truy cập [Nên]
SSH service 2.2 Sử dụng public key thay cho authenticate bằng password [Nên]
SSH service 2.3 Dừng port forward lại [Nên]
SSH service 2.4 Không sử dụng port 22 cho ssh nữa [Nên]
SSH service 2.5 hash file known_hosts [Nên]
SSH service 2.6 Chỉ cho phép 1 số user mới được quyền login [Tùy]
SSH service 2.7 Ko sử dụng ip v6 thì disable nó đi [Tùy]
SSH service 2.8 Ko sử dụng thuật toán mã hóa và ko sử dụng mã code lỗi yếu [Tùy]
Quản lý key 3.1 Sử dụng passphare cho private key [Nên]
Quản lý key 3.2 Không để private key trên ssh server [Nên]

Phần tiếp theo sẽ đi vào giới thiệu cụ thể từng biện pháp phòng chống nhé!

Chi tiết các phương pháp bảo mật cho ssh service

1.1-Triệt hạ những service không cần thiết

Đi kèm với ssh là các service Telnet, FTP. Ta phải kiểm tra những service nào có sử dụng Telnet, FTP mà ko cần thiết thì stop hết và không cho tự động khởi động lại nữa.

  • Stop service
[root@sshsrv ~]# service <service_name> stop
  • Không cho tự khởi động lại
[root@sshsrv ~]# /sbin/chkconfig <service_name> off ⏎
[root@sshsrv ~]# /sbin/chkconfig --list <service_name> # kiểm tra cấu hình
<service_name> 0:off 1:off 2:off 3:off 4:off 5:off 6:off

1.2-Chỉ cho phép một số host được quyền truy cập vào server

Có 2 cách để giới hạn quyền truy cập là iptables và TCP wrap

1.2.1 - Iptables

Sử dụng iptables (firewall của linux) để cấu hình. Ta chỉ cho phép những ip chuẩn chỉ mới được truy cập vào server thông qua ssh.

  • Ví dụ file cấu hình của iptables (lưu tại /etc/sysconfig/iptables)
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -s 192.168.1.0/24 --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -s 198.51.100.0/24 --dport 22 -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp -s 203.0.113.0/32 --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
  • Giải thích: chỉ những client có ip thuộc các dải mạng 192.168.1.0/24, 198.51.100.0/24, 203.0.113.0/32 sẽ được quyền truy cập vào ssh server, tất cả những ip khác sẽ bị cấm bởi config -A INPUT -j REJECT --reject-with icmp-host-prohibited ý nghĩa của icmp-host-prohibited là những truy cập bị cấm sẽ trả về lỗi type=3:Destination Unreachable hoặc code=10:Host administratively prohibited cho client
  • Cách kiểm tra: xem log ssh service qua command /tail -f /var/log/secure : những truy cập bị cấm sẽ có thông báo refused connect from như dưới đây:
Apr 29 12:00:04 sshsrv sshd[23071]: refused connect from 172.16.11.10 (172.16.11.10)
Apr 29 12:02:04 sshsrv sshd[23075]: refused connect from 172.16.11.10 (172.16.11.10)
Apr 29 12:02:36 sshsrv sshd[23078]: refused connect from 172.16.11.10 (172.16.11.10)

1.2.2 - TCP_wrapper

Config vào 2 file /etc/hosts.deny/etc/hosts.allow , ví dụ:

  • file /etc/hosts.deny : với sshd thì cấm tất
sshd : ALL
  • file /etc/hosts.allow : chỉ cho phép truy cập với những dải mạng sau
sshd : 192.168.1.0/255.255.255.0
sshd : 198.51.100.0/255.255.255.0
sshd : 203.0.113.1/255.255.255.255
  • Cách kiểm tra cũng thông qua log của sshd như trên iptables

1.3-Giới hạn số lượng ssh access vào ssh server

Tụi hacker tàu khựa chuyên môn tấn công brush force vào các server của ta, bạn cứ check log /var/log/secure sẽ thấy có 1 loạt các ip tấn công server ta liên tục

Aug 13 03:32:08 host-133-130-124-187 sshd[11543]: Failed password for root from 121.18.238.123 port 38217 ssh2
Aug 13 03:32:10 host-133-130-124-187 sshd[11543]: Failed password for root from 121.18.238.123 port 38217 ssh2
Aug 13 03:32:13 host-133-130-124-187 sshd[11543]: Failed password for root from 121.18.238.123 port 38217 ssh2

Tụi hacker sẽ gửi đồng thời nhiều request truy cập cùng lúc từ cùng 1 server nên ta nên giới hạn request đồng thời để hạn chế kiểu tấn công brush force. Có 2 cách là dùng iptables hashlimit hoặc config sshd thông số MaxStartups

1.3.1 Iptables hashlimit

  • Config như sau
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -m hashlimit --hashlimit-name ssh --hashlimit-burst
3 --hashlimit 2/m --hashlimit-mode srcip --hashlimit-htable-expire 180000 -j ACCEPT

Giải thích: từ cùng 1 máy client (--hashlimit-mode srcip => chế độ source ip) nếu có tới 3 kết nối đồng thời (--hashlimit-burst 3) sẽ chỉ cho 2 kết nối trên mỗi phút (--hashlimit 2/m), và những kết nối quá 3 phút sẽ bị ngắt (htable-expire 180000)

1.3.3 OpenSSH MaxStartups

Config trong file : /etc/ssh/sshd_config

MaxStartups 3 # Chỉ cho phép tối đa 3 liên kết xác thực ssh
LogLevel DEBUG # để log level debug để kiểm tra config có hoạt động hay ko

Check file log của ssh /var/log/secure ta sẽ thấy debug1: drop connection #3 là thể hiện kết nối xác thực tới ssh đã bị chặn

Aug 2 11:16:15 sshsrv sshd[1536]: debug1: Forked child 1544.
Aug 2 11:16:15 sshsrv sshd[1544]: Set /proc/self/oom_score_adj to 0
Aug 2 11:16:15 sshsrv sshd[1544]: debug1: rexec start in 5 out 5 newsock 5 pipe 9 sock 10
Aug 2 11:16:15 sshsrv sshd[1544]: debug1: inetd sockets after dupping: 3, 3
Aug 2 11:16:15 sshsrv sshd[1544]: Connection from 172.16.11.10 port 49784
Aug 2 11:16:18 sshsrv sshd[1536]: debug1: drop connection #3
Aug 2 11:16:18 sshsrv sshd[1536]: debug1: drop connection #3

1.4-Giới hạn truy cập từ chính ssh server ra ngoài

Hạn chế chính ssh server truy cập lung tung, ví dụ như server của chúng ta bị tấn công kiểu OS command injection ( hacker sẽ thực tiêm những command của hệ thống vào thông qua web service chẳng hạn để thực hiện ssh đến một máy chủ nào đó nhằm mục đích xấu). Ta lại sử dụng iptables để phòng chống. Config cho chain OUTPUT của iptables như sau:

-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A OUTPUT -p tcp -d 192.168.1.200 --dport 22 -j ACCEPT
-A OUTPUT -j DROP

2.1-Chỉ cho phép ssh protocol version 2 mới được truy cập

Config để phía ssh server chỉ cho phép những client nào sử dụng protocol ver 2 mới được quyền truy cập. Config trong file /etc/ssh/sshd_config như sau

Protocol 2 

2.2-Sử dụng public key thay cho authenticate bằng password

Bình thường ta sẽ login ssh bằng cách nhập password, nhưng để nâng cao tính bảo mật thì ta nên chuyển qua authen bằng public key. Config như sau trong /etc/ssh/sshd_config để đổi từ password sang public key

HostbasedAuthentication no # ko xác thực theo host based 
RhostsAuthentication no # ko xác thực theo host based

RhostsRSAAuthentication no # ko xác thực theo host based RSA
PasswordAuthentication no # ko sử dụng authen bằng password
ChallengeResponseAuthentication no # ko sử dụng authen bằng password
PermitEmptyPasswords no # ko cho phép truy cập bằng password rỗng (đối với user ko setup pass)
RSAAuthentication no # Không authen RSA(version 1 thôi)
PubkeyAuthentication yes # sử dụng public key để authen

Sau khi thiết lập xong ta chạy command sudo service sshd restart để restart lại sshd
Vậy ta sẽ login vào server qua ssh như thế nào sau khi thiết lập như trên. Ta phải

  • 1.Sinh ra cặp khóa (key pair) để dùng xác thực. Chạy câu lệnh sau ở bất kỳ đâu
ssh-keygen -t rsa -P '' -f <path>/mykey
  • 2.Copy public key của cặp khóa lên ssh server vào file ~/.ssh/authorized_keys (lưu ý file này phải để phân quyền là 600 ), mục đích là add public key đã sinh ra vào key được xác thực trên ssh server.
cat mykey.pub >> ~/.ssh/authorized_keys 
  • 3.Lúc ssh vào ssh server ta sử dụng command sau (sử dụng private key để đăng nhập)
ssh <user>@<ssh_server_ip> -i <key_path>/mykey

2.3-Dừng port forward lại

Mục đích là phòng chống việc portforward những port không được public ra ngoài. ssh có kiểu portforward để giúp mở những port từ máy client đến ssh server hoặc những host trong mạng private network của ssh server (ssh tunnel) nên nhiều lúc trở thành lỗ hổng để các hacker khai thác nhằm mục đích truy cập các service trong nội bộ của mạng private phía ssh server (thông thường private network sẽ có bảo mật rất yếu )

  • Config trong file /etc/ssh/sshd_config
AllowTcpForwarding no # cấm TCP port forward 
X11Forwarding no # cấm X11 port forward 

2.4-Không sử dụng port 22 cho ssh nữa

Đổi sshd port trong file /etc/ssh/sshd_config như sau

Port 22222

Lúc này để ssh vào ta phải thiết lập port number từ client ssh <user>@<ssh_server_ip> -p 22222

2.5-hash file known_hosts

Config trong file /etc/ssh/sshd_config như sau

HashKnownHosts yes 

Lúc này file ~/.ssh/known_hosts sẽ bị hash đi kiểu như sau

[hanakosrv@sshsrv .ssh]$ cat ~/ssh/known_hosts
|1| dJaVQ/LE/aKuOy13+Z1NrPNj8Qc=|D6zc9n3ZiXUcWyVN88rLLWw5hgA= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA7g
Bfuo5STGGNxQbNHBElQQvSnwShmmSRGdWDjP9mGgLbZVYu0J6ny6cVGpVvE2aNuVRnc+knT65eHF1aQZ0t+tIGvlV5c+8ObwNo7
MB9yHl2m5AWu5WQ8UcI3ZmXNDapOw5UXKy/viBp9BqPLFNlXLFpMNHkeWubCotc/dZzuVmsZgZ1BG9fJfNdvYjNsbS6WAdpp9qX
zDrl+6nWlLKuUazPvA5r7KZqv0ZSm5rUFGqepFibl0af4Psjmc8y1qVO4wqUm5sNMTBm2XofxTepnVAx5xrehWVPCd17lJcEbrB
WCs/vYmCDun9vHrtEJDGpT8mn4PiYZKKYrsNSOBE/5w==

2.6-Chỉ cho phép 1 số user mới được quyền login

Để đảm bảo tính bảo mật thì ta nên cấm login qua root và chỉ cho phép login bằng 1 user duy nhất. Config trong file /etc/ssh/sshd_config như sau

PermitRootLogin no # ko cho login bằng user root
AllowUsers kyo88 # chỉ cho phép user kyo88 login

Nhớ restart lại sshd nhé

2.7-Ko sử dụng ip v6 thì disable nó đi

Disable trong file /etc/ssh/sshd_config như sau

AddressFamily inet # Đổi từ any sang inet
#ListenAddress :: # Commentout dòng này

2.8-Ko sử dụng thuật toán mã hóa và ko sử dụng mã code yếu

Sử dụng thuật toán mã hoá đối xứng truyền dữ liệu lớn (Symmetric algorithms for encrypting the bulk of transferred data) + thuật toán mã hoá code xác thực (Message authentication code algorithms) mạnh để tăng tính bảo mật. Để kiểm tra config hiện tại chúng ta chạy lệnh sau

[root@sshsrv ~]#ssh -vv localhost
OpenSSH_5.3p1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Applying options for *
debug2: ssh_connect: needpriv 0
debug1: Connecting to localhost [::1] port 22.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: identity file /root/.ssh/identity type -1
debug1: identity file /root/.ssh/identity-cert type -1
debug2: key_type_from_name: unknown key type '-----BEGIN'
debug2: key_type_from_name: unknown key type '-----END'
debug1: identity file /root/.ssh/id_rsa type 1
debug1: identity file /root/.ssh/id_rsa-cert type -1
debug1: identity file /root/.ssh/id_dsa type -1
debug1: identity file /root/.ssh/id_dsa-cert type -1
debug1: identity file /root/.ssh/id_ecdsa type -1
debug1: identity file /root/.ssh/id_ecdsa-cert type -1
debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3
debug1: match: OpenSSH_5.3 pat OpenSSH*
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_5.3
debug2: fd 3 setting O_NONBLOCK
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
debug2: kex_parse_kexinit: ssh-rsa-cert-v01@openssh.com,ssh-dss-cert-v01@openssh.com,ssh-rsa-cert-v00@openssh.com,ssh-dss-cert-v00@openssh.com,ssh-rsa,ssh-dss
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96
debug2: kex_parse_kexinit: hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96
debug2: kex_parse_kexinit: none,zlib@openssh.com,zlib
debug2: kex_parse_kexinit: none,zlib@openssh.com,zlib
debug2: kex_parse_kexinit: 
debug2: kex_parse_kexinit: 
debug2: kex_parse_kexinit: first_kex_follows 0 
debug2: kex_parse_kexinit: reserved 0 
debug2: kex_parse_kexinit: diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
debug2: kex_parse_kexinit: ssh-rsa,ssh-dss
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96
debug2: kex_parse_kexinit: none,zlib@openssh.com
debug2: kex_parse_kexinit: none,zlib@openssh.com
debug2: kex_parse_kexinit: 
debug2: kex_parse_kexinit: 
debug2: kex_parse_kexinit: first_kex_follows 0 
debug2: kex_parse_kexinit: reserved 0 
debug2: mac_setup: found hmac-sha1
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug2: mac_setup: found hmac-sha1
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<2048<8192) sent
debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP
debug2: dh_gen_key: priv key bits set: 155/320

Trong kết quả trên

  • aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc : hiển thị các thuật toán mã hoá đối xứng truyền dữ liệu lớn đang sử dụng. Các thuật toán nên dùng là aes128-ctr,aes192-ctr,aes256-ctr
  • hmac-md5,hmac-sha1,umac-64@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha1-96,hmac-md5-96 : hiển thị thuật toán mã hoá code xác thực đang sử dụng. Các thuật toán nên dùng là hmac-sha2-256,hmac-sha2-512,hmac-sha1.

Để config thuật toán ta config như sau trong file /etc/ssh/sshd_config:

Ciphers aes128-ctr,aes192-ctr,aes256-ctr 
MACs hmac-sha2-256,hmac-sha2-512,hmac-sha1 

3.1-Sử dụng passphare cho private key

Khi sử dụng public key để authen thay cho password, thì ta phải lưu trữ private key nhằm mục đích đăng nhập, để tăng tính bảo mật ta nên đặt passphare cho private key (lúc sử dụng key sẽ phải nhập password) đề phòng trường hợp hacker trộm được file private key của ta. Lúc sinh cặp key pair ta setting password thông qua option -P của lệnh ssh-keygen như sau:

ssh-keygen -t rsa -P '<passphare>' -f <path_file>

3.2-Không để private key trên ssh server

Như tiêu đề thôi :P. Đừng để private key của bạn trên ssh server nhé.

Kết luận

  • Để đêm có thể ăn ngon ngủ yên, hạn chế rủi ro cho những chú server thân yêu, việc thiết lập bảo mật cho ssh là không thể thiếu được. Hy vọng bài viết sẽ giúp cho mọi người quản trị server của mình được tốt hơn, an toàn hơn, tránh xa tụi hacker đặc biệt là hội hacker Tung Của!

Tham khảo