After switching to HTTPS, pages show a "mixed content" warning; how do I fix it?
Short answer
The warning is caused by the HTTPS page requesting resources such as images, scripts or styles with http://; most of the time, because TLS is terminated on TR7, the application does not know that the request is HTTPS and generates the links with http://. The permanent solution is to forward the X-Forwarded-Proto: https header to the Backend Service with the Set HTTP Header action and to make the application use this header. If the application cannot be changed, the Content-Security-Policy: upgrade-insecure-requests header added with the Add HTTP Header action makes the browser upgrade the requests, or the Modify Response Content action (Replace) changes the http:// addresses in the response body.
Problem: Insecure Resources on an HTTPS Page
After the switch to HTTPS, browsers block the resources that the page loads with http:// or show a warning; the padlock icon disappears, and some functions do not work because the script and style files are not loaded. When TLS is terminated on TR7, the Backend Service receives the request as plain HTTP; for this reason, the application continues to generate its own absolute links and redirects with http://.
Solution: Three Methods
Method 1 solves the problem at its source; Methods 2 and 3 are used when the application cannot be touched.
| Your situation | Suitable method |
|---|---|
| The application can read proxy headers (permanent solution) | Method 1: X-Forwarded-Proto header |
| The resources are also reachable over HTTPS; it is enough for the browser to upgrade the requests | Method 2: CSP upgrade-insecure-requests |
The application cannot be changed; the http:// addresses are fixed in the response body | Method 3: Replacing in the response body |
Method 1: X-Forwarded-Proto Header Recommended
- How it works TR7 writes the
X-Forwarded-Proto: httpsheader to the requests on which it terminates TLS; based on this header, the application considers the request HTTPS and generates its links withhttps://. - Where it is openedLoad Balancer → Actions → Action Type = Set HTTP Header
- Requirement The application being configured to read proxy headers
- vService type HTTP
Step-by-Step Configuration
On the Load Balancer → Actions screen, Add is clicked (how to add).
Action Name is entered; Action Type = Set HTTP Header and Execution Level = On Request are selected. Header to Edit = X-Forwarded-Proto and Header Content = https are written (protocol information after SSL offloading). Set HTTP Header replaces the header of the same name sent by the client.
In the Conditions field, the ready-made If SSL is terminated condition is selected; the header is written only to HTTPS requests.
Add is clicked; the action is added to the list.
On the Load Balancer → Load Balancer vService List screen, the HTTP vService is selected and Edit is clicked.
In the Details panel, the Actions box under Modules is checked and the action is selected in the field that opens.
Save is clicked. In a cluster setup, with the default auto-sync, the change is also sent to the peer device; if Manual Sync Mode is on, it is sent to the peer device manually.
In the application, the setting for reading proxy headers is turned on; the setting is limited so that it trusts only the requests coming from the TR7 address. Examples: SECURE_PROXY_SSL_HEADER in Django, trust proxy in Express, Forwarded Headers Middleware (XForwardedProto) in ASP.NET Core.
Verification
The page is opened and the Console and Network tabs of the browser developer tools are checked.
No "Mixed Content" warning · all subresources https://The headers of the incoming request are read in the access log of the application server or in a packet capture.
Command: tcpdump -A -nn -i any port 80 | grep -i x-forwarded-proto
X-Forwarded-Proto: httpsMethod 2: CSP upgrade-insecure-requests
- How it works The
Content-Security-Policy: upgrade-insecure-requestsheader added to the response tells the browser to turn thehttp://requests on the page intohttps://before sending them. - Where it is openedLoad Balancer → Actions → Action Type = Add HTTP Header
- Requirement The resources also being reachable over HTTPS
- vService type HTTP
Step-by-Step Configuration
On the Load Balancer → Actions screen, Add is clicked (how to add).
Action Name is entered; Action Type = Add HTTP Header and Execution Level = On Response are selected. Header to Add = Content-Security-Policy and Header Content = upgrade-insecure-requests are written. If the application already sends a Content-Security-Policy header, Add HTTP Header adds a second copy and a double policy is formed in the response.
Add is clicked.
On the Load Balancer → Load Balancer vService List screen, the HTTP vService is selected and Edit is clicked.
In the Details panel, the Actions box under Modules is checked and the action is selected.
Save is clicked.
Verification
Command: curl -skI https://www.example.com/ | grep -i content-security-policy; then the browser Console tab is checked.
Content-Security-Policy: upgrade-insecure-requests · no warningMethod 3: Replacing in the Response Body
- How it works The specified text in the response body (e.g.
http://portal.example.com) is replaced with the new one (https://portal.example.com). - Where it is openedLoad Balancer → Actions → Action Type = Modify Response Content → Modify Type = Replace
- Requirement The
http://addresses being present in the response body (HTML) - vService type HTTP
Step-by-Step Configuration
On the Load Balancer → Actions screen, Add is clicked (how to add).
Action Name is entered; Action Type = Modify Response Content and Modify Type = Replace are selected (Replace mode). Query Type is RegEx by default; for plain text, String is selected. Mask Query = http://portal.example.com and New Content = https://portal.example.com are written.
Add is clicked.
On the Load Balancer → Load Balancer vService List screen, the HTTP vService is selected and Edit is clicked.
In the Details panel, the Actions box under Modules is checked and the action is selected.
Save is clicked.
Verification
Command: curl -sk https://portal.example.com/ | grep -c "http://portal.example.com"
0 · no warning in the browser ConsoleCommon Mistakes
- Thinking that the HTTP → HTTPS redirect will solve the problem. The redirect moves the page itself to HTTPS; it does not fix the
http://resources inside the page. - Adding the header without configuring the application. If the application does not read the
X-Forwarded-Protoheader, the links do not change. - Using the CSP option in the Manage HTTP Security Headers action. This option writes the fixed
default-src 'self'policy; it does not upgrade the requests and may also block external resources. - Overlooking the side effect of modifying the response body. While the action is active, TR7 does not request compressed responses from the Backend Service; links generated at runtime with JavaScript are not fixed this way either.
How it is done in the documentation
