Sửa lỗi SSH Too Many Authentication Failures
Lỗi “Too many authentication failures” thường do SSH agent gửi hết key đang giữ. Dùng ssh -v để kiểm tra và giới hạn client chỉ gửi đúng key cần dùng.
Ý 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.
Máy chủ đếm gì và MaxAuthTries liên quan như thế nào
Xác thực bằng public key bắt đầu như một quá trình thử lần lượt. Client gửi một public key và hỏi máy chủ có chấp nhận chữ ký được tạo bằng key đó hay không. Máy chủ trả lời có hoặc không. Một câu trả lời “không” được tính là một lần thử thất bại, giống hệt như nhập sai mật khẩu.
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 kết nối. 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 log. Giá trị mặc định là 6.”
6 lần thử là đủ cho người đang nhập mật khẩu. 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 vượt quá giới hạn, sshd ngắt kết nối 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 ssh2Client 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à một lỗi khác với lỗi SSH permission denied (publickey). Trong trường hợp đó, máy chủ đã kiểm tra mọi thứ bạn gửi nhưng không chấp nhận key nào. Ở đây, máy chủ đã dừng kiểm tra trước khi hoàn tất. Nhầm hai trường hợp này với nhau khiến bạn 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.10Có 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... agentCá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 -lMỗ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.
Cách 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 khác mà agent tự cung cấp. Kết hợp nó với một dòng IdentityFile, client sẽ chỉ gửi một lần chào key.
Host vps
HostName 203.0.113.10
User deploy
IdentityFile ~/.ssh/id_ed25519_vps
IdentitiesOnly yesLưu cấu hình đó vào ~/.ssh/config, sau đó 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 sẽ hiển thị đúng một dòng Offering public key:.
Có 2 điểm thường khiến người dùng bất ngờ.
IdentitiesOnly yestự nó không có nghĩa là “một key”. Các identity file 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_rsavà những file mặc định khác mà nó tìm thấy. Bạn cũng cần dòngIdentityFile.- Agent vẫn thực hiện việc ký.
IdentitiesOnlykiểm soát key nào được cung cấp, 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ởiIdentityFileđã được load trong agent, agent sẽ tạo chữ ký và bạn không bao giờ được hỏi passphrase. Bạn thậm chí có thể trỏIdentityFileđến file.pubtương ứng. Cách này dùng khi private key chỉ tồn tại 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 dùng giá trị đầu tiên được tìm thấy. Vì vậy, các block Host cụ thể phải đặt phía trên Host *. IdentityFile không tuân theo quy tắc đó. Manual ghi: “Có thể chỉ định nhiều identity file trong các file cấu hình; tất cả identity này sẽ lần lượt được thử.” Một IdentityFile bên dưới Host * sẽ được thêm vào identity theo từng host, thay vì thay thế identity đó. Vì vậy, một dòng cấu hình global bị bỏ quên sẽ đưa thêm một lần chào key vào mọi connection.
Nếu muốn có một lớp bảo vệ global, chỉ đặt flag ở cuối file:
Host *
IdentitiesOnly yesMỗi host sau đó cần có IdentityFile riêng. Đây cũng chính là kết quả bạn muốn. Đặt tên một key cho mỗi server còn giúp revoke 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 theo 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 needNế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_vpsKey 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.10Chỉ 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.10Sau đó, 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.gitVì 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ẽ sử dụng agent cục bộ 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, dù 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: nếu có đường dẫn socket thì agent được forward đang khả dụng; output rỗng nghĩa là không có agent.
Agent forwarding có thêm một rủi ro. 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 với danh tính của bạn trong suốt thời gian session còn mở. ProxyJump tránh được cả hai vấn đề:
ssh -J deploy@jump.example.com deploy@10.0.0.5ProxyJump mở kết nối qua jump host và xác thực với server đích từ chính máy của bạn. Vì vậy, ~/.ssh/config cục bộ đượ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 là không. Trước tiên, kiểm tra giá trị hiện tại:
sudo sshd -T | grep -i maxauthtriessshd -T in cấu hình hiệu lực, bao gồm cả giá trị mặc định, nên nó báo đúng giá trị thực ngay cả khi sshd_config không hiển thị gì về tùy chọn đó. Nếu dùng các block -C user=deploy,host=example.com,addr=203.0.113.10, hãy thêm 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, nhưng chỉ theo nghĩa hẹp: giá trị lớn hơn cho client hoạt động không đúng thêm nhiều lượt thử hơn:
MaxAuthTries 20Kiể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 familyNếu systemctl is-enabled ssh.socket báo enabled trên Ubuntu 24.04, sshd được kích hoạt bằng socket: mỗi connection khởi chạy một process mới và đọc lại sshd_config, nên các connection mới sẽ tự nhận thay đổi.
Bây giờ hãy xem thay đổi đó thực sự giải quyết được 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 kẻ thử mật khẩu trên Internet. Mỗi key khiến server phải tra cứu trong authorized_keys. Lần đăng nhập của bạn vẫn chậm vì key đúng vẫn ở cuối danh sách. Thêm key thứ 13 vào agent, rồi bạn lại quay về tình trạng ban đầu và tiếp tục yêu cầu 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 đều đăng nhập bằng key đã cấu hình, có thể giảm giới hạn để hardening, vì giá trị nhỏ hơn khiến kẻ đoán mật khẩu có ít lượt thử hơn trên mỗi connection.
Vì sao fail2ban có thể ban bạn trong trường hợp này
Ở log level mặc định, sshd ghi lại mỗi lần từ chối public key:
Failed publickey for deploy from 203.0.113.10 port 51292 ssh2: ED25519 SHA256:AAAA...Một kết nối từ agent có quá nhiều key sẽ tạo ra nhiều dòng như vậy từ cùng một địa chỉ trong vòng một hoặc hai giây. Jail fail2ban sshd đếm các dòng lỗi của sshd và ban địa chỉ nguồn khi đạt maxretry trong khoảng thời gian findtime. Các khoảng thời gian này mặc định khá ngắn, nên hai lần retry một kết nối bị lỗi cũng có thể đủ để ban địa chỉ của chính bạn.
Sau đó triệu chứng sẽ thay đổi. Đây là phần khiến nhiều người nhầm lẫn. Bạn không còn thấy lỗi "Too many authentication failures" mà không thấy phản hồi nào: kết nối treo rồi timeout, vì firewall lúc này đang drop packet của bạn thay vì phản hồi. Timeout trong khi trước đó bạn nhận được thông báo lỗi là dấu hiệu quan trọng. Phân biệt này được giải thích trong SSH bị từ chối kết nối và SSH bị timeout khi kết nối.
Từ console của nhà cung cấp hoặc từ một địa chỉ khác, kiểm tra jail và gỡ ban:
sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.10Thêm địa chỉ của bạn vào ignoreip trong jail.local trong lúc xử lý client, rồi xóa địa chỉ đó khi hoàn tất. Cách thiết lập jail được trình bày trong hướng dẫn 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 ngay lỗi "Too many authentication failures"?
Chỉ cung cấp một key thay vì cung cấp tất cả key. Để kết nối ngay, chạy ssh -o IdentitiesOnly=yes -i ~/.ssh/your_key user@host. Để sửa lâu dài, 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 đó.
Tại sao ssh -i vẫn cung cấp các key khác của tôi?
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 đã được load 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 MaxAuthTries trước khi đến key của bạn. -o IdentitiesOnly=yes là option giới hạn ssh chỉ sử 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 trong 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. Giới hạn lớn hơn chỉ khiến server xử lý thêm các lần cung cấp bị từ chối trong mỗi kết nối, đối với mọi client và mọi lần brute force truy cập được vào server. Lỗi cũng sẽ xuất hiện lại ngay khi có thêm một key được load vào agent. Nếu muốn kiểm tra, dùng sudo sshd -T | grep -i maxauthtries để xem giá trị thực tế, rồi sửa client bằng IdentitiesOnly.
Tại sao lỗi này bắt đầu xuất hiện trên 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 luôn được load, còn các desktop keyring agent tự load key khi đăng nhập. Khi số key đã load vượt quá MaxAuthTries của server, mọi server có key nằm muộn trong thứ tự cung cấp bắt đầu bị 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ó. Mỗi key bị từ chối tạo ra một dòng Failed publickey for ... trong log của server. Vì vậy, một kết nối có thể tạo ra nhiều lần lỗi từ địa chỉ của bạn chỉ trong vài giây. Jail fail2ban sshd sẽ ban địa chỉ khi đạt maxretry trong khoảng thời gian findtime. Dấu hiệu dễ nhận biết là lỗi chuyển thành trạng thái treo rồi timeout, vì các packet đang bị drop thay vì được phản hồi. Xóa lệnh 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.