Java获取AWS EC2实例公网IP时返回401错误的问题
问题解答
获取EC2实例公网IP的IMDS元数据路径不会随AWS区域变化,http://169.254.169.254/latest/meta-data/public-ipv4是全局统一的。你遇到的401错误和区域无关,核心原因是IMDSv2强制要求先获取会话令牌(Session Token),才能访问元数据接口,而你的代码直接跳过了令牌获取步骤。
问题根源
- 你在eu-central区域的实例可能允许IMDSv1回退(默认配置可能未强制IMDSv2),所以直接访问能成功;
- ap-south区域的实例大概率被配置为强制启用IMDSv2(禁止IMDSv1访问),因此无令牌的请求会被拒绝,返回401 Unauthorized。
正确的IMDSv2实现代码
使用IMDSv2访问元数据需要两步:先发送PUT请求获取会话令牌,再携带令牌访问目标元数据接口。以下是适配你的场景的Java实现:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class EC2MetadataUtils { private static final String IMDS_BASE_URL = "http://169.254.169.254/latest/meta-data/"; private static final String TOKEN_URL = "http://169.254.169.254/latest/api/token"; private static final int TOKEN_TTL = 21600; // 令牌有效期,最长6小时 public String findCurrentPublicIp() throws IOException { // 第一步:获取IMDSv2会话令牌 String token = getIMDSv2Token(); // 第二步:携带令牌访问公网IP元数据 URL publicIpUrl = new URL(IMDS_BASE_URL + "public-ipv4"); HttpURLConnection connection = (HttpURLConnection) publicIpUrl.openConnection(); connection.setRequestProperty("X-aws-ec2-metadata-token", token); try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { return reader.readLine(); } finally { connection.disconnect(); } } private String getIMDSv2Token() throws IOException { URL tokenUrl = new URL(TOKEN_URL); HttpURLConnection connection = (HttpURLConnection) tokenUrl.openConnection(); connection.setRequestMethod("PUT"); connection.setRequestProperty("X-aws-ec2-metadata-token-ttl-seconds", String.valueOf(TOKEN_TTL)); try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { return reader.readLine(); } finally { connection.disconnect(); } } }
额外排查点
- 检查CloudFormation模板中EC2实例的
MetadataOptions配置:确认ap-south区域的实例是否设置了HttpTokens: required(强制IMDSv2),而eu-central区域可能是optional(允许IMDSv1)。示例CloudFormation片段:
Resources: MyEC2Instance: Type: AWS::EC2::Instance Properties: # 其他配置... MetadataOptions: HttpTokens: required # 强制IMDSv2,会拒绝无令牌请求 HttpPutResponseHopLimit: 1
- 确保你的IMDSv2客户端版本(imds-2.20.11.jar)配置正确,或者直接使用上述原生实现避免依赖问题。
内容的提问来源于stack exchange,提问作者slow_learner
相关产品推荐
相关产品推荐

