SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor

Sửa lỗi SSH Too Many Authentication Failures

Lỗi Too many authentication failures xảy ra khi SSH gửi quá nhiều key. Dùng ssh -v để chẩn đoán và chỉ định đúng key, tránh vượt MaxAuthTries mặc định là 6.

Ý nghĩa của lỗi "Too many authentication failures"

"Too many authentication failures" có nghĩa là SSH client đã gửi cho server nhiều key hơn số lượng server chấp nhận kiểm tra, nên server đóng kết nối trước khi thử đúng key. Đây gần như luôn là vấn đề ở client. Key nằm trên disk của bạn, server có key đó trong authorized_keys, nhưng cả hai điều này đều không giúp được vì kết nối đã kết thúc quá sớm.

Quy trình xảy ra như sau. ssh-agent chứa mọi private key đã được load vào đó. Client lần lượt gửi từng key cho server vì client không biết account chấp nhận key nào. Server từ chối từng key không có trong authorized_keys và tính mỗi lần từ chối là một lần xác thực thất bại. MaxAuthTries trong sshd_config giới hạn số lần thất bại được phép trong một kết nối. Giá trị mặc định là 6. Nếu agent của bạn chứa 10 key và đúng key đứng thứ 8, server sẽ ngắt kết nối trước khi thử đến key đó.

Vì vậy, cách xử lý là để client chỉ gửi một key: đúng key cần dùng.

SSH server đếm gì và MaxAuthTries được áp dụng ở đâu

Xác thực bằng public key bắt đầu như một trò đoán. Client gửi một public key và hỏi server có chấp nhận chữ ký được tạo bằng key đó không. Server trả lời có hoặc không. Câu trả lời “không” được tính là một lần thử thất bại, giống như nhập sai password.

Trang manual sshd_config(5) mô tả giới hạn này: “Chỉ định số lần thử xác thực tối đa được phép trên mỗi connection. Khi số lần thất bại đạt một nửa giá trị này, các lần thất bại tiếp theo sẽ được ghi vào log. Giá trị mặc định là 6.”

6 lần thử là đủ cho người đang nhập password. Nhưng con số này không nhiều đối với một agent đang giữ 10 key. Khi số lần thất bại đạt đến giới hạn, sshd ngắt connection và ghi một dòng như sau vào system log:

error: maximum authentication attempts exceeded for deploy from 203.0.113.10 port 51292 ssh2

Client của bạn in ra nửa còn lại của cùng sự kiện:

Received disconnect from 203.0.113.10 port 22:2: Too many authentication failures
Disconnected from 203.0.113.10 port 22

Đây là lỗi khác với lỗi SSH permission denied (publickey). Trong trường hợp đó, server đã kiểm tra mọi thứ bạn gửi nhưng không chấp nhận mục nào. Ở đây, server dừng kiểm tra trước đó. Nhầm hai trường hợp này với nhau khiến nhiều người mất cả buổi chiều chép lại một key vốn đã đúng.

Vì sao cùng một key hoạt động trên laptop của đồng nghiệp

Key và server không có gì khác nhau. Agent của họ giữ 2 key, còn agent của bạn giữ 12 key. Key được offer đầu tiên với họ đứng thứ 9 trong danh sách của bạn. Đến lúc đó, connection đã kết thúc.

Số lượng key tăng lên âm thầm. AddKeysToAgent yes trong ~/.ssh/config thêm từng key bạn sử dụng vào agent và giữ key đó ở đó. Các agent của desktop keyring, chẳng hạn như GNOME Keyring trên Linux hoặc login keychain trên macOS, tự động load key khi đăng nhập mà không hỏi. Nếu trong một năm bạn thêm key của client, key của git host và key của một lab box, sẽ có ngày một server vốn luôn hoạt động bắt đầu từ chối bạn. Server không thay đổi. Agent của bạn đã chứa quá nhiều key.

Cách xem các offer bằng ssh -v

Chạy lại kết nối bị lỗi với -v rồi đọc trace.

ssh -v deploy@203.0.113.10

Có 2 loại dòng cần chú ý. Will attempt key: liệt kê các identity mà client đã tập hợp, theo đúng thứ tự client sẽ sử dụng. Offering public key: xuất hiện một lần cho mỗi key thực sự được gửi đến server.

