- 新しい順
- 投票が多い順
- コメントが多い順
Why the Referer Header Changes After WAF Challenges
The behavior you're experiencing with lost Referer headers after WAF challenges is expected due to how the challenge mechanism works. Here's what's happening:
Initial Request Flow:
User clicks a link from Google search results
Browser sends request with Referer: https://www.google.com/
AWS WAF intercepts this request and identifies it needs a challenge
Challenge Process:
WAF returns a challenge page (with challenge.js) instead of your actual content
This challenge page runs in the user's browser at your domain
The challenge script completes silently in the background
Post-Challenge Request:
After successful challenge completion, the browser makes a new request
This new request originates from your domain (the challenge page)
Browser sets the Referer to your page URL, not the original Google URL
The original referer is lost in the standard HTTP flow
This happens because the WAF challenge creates a new browser context - essentially a client-side redirect - which changes the Referer according to standard browser behavior. Technical Solutions to Preserve the Original Referer
Since you've already confirmed the original referer is stored in Local Storage but not being used, here are several approaches to solve this issue:
- Custom Request Headers with Lambda@Edge
Use Lambda@Edge to add a custom header containing the original referer:
// Lambda@Edge Viewer Request function exports.handler = async (event) => { const request = event.Records[0].cf.request;
// Check if this is a post-challenge request (has WAF token) if (request.headers['x-amzn-waf-token']) { // Extract original referer from cookies or query params // Add it as a custom header request.headers['x-original-referer'] = [{ key: 'X-Original-Referer', value: /* extract from cookie or query param */ }]; }
return request; };
- URL Parameter Approach
Modify your application to include the original referer as a URL parameter:
Create a CloudFront Function that runs on Viewer Request:
function handler(event) { var request = event.request;
// Check if referer exists and no WAF token yet (first request) if (request.headers.referer && !request.headers['x-amzn-waf-token']) { var referer = request.headers.referer.value;
// Append referer to URL if it's from an external source
if (referer.indexOf('google.com') !== -1) {
var separator = request.uri.indexOf('?') !== -1 ? '&' : '?';
request.uri += separator + 'original_referer=' + encodeURIComponent(referer);
}
}
return request; }
Then handle this parameter in your application code.
3. Cookie-Based Solution
Set a cookie with the original referer that persists through the challenge:
// CloudFront Function (Viewer Request) function handler(event) { var request = event.request;
// Check if referer exists and no WAF token yet (first request) if (request.headers.referer && !request.headers['x-amzn-waf-token']) { var referer = request.headers.referer.value;
// Add a cookie header with the original referer
if (!request.cookies['original_referer']) {
request.headers['cookie'] = {
value: (request.headers.cookie ? request.headers.cookie.value + '; ' : '') +
'original_referer=' + encodeURIComponent(referer)
};
}
}
return request; }
- Server-Side Tracking with WAF Custom Request Handling
Use AWS WAF's custom request handling to add the original referer to a header:
Create a custom request handling rule in WAF
Configure it to capture the Referer header on initial requests
Add this as a custom header that persists through the challenge
5. Client-Side JavaScript Solution
Since you mentioned the referer is already stored in localStorage, you can use JavaScript to restore it:
// Add this to your page document.addEventListener('DOMContentLoaded', function() { // Check if this is a post-challenge page load const hasWafToken = document.cookie.includes('aws-waf-token');
if (hasWafToken) { // Get stored referer from localStorage const storedData = localStorage.getItem('referrerData'); if (storedData) { const referrerData = JSON.parse(storedData);
// Send an analytics event with the original referer
if (typeof gtag === 'function') {
gtag('event', 'page_view', {
'referrer': referrerData.referrer
});
}
// Or update your analytics data directly
if (typeof ga === 'function') {
ga('set', 'referrer', referrerData.referrer);
}
}
} });
Implementation Considerations
Performance Impact: Lambda@Edge adds latency, while CloudFront Functions are more lightweight
Security: Validate and sanitize any referer data before using it
Browser Compatibility: Test across browsers as referer handling varies
Analytics Integration: Ensure your analytics platform can use custom headers or parameters
Best Practice Recommendation
The most robust solution is a combination of approaches:
- Use CloudFront Functions to capture the original referer on first request
- Store it as both a cookie and URL parameter
- Implement client-side code to restore it for analytics purposes
This provides multiple fallback mechanisms and works across different browser security policies.
https://docs.aws.amazon.com/waf/latest/APIReference/API_ChallengeAction.html
https://docs.aws.amazon.com/waf/latest/developerguide/waf-tokens-domains.html
https://docs.aws.amazon.com/waf/latest/developerguide/customizing-the-incoming-request.html
関連するコンテンツ
- 質問済み 1年前
