Browser "remembers" a temporary redirect for a while. Can I prevent that?

1.4k Views Asked by At

My nginx website is protected by IP range and I need to be on the premises or log in via vpn to see it:

geo $external_ip {
  192.168.0.0/16 0;
}
…
if ($external_ip) {
  return 302 https://www.different-site.com/info_explaining_to_log_in_via_vpn ;
}
…
# Normal location config for website

Now I access my website and I have forgotten to log in via the VPN. So I am being redirected to the info page that tells me nicely why I can't access the site and that I have to fire up my VPN client.

I do so. And now I reenter the URL to my website again, but the browser seems to remember the redirect and keeps returning the info page.

The same happens if I use a 307 status code.

After a while, the browser seems to forget that redirect and behaves as I expect again and shows me my site.

The same happens if I simply return 403, effectively discarding my info page. I did that because I thought it might be some cache statements. But also the default nginx 403 page seems to get remembered by the browser.

Is there a way how I can make the browser try to reload the orginal site with each try? I feel I am missing a vital brick of the puzzle.

Output of $ curl -I https://different-site.com/:

HTTP/2 302

server: nginx/1.10.3 (Ubuntu)
date: Mon, 11 May 2020 20:07:54 GMT
content-type: text/html
content-length: 170
location: different-site.com/info_explaining_to_log_in_via_vpn
pragma: no-cache
cache-control: no-cache

More information: The problem only exists in the browser that initially opened the connection without the vpn in place. Any other browser or a curl run after initiating the vpn succeeds.

More information (2): I am currently assuming that my browser is keeping a connection alive which is reused even once the VPN is started. That way, nginx still sees the old public IP and refuses access until that original connection is terminated. According to https://serverfault.com/questions/775617/force-nginx-to-close-connection, I cannot terminate the connection server side unless I disable keepalive completely, which I don't want for performance reasons. So it looks like there is no way forward. My next thought is to put something in front of nginx (haproxy?) which could determine a connection close depending on url.

2

There are 2 best solutions below

1
On

Try Cache-Control: no-store instead.

From the documentation for no-cache:

The response may be stored by any cache, even if the response is normally non-cacheable. However, the stored response MUST always go through validation with the origin server first before using it, therefore, you cannot use no-cache in-conjunction with immutable. If you mean to not store the response in any cache, use no-store instead. This directive is not effective in preventing caches from storing your response.

2
On

Does it help to disable cache response headers?

add_header cache-control no-cache always;
add_header Last-Modified  "" always;
etag off;
if_modified_since off;

I've had this issue before when my server originally sent a 301 before I changed it to 302. You can also clear Chrome's DNS cache with chrome://net-internals/#dns, or try a private/incognito window in your browser. Firefox/Chrome dev tools let you disable the cache and should pick up the new Location header if you reload the URL:

enter image description here