debug1: Will attempt key: /home/you/.ssh/id_ed25519 ED25519 SHA256:AAAA... agent
debug1: Will attempt key: /home/you/.ssh/id_rsa RSA SHA256:BBBB... agent
debug1: Offering public key: /home/you/.ssh/id_ed25519 ED25519 SHA256:AAAA... agent
debug1: Authentications that can continue: publickey,password
debug1: Offering public key: /home/you/.ssh/id_rsa RSA SHA256:BBBB... agent

Các path, loại key và fingerprint của bạn sẽ khác. Bạn cần đếm số dòng Offering public key: trước khi ngắt kết nối. Nếu các offer tiếp tục xuất hiện rồi session kết thúc mà key bạn muốn dùng chưa từng xuất hiện, chẩn đoán đã rõ. Từ agent ở cuối dòng cho biết identity đó đến từ ssh-agent. Từ explicit cho biết identity đó đến từ dòng IdentityFile hoặc từ -i trên command line.

Sau đó kiểm tra agent đang giữ những gì:

ssh-add -l

Mỗi dòng output là một key đã được load. Nếu output là The agent has no identities. thì agent không phải nguyên nhân, và bạn nên kiểm tra các dòng IdentityFile trong ~/.ssh/config. Nếu output là Could not open a connection to your authentication agent. thì không có agent nào đang chạy, và các offer đến từ các file key mặc định của bạn.

Khắc phục 1: IdentitiesOnly với một key cho mỗi host

IdentitiesOnly yes yêu cầu ssh chỉ gửi các identity bạn đã cấu hình và bỏ qua những identity bổ sung mà agent tự đưa ra. Kết hợp với một dòng IdentityFile, client chỉ gửi một lần thử xác thực.

Host vps
  HostName 203.0.113.10
  User deploy
  IdentityFile ~/.ssh/id_ed25519_vps
  IdentitiesOnly yes

Lưu cấu hình đó vào ~/.ssh/config, rồi chạy chmod 600 ~/.ssh/config. Nếu file cho phép group hoặc mọi user ghi, ssh sẽ từ chối chạy và báo Bad owner or permissions on /home/you/.ssh/config. Khi đó, ssh vps chỉ cung cấp một key, còn ssh -v vps phải hiển thị chính xác một dòng Offering public key:.

Có 2 chi tiết thường gây bất ngờ.

  • Chỉ có IdentitiesOnly yes không có nghĩa là “một key”. Nếu không có dòng IdentityFile, các file identity mặc định vẫn được tính là identity đã cấu hình, nên ssh vẫn thử ~/.ssh/id_ed25519, ~/.ssh/id_rsa và các file mặc định khác mà nó tìm thấy. Bạn cũng cần dòng IdentityFile: ngay khi đặt dòng này, ssh sẽ ngừng tự thêm các identity mặc định.
  • Agent vẫn thực hiện việc ký. IdentitiesOnly kiểm soát những key được gửi, không kiểm soát thành phần thực hiện việc ký. Nếu private key được chỉ định bởi IdentityFile đã được load trong agent, agent sẽ tạo chữ ký và bạn không bị hỏi passphrase. Bạn cũng có thể trỏ IdentityFile đến file .pub tương ứng. Cách này được dùng khi private key chỉ nằm trong agent hoặc trên hardware token.

Một bẫy trong ~/.ssh/config có thể âm thầm làm mất tác dụng của cách khắc phục này. Hầu hết keyword sử dụng giá trị đầu tiên được tìm thấy. Vì vậy, các block Host cụ thể phải nằm trước Host *. IdentityFile không tuân theo quy tắc đó. Manual ghi rõ: “Có thể chỉ định nhiều identity file trong các file cấu hình; tất cả identity này sẽ được thử lần lượt.” Một IdentityFile trong Host * sẽ được thêm vào identity cho từng host, thay vì bị thay thế. Vì vậy, một dòng cấu hình global bị bỏ quên sẽ đưa thêm một lần thử xác thực vào mọi connection.

Nếu muốn có lớp bảo vệ global, chỉ đặt flag này ở cuối file:

Host *
  IdentitiesOnly yes

Khi đó, mỗi host phải có IdentityFile riêng. Đây cũng là kết quả bạn muốn. Đặt tên một key cho mỗi server còn giúp bạn thu hồi quyền truy cập của một máy riêng lẻ sau này mà không phải cấp lại mọi thứ. Nên hình thành thói quen này sớm: xem cách quản lý SSH key cho từng máy.

Sửa 2: xóa key khỏi agent hoặc khởi động lại agent

