Spring Boot(Java)
Spring Boot アプリケーションは、標準の OncePerRequestFilter または HandlerInterceptor コンポーネントを使用して受信リクエストをインターセプトします。ProxyTracer をサーブレットフィルターとして追加することで、すべての受信 HTTP リクエストが @RestController エンドポイントに到達する前に確実に評価されます。
インターセプターの実装
このフィルターはクライアント IP アドレスを抽出し(X-Forwarded-For ヘッダーを安全に処理)、Spring の RestClient または RestTemplate を使用して ProxyTracer への HTTP 呼び出しを行い、プロキシが検出された場合に 403 Forbidden エラーを HttpServletResponse に直接書き込みます。
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
@Component
public class ProxyTracerInterceptor implements HandlerInterceptor {
private static final String API_KEY = System.getenv("PROXYTRACER_API_KEY");
private final HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofMillis(500)) // ボトルネックを防ぐための厳格なタイムアウト
.build();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1. ロードバランサー/NGINXの背後にある実際のIPを安全に抽出
String ipAddress = request.getHeader("X-Forwarded-For");
if (ipAddress == null || ipAddress.isEmpty()) {
ipAddress = request.getRemoteAddr();
} else {
ipAddress = ipAddress.split(",")[0].trim();
}
// 2. ProxyTracer APIにクエリを実行
HttpRequest ptRequest = HttpRequest.newBuilder()
.uri(URI.create("https://api.proxytracer.com/v1/check/" + ipAddress))
.header("Authorization", "Bearer " + API_KEY)
.GET()
.build();
try {
HttpResponse<String> ptResponse = httpClient.send(ptRequest, HttpResponse.BodyHandlers.ofString());
if (ptResponse.statusCode() == 200) {
// 3. シンプルな文字列マッチング (最高速度を確保するため重いJSONパースライブラリを回避)
if (ptResponse.body().contains("\"proxy\": true") || ptResponse.body().contains("\"proxy\":true")) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.getWriter().write("{\"error\": \"Access Denied: VPN or Proxy detected.\"}");
response.setContentType("application/json");
return false; // リクエストを破棄
}
}
} catch (Exception e) {
// フェイルオープン: エラーをログに記録し、リクエストの通過を許可
System.err.println("ProxyTracer validation failed: " + e.getMessage());
}
// 4. トラフィックは正常です。コントローラーへ処理を渡します
return true;
}
}設定:
設定手順: フィルタークラスに @Component アノテーションを付与するか、SecurityFilterChain Bean に登録して実行順序を指定します。
最終更新日: