GIẢI MÃ LỖI: CÚ LỪA TỪ ĐỊA CHỈ IP "MA THUẬT" 169.254.169.254
đây là một trong những lỗi "kinh điển" và phổ biến nhất mà các kỹ sư Backend gặp phải khi hệ thống bắt đầu tương tác với các dịch vụ của AWS (như tải file lên S3, đẩy message vào SQS, hoặc gửi email qua SES).
Nhìn lướt qua, có vẻ như hệ thống của bạn đang bị lỗi mạng (cURL error 7). Nhưng thực chất, đây là lỗi thiếu thông tin xác thực (Missing Credentials) bị hệ thống che giấu dưới dạng một lỗi timeout mạng.
1. Địa chỉ IP 169.254.169.254 là gì?
Trong thế giới điện toán đám mây (đặc biệt là AWS), 169.254.169.254 là một địa chỉ IP nội bộ (Link-local address) cực kỳ đặc biệt. Nó là cổng giao tiếp của Instance Metadata Service (IMDS).
Bất kỳ một máy chủ ảo EC2 nào chạy trên AWS cũng có thể gọi vào IP này để tự hỏi: "Tôi là ai? Tôi đang chạy ở Region nào? Quyền hạn (IAM Role) của tôi là gì?".
2. Tại sao Laravel/PHP SDK lại tự nhiên gọi vào IP này?
Trong Laravel, khi bạn cài đặt AWS SDK (ví dụ thông qua thư viện league/flysystem-aws-s3-v3 để làm việc với S3), SDK này được lập trình theo một quy tắc gọi là Default Credential Provider Chain (Chuỗi cung cấp chứng chỉ mặc định).
Khi bạn yêu cầu Laravel kết nối với AWS, nó sẽ đi tìm chìa khóa (Credentials) theo đúng thứ tự ưu tiên sau:
-
Tìm trong biến môi trường (
.env- AWS_ACCESS_KEY_ID). -
Nếu không có, nó tìm trong file cấu hình aws ở thư mục
~/.aws/credentials. -
Nếu vẫn không có, SDK giả định rằng: "Chắc code này đang được chạy trên máy chủ AWS EC2, để mình gõ cửa IP
169.254.169.254để xin quyền (IAM Role) tự động".
Và thế là lỗi xảy ra!
3. Ba Kịch Bản Gây Ra Lỗi Và Cách Xử Lý
Tùy vào môi trường bạn đang chạy code (WSL Ubuntu, Railway, hay AWS thực tế), lỗi này sẽ rơi vào 1 trong 3 kịch bản sau:
Kịch Bản 1: Bạn đang chạy code ở Local (WSL/Docker) hoặc Server không phải của AWS (Railway, Vultr, On-Premise)
-
Nguyên nhân: Bạn gọi lệnh upload file lên S3, nhưng trong file
.envcủa bạn đang bị thiếu, bị sai tên biến, hoặc cache chưa nhận biếnAWS_ACCESS_KEY_IDvàAWS_SECRET_ACCESS_KEY.Vì không tìm thấy key trong
.env, Laravel SDK chuyển sang Bước 3 (gọi vào IP 169.254.169.254). Nhưng vì máy tính của bạn (hoặc server Railway) không phải là máy ảo AWS, nên IP này không tồn tại. Lệnh cURL bị treo 4 mili-giây rồi văng ra lỗi TimeoutcURL error 7. -
Cách khắc phục:
Kiểm tra lại file
.env, đảm bảo khai báo chính xác và đầy đủ 4 biến sau. Sau đó chạyphp artisan config:clearđể Laravel nhận cấu hình mới.Đoạn mã
AWS_ACCESS_KEY_ID=AKIA... AWS_SECRET_ACCESS_KEY=YOUR_SECRET... AWS_DEFAULT_REGION=ap-southeast-1 AWS_BUCKET=your-bucket-name
Kịch Bản 2: Bạn đang chạy trên máy chủ AWS EC2 thực sự, nhưng code nằm trong Docker Container
-
Nguyên nhân: Đây là cái bẫy rất đau mạng tên là IMDSv2 Hop Limit. Trên AWS EC2 đời mới, dịch vụ Metadata yêu cầu khoảng cách mạng (network hop) mặc định bằng 1 để chống rò rỉ bảo mật. Tuy nhiên, khi bạn bọc code Laravel vào trong Docker, Docker sinh ra một lớp mạng ảo riêng (Bridge Network). Khi code từ trong Docker gọi ra IP 169.254.169.254, nó bị cộng thêm 1 hop (thành 2 hops), nên bị AWS chặn đứng ngay lập tức (Timeout).
-
Cách khắc phục: Bạn không cần điền file
.env(vì dùng IAM Role an toàn hơn). Thay vào đó, bạn phải báo với AWS nâng giới hạn Hop Limit của máy chủ EC2 đó lên 2 bằng lệnh AWS CLI sau:Bash
aws ec2 modify-instance-metadata-options \ --instance-id i-1234567890abcdef0 \ --http-put-response-hop-limit 2 \ --http-endpoint enabled
Kịch Bản 3: Chạy trên AWS EC2, không dùng Docker, nhưng quên gán Quyền (IAM Role)
-
Nguyên nhân: Code tìm đến được IP 169.254.169.254, nhưng bản thân máy chủ EC2 đó chưa được gán bất kỳ một "Identity" (IAM Role) nào, nên nó không lấy được Security Credentials trả về.
-
Cách khắc phục: Truy cập AWS Console Mở máy ảo EC2 đó lên Actions Security Modify IAM role Gán cho nó một Role có quyền truy cập S3/SQS tương ứng.
💡 Lời Kết
Khi nhìn thấy lỗi cURL error 7: 169.254.169.254, đừng bao giờ đi tìm cách sửa lỗi cấu hình mạng hay mở port firewall. Hãy nhớ ngay đến nguyên lý: Hệ thống đang bị thiếu chìa khóa (Credentials), nên nó đang tuyệt vọng đi tìm chìa khóa ở địa chỉ dự phòng của AWS và thất bại. Tùy vào môi trường (Local hay AWS) mà bạn quyết định cấp phát Key qua .env hay cấp phát quyền qua EC2 IAM Role.
All rights reserved