Nếu chưa thể chỉnh sửa config, hãy xóa toàn bộ key khỏi agent rồi chỉ nạp những key bạn cần.

ssh-add -l                    # list what is loaded
ssh-add -d ~/.ssh/id_rsa      # remove one key
ssh-add -D                    # remove every key
ssh-add ~/.ssh/id_ed25519_vps # load the one you need

Nếu kết nối hoạt động ngay sau ssh-add -D, agent là nguyên nhân. Hãy xem đây là bước kiểm tra, không phải cách sửa triệt để. Desktop keyring agent sẽ nạp lại các key trong lần đăng nhập tiếp theo, nên ngày mai sự cố sẽ quay lại. Một dòng IdentitiesOnly trong ~/.ssh/config vẫn còn sau khi reboot. Agent không có key thì không.

Bạn cũng có thể đặt thời hạn cho một key để agent tự xóa key đó:

ssh-add -t 1800 ~/.ssh/id_ed25519_vps

Key sẽ bị xóa sau 1800 giây kể từ khi được thêm vào. Khởi động lại agent cũng có tác dụng, nhưng cách thực hiện phụ thuộc vào thành phần đã khởi động agent. Một ssh-agent do bạn tự chạy sẽ dừng bằng ssh-agent -k. Nếu bạn chạy agent từ systemd user unit do mình tạo, hãy khởi động lại unit đó bằng systemctl --user restart <unit>. Keyring agent sẽ khởi động lại cùng desktop session.

Khắc phục 3: lệnh chạy một lần cho server chỉ truy cập một lần

Với một host không thêm vào config, đặt các thiết lập tương tự ngay trên command line:

ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10

Chỉ dùng -i là cách khắc phục sai phổ biến nhất. -i thêm một key vào danh sách identity. Nó không xóa các key của agent khỏi danh sách đó, nên tất cả các key khác vẫn được gửi trước key của bạn và kết nối vẫn bị ngắt khi chạm giới hạn. Chạy ssh -v -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10 mà không có IdentitiesOnly sẽ khiến bạn thấy các key của agent được gửi trước. -i cần đi kèm với -o IdentitiesOnly=yes.

Để loại bỏ hoàn toàn agent khỏi một kết nối:

ssh -o IdentityAgent=none -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10

Sau đó, ssh đọc private key từ disk và hỏi passphrase nếu key có passphrase.

Các tool xây dựng trên ssh cũng chấp nhận option tương tự:

scp -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps report.tar.gz deploy@203.0.113.10:/tmp/
rsync -av -e "ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps" ./site/ deploy@203.0.113.10:/srv/site/
GIT_SSH_COMMAND="ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps" git clone git@example.com:team/repo.git

Vì sao lỗi xuất hiện ở hop thứ hai

Với ForwardAgent yes, agent socket được cung cấp trên server mà bạn kết nối đến. Lệnh ssh chạy trên server đó sẽ dùng agent local của bạn, cùng toàn bộ key của bạn, thông qua socket được forward. Vì vậy, lỗi có thể xuất hiện ở hop từ jump host đến server đích, trong khi hop đầu tiên vẫn hoạt động bình thường. Chạy echo $SSH_AUTH_SOCK trên máy trung gian: output rỗng nghĩa là không có agent nào có thể truy cập. Nếu thấy một socket path, nghĩa là có agent, nhưng chưa chắc đó là agent của bạn, vì một agent được khởi động trên máy đó cũng có thể đặt cùng biến này. Chạy thêm ssh-add -l tại đó: nếu lệnh liệt kê các key từ máy của bạn, forwarding đang hoạt động.

Agent forwarding còn có một rủi ro khác. Bất kỳ ai có quyền root trên máy trung gian đều có thể dùng agent của bạn để xác thực dưới danh nghĩa bạn trong suốt thời gian session còn mở. ProxyJump tránh được cả 2 vấn đề:

ssh -J deploy@jump.example.com deploy@10.0.0.5

ProxyJump mở connection thông qua jump host và xác thực với server đích từ chính máy của bạn. Vì vậy, cấu hình ~/.ssh/config local được áp dụng ở mọi hop, bao gồm cả IdentitiesOnly. Tắt ForwardAgent là một bước tiêu chuẩn khi hardening SSH trên VPS.

Có nên tăng MaxAuthTries trên server không?

Thông thường là không. Trước tiên, kiểm tra giá trị hiện tại:

sudo sshd -T | grep -i maxauthtries

