iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🦑

#1 [Caching] Does Forward Proxy Cache Cause Outdated CSS? (Chrome, Squid, Nginx)

に公開

Background

Recently, I heard that "even though a website has been updated, an old screen may be displayed due to the forward proxy's cache." While I thought that such a thing might be possible, I also wondered, "Is it really true? Could it be that just the browser cache was being displayed?" So, the theme of this project is to actually verify this.

Configuration

I will prepare the following four machines. Note that the servers and the proxy will be built on Rocky Linux 8.8 deployed on Proxmox.

  • Web Origin Server : 192.168.12.55
    Stores HTML and CSS content. (Nginx 1.14.1)
  • Web Cache Server : 192.168.12.56
    Caches content from the origin server and accepts access from clients. The content expiration is set to 1 minute, and it is basically configured to fetch the latest content. (Nginx 1.14.1)
  • Forward Proxy : 192.168.12.57
    Relays HTTP access from clients and holds once-downloaded (accessed) content in the cache for 60 minutes. (Squid 4.15)
  • Client PC : 192.168.12.X (DHCP)
    Performs HTTP access. The browser used is Chrome Ver. 134.

Setup

I will build the environment according to the requirements.

1. Web Origin Server

  1. Installation & Folder Creation
dnf install nginx -y

mkdir -p /var/www/html
chown -R nginx:nginx /var/www/html
chmod -R 755 /var/www/html
  1. Creating HTML & CSS
/var/www/html/index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>CSS Test</title>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <h1>CSS Test</h1>
    <p>After modifying the CSS, this part should be displayed in red.</p>
</body>
</html>
/var/www/html/style.css
body {
    font-family: Arial, sans-serif;
    background-color: #f4f4f4;
    text-align: center;
    padding: 50px;
}

h1 {
    color: black;
}

p {
    font-weight: bold;
    font-size: 1.2em;
    color: black;  /* Black */
}
  1. Editing the Configuration File
/etc/nginx/nginx.conf(excerpt)
    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        # root         /usr/share/nginx/html;
        root         /var/www/html;
        index        index.html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
            try_files $uri $uri/ =404;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
  1. Firewall and Startup
firewall-cmd --add-service=http --zone=public --permanent
firewall-cmd --reload
firewall-cmd --list-all

systemctl enable --now nginx
systemctl status nginx
  1. SELinux Countermeasures
    If left as is, accessing it will result in a 403 error, so we will rebuild the SELinux policy.
# From confirmation to creation and application of the new policy
cat /var/log/audit/audit.log | grep denied | tail -5
cat /var/log/audit/audit.log | grep denied | audit2allow
cat /var/log/audit/audit.log | grep denied | audit2allow -M nginxpolicy_20250323_01
semodule -i nginxpolicy_20250323_01.pp

# Re-confirm. If HTTP access is still blocked after applying the new policy, recreate the policy several times.
# In this case, it was completed in two attempts. The final allowed policy is as follows.
cat /var/log/audit/audit.log | grep denied | audit2allow

#============= httpd_t ==============

#!!!! This avc is allowed in the current policy
allow httpd_t var_t:file { getattr open read };

Access h++p://192.168.12.55/, and if the content of index.html is displayed, you're all set.

Web Cache Server

  1. Installation & Folder Creation
dnf install nginx -y

mkdir -p /var/cache/nginx
chown -R nginx:nginx /var/cache/nginx
chmod -R 755 /var/cache/nginx
  1. Editing the Configuration File
    The proxy_set_header settings are a bit of a mystery. add_header seemed to be reflected correctly.
    Well, I'm not entirely sure, but I'll ignore it for now as it's not the main point.
/etc/nginx/nginx.conf(excerpt)
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=cache_zone:10m max_size=1g inactive=60m use_temp_path=off;

    server {
        listen 80;
        server_name 192.168.12.56;  # Frontend domain or IP

        location / {
            proxy_pass http://192.168.12.55;  # Backend web server
            proxy_set_header Host $host;  # Host requested by the client
            proxy_set_header X-Real-IP $remote_addr;  # Client's real IP
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Add XFF header

            proxy_cache cache_zone;
            proxy_cache_valid any 1m;  # Cache expiration is 1 minute (keeping the front end up to date)
            # proxy_cache_bypass $http_cache_control;  # Bypass the cache if the client sends a Cache-Control header
            add_header X-Cache-Status $upstream_cache_status;  # Add cache status (HIT, MISS, BYPASS, etc.) to the response header
        }
    }
  1. Firewall and Startup
firewall-cmd --add-service=http --zone=public --permanent
firewall-cmd --reload
firewall-cmd --list-all

systemctl enable --now nginx
systemctl status nginx
  1. SELinux Countermeasures
    The process is the same as for the origin server.
# From confirmation to creation and application of the new policy
cat /var/log/audit/audit.log | grep denied | tail -5
cat /var/log/audit/audit.log | grep denied | audit2allow
cat /var/log/audit/audit.log | grep denied | audit2allow -M nginxpolicy_20250323_01
semodule -i nginxpolicy_20250323_01.pp

# Re-confirm. If HTTP access is still blocked after applying the new policy, recreate the policy several times.
# In this case, it was completed in one attempt. The final allowed policy is as follows.
cat /var/log/audit/audit.log | grep denied | audit2allow

#============= httpd_t ==============

#!!!! This avc is allowed in the current policy
allow httpd_t http_port_t:tcp_socket name_connect;

Access h++p://192.168.12.56/, and if the index.html from the Web Origin Server is displayed, you're all set.

Forward Proxy

  1. Installation
dnf install squid -y
  1. Editing the Configuration File
/etc/squid/squid.conf
# Safe ports
acl Safe_ports port 80          # http
acl Safe_ports port 8080        # http
http_access deny !Safe_ports

# Network ACL
acl localnet src 192.168.12.0/24
http_access allow localnet
http_access allow localhost
http_access deny all

# Squid's listening port
http_port 8080

# Cache settings
cache_dir ufs /var/spool/squid 1000 16 256  # Cache directory (1000MB)

# Cache expiration (60 minutes)
refresh_pattern . 60 100% 60
  1. Creating the Cache Directory
ll /var/spool/squid/
squid -z
ll /var/spool/squid/
  1. Firewall and Startup
firewall-cmd --add-port=8080/tcp --zone=public --permanent
firewall-cmd --reload
firewall-cmd --list-all

systemctl enable --now squid
systemctl status squid

Connection

Configure the proxy settings on the client PC side and confirm that you can access h++p://192.168.12.56/.

If the access is successful, it will be displayed as follows.
Since the Remote Address is the proxy's IP:8080, it seems to be correctly accessing via the forward proxy.

I didn't pay much attention when building the forward proxy, but X-Cache and X-Cache-Lookup are added to the response headers. Since I want to know "whether the proxy responded from the cache," I probably only need to look at X-Cache.
Since this is the first access, it's naturally a MISS. HIT would mean a cache response.

That's it for this time.
Next time, I will actually check the behavior of the proxy and browser cache.

Discussion