sshd -T in ra cấu hình có hiệu lực, bao gồm cả giá trị mặc định, nên cho biết giá trị thực ngay cả khi sshd_config không đề cập đến tùy chọn này. Thêm -C user=deploy,host=example.com,addr=203.0.113.10 nếu bạn dùng các block Match, vì chúng được đánh giá theo từng connection và nếu không có tùy chọn này thì sẽ bị bỏ qua.

Tăng giới hạn có tác dụng theo nghĩa hẹp: một con số lớn hơn cho client hoạt động sai thêm cơ hội để thử:

MaxAuthTries 20

Kiểm tra file rồi reload service. Giữ một session thứ hai mở trong lúc thực hiện:

sudo sshd -t
sudo systemctl reload ssh      # Debian and Ubuntu
sudo systemctl reload sshd     # RHEL family

Nếu systemctl is-enabled ssh.socket báo enabled trên Ubuntu 24.04, sshd được kích hoạt bằng socket. ssh.socket của Ubuntu không khởi động một daemon mới cho từng connection. Nó khởi động ssh.service khi connection đầu tiên đến, rồi service đó tiếp tục chạy và xử lý các connection sau đó. Lệnh reload ở trên vẫn là cách áp dụng thay đổi. Nếu ssh.service chưa active thì không có gì để reload, và connection tiếp theo sẽ khởi động nó với file mới.

Bây giờ xem thay đổi đó đã làm gì. Client đang gửi các key mà server này sẽ không bao giờ chấp nhận. Tăng giới hạn khiến server xử lý 20 key bị từ chối cho mỗi connection thay vì 6 key, áp dụng cho mọi client kết nối và mọi đối tượng đoán password trên Internet. Mỗi lần thử khiến server phải tra cứu trong authorized_keys. Đăng nhập của bạn vẫn chậm vì key đúng vẫn nằm cuối danh sách. Thêm key thứ 13 vào agent là bạn lại quay về tình trạng ban đầu và phải tiếp tục tăng giới hạn.

Chỉ tăng giới hạn khi một client hợp lệ thực sự cần gửi nhiều identity. Trong mọi trường hợp khác, hãy sửa client. Sau khi mọi user đăng nhập bằng key đã cấu hình, giảm giới hạn là một biện pháp hardening hợp lý vì con số nhỏ hơn khiến đối tượng đoán password có ít lần thử hơn trong mỗi connection.

Vì sao fail2ban có thể ban địa chỉ của bạn trong trường hợp này

sshd không ghi log mọi key bị từ chối. Ở LogLevel INFO mặc định, key bị từ chối của một account hợp lệ chỉ được ghi vào log khi số lần kết nối thất bại đạt một nửa MaxAuthTries. Đây là ý của câu trong manual: “Once the number of failures reaches half this value, additional failures are logged.” Với giá trị mặc định là 6, 3 lần offer bị từ chối đầu tiên không được ghi vào log. 3 lần cuối xuất hiện dưới dạng các dòng như sau, tiếp đó là dòng maximum authentication attempts exceeded:

Failed publickey for deploy from 203.0.113.10 port 51292 ssh2: ED25519 SHA256:AAAA...

Các dòng này trông như nhiều lần thất bại, nhưng filter sshd của fail2ban không đếm chúng. Giá trị mặc định đi kèm fail2ban, publickey = nofail, đọc một dòng Failed publickey của user hợp lệ chỉ để lấy địa chỉ và tên user. Dòng được đếm là maximum authentication attempts exceeded, vì vậy một connection chạm giới hạn chỉ cộng 1 lần thất bại, không phải nhiều lần. Jail sẽ ban địa chỉ nguồn khi có maxretry lần thất bại trong findtime. jail.conf của fail2ban đặt các giá trị này lần lượt là 5 và 10 phút. Khoảng 5 connection thất bại trong 10 phút là đủ để ban địa chỉ của chính bạn. Một script hoặc tool retry theo vòng lặp sẽ đạt ngưỡng này rất nhanh.

Sau đó triệu chứng thay đổi, và đây là phần khiến nhiều người nhầm lẫn. Bạn không còn thấy “Too many authentication failures” mà không thấy phản hồi nào: connection bị treo rồi timeout, vì firewall hiện đang drop packet thay vì trả lời. Timeout trong khi trước đó bạn nhận được thông báo lỗi là dấu hiệu cần chú ý. Phân biệt này được giải thích trong SSH connection bị từ chối so với SSH connection bị timeout.

Từ console của provider, hoặc từ một địa chỉ khác, hãy kiểm tra jail và gỡ ban:

sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.10

Đặt địa chỉ của bạn vào ignoreip trong jail.local trong lúc xử lý client, rồi xóa địa chỉ đó sau khi hoàn tất. Jail được cấu hình trong guide fail2ban cho Ubuntu 24.04.

Cần làm một lần để lỗi này không quay lại

Cấp cho mỗi server một block Host riêng trong ~/.ssh/config, kèm theo HostName, User, IdentityFile và IdentitiesOnly yes. Sau đó, ssh vps sẽ ngắn và dễ nhập, chỉ cung cấp đúng một key, đồng thời không thể làm MaxAuthTries lỗi dù agent của bạn có đầy bao nhiêu key. Cách này cũng giữ cho output của ssh -v đủ ngắn để đọc được khi một lỗi khác xảy ra.

FAQ

Làm thế nào để sửa lỗi "Too many authentication failures" ngay bây giờ?

Chỉ cung cấp một key thay vì tất cả key. Để kết nối ngay, chạy ssh -o IdentitiesOnly=yes -i ~/.ssh/your_key user@host. Để sửa vĩnh viễn, thêm một block vào ~/.ssh/config với HostName, User, IdentityFile trỏ đến key đó, rồi thêm IdentitiesOnly yes, sau đó chạy chmod 600 ~/.ssh/config. Xác nhận bằng ssh -v: bạn phải thấy một dòng Offering public key: cho host đó.

Vì sao ssh -i vẫn cung cấp các key khác?

Vì -i thêm một identity vào danh sách, chứ không giới hạn danh sách. Các key đã nạp trong ssh-agent vẫn nằm trong danh sách và vẫn được cung cấp, thường là trước key của bạn. Vì vậy server vẫn có thể chạm tới MaxAuthTries trước khi đến key của bạn. -o IdentitiesOnly=yes là option giới hạn ssh chỉ dùng các identity bạn chỉ định. Dùng -i và -o IdentitiesOnly=yes cùng nhau, hoặc dùng -o IdentityAgent=none để bỏ qua agent hoàn toàn cho kết nối đó.

Có nên tăng MaxAuthTries trên server để sửa lỗi này không?

Không, trong gần như mọi trường hợp. Client đang gửi các key mà server này sẽ không bao giờ chấp nhận. Tăng giới hạn chỉ khiến server kiểm tra thêm các lần cung cấp bị từ chối trong mỗi kết nối, áp dụng cho mọi client và mọi lần brute force đến được server. Lỗi cũng sẽ tái diễn ngay khi có thêm một key được nạp vào agent của bạn. Nếu muốn kiểm tra, xem giá trị thực tế bằng sudo sshd -T | grep -i maxauthtries, rồi sửa phía client bằng IdentitiesOnly.

Vì sao lỗi này bắt đầu xảy ra trên một server vẫn hoạt động bình thường vào tháng trước?

Agent của bạn đã có nhiều key hơn. AddKeysToAgent yes trong ~/.ssh/config giữ mỗi key bạn sử dụng ở trạng thái đã nạp, còn các desktop keyring agent tự nạp key khi đăng nhập. Khi số key đã nạp vượt quá MaxAuthTries của server, mọi server có key nằm gần cuối thứ tự cung cấp sẽ bắt đầu lỗi. Chạy ssh-add -l và so sánh số lượng với giới hạn trên server.

Lỗi này có thể khiến fail2ban ban địa chỉ IP của tôi không?

Có, dù chậm hơn những gì log của server thể hiện. Bộ lọc sshd mặc định của fail2ban không đếm các dòng Failed publickey đối với user hợp lệ. Nó đếm dòng maximum authentication attempts exceeded, nên mỗi kết nối chạm giới hạn được tính là một lần thất bại. Với các giá trị mặc định đi kèm là maxretry = 5 và findtime = 10m, khoảng 5 kết nối như vậy trong 10 phút sẽ ban địa chỉ của bạn. Dấu hiệu là lỗi chuyển thành trạng thái treo rồi timeout, vì các packet bị drop thay vì nhận phản hồi. Xóa ban từ console bằng sudo fail2ban-client set sshd unbanip <your address>, rồi sửa client trước khi kết nối lại.

#SSH#ssh-agent#openssh#ssh-config#troubleshooting