How to enable HSTS header for HTTPS only in lighttpd config? - http-headers

I want to enable HSTS header for my lighttpd server. As per the this article, the HSTS header does get set, but I can see that the server sends this header even in responses over HTTP (non-secure transport). As specified in RFC 6797:
An HSTS Host MUST NOT include the STS header field in HTTP response
conveyed over non-secure transport.
How do I disable this header for non-secure HTTP responses?

server.modules += ( "mod_setenv" )
$HTTP["scheme"] == "https" {
setenv.set-response-header = ( "Strict-Transport-Security" => "max-age=SECONDS" )
}
(replace SECONDS with a value appropriate for your site policy)
See lighttpd documentation for mod_setenv for additional policy examples.
If you set site policy headers globally in lighttpd, but you redirect all http traffic to https and want to disable sending policy headers with those redirects (and you used setenv.set-response-header as above):
server.modules += ( "mod_setenv", "mod_redirect" )
$HTTP["scheme"] == "http" {
setenv.set-response-header = ()
url.redirect = ("" => "https://${url.authority}${url.path}${qsa}")
url.redirect-code = 308
}

Related

cloudflare worker rewrite Host Header

How do I set up another Host Header in the cloudflare worker?
For example, I have set up a 1.2.3.4 ip for my site's www record
By default www requests are sent with the header www.ex.com but I want to send the www requests with the new.ex.com header
You need to configure a DNS record for new.ex.com so that it points to the same IP address. Then, you can make a fetch() request with new.ex.com in the URL.
If you cannot make new.ex.com point at the right IP, another alternative is to make a fetch() request using the resolveOverride option to specify a different hostname's IP address to use:
fetch("https://new.ex.com", {cf: {resolveOverride: "www.ex.com"}});
Note that this only works if both hostnames involved are under your zone. Documentation about resolveOverride can be found here.
You cannot directly set the Host header because doing so could allow bypassing of security settings when making requests to third-party servers that also use Cloudflare.
// Parse the URL.
let url = new URL(request.url)
// Change the hostname.
url.hostname = "check-server.example.com"
// Construct a new request
request = new Request(url, request)
Note that this will affect the Host header seen by the origin
(it'll be check-server.example.com). Sometimes people want the Host header to remain the same.
// Tell Cloudflare to connect to `check-server.example.com`
// instead of the hostname specified in the URL.
request = new Request(request,
{cf: {resolveOverride: "check-server.example.com"}})

Strict-Transport-Security influence on http reverse proxy that redirects to https

The server response comes with HSTS header, and since I'm using reverse proxy HSTS header is also being sent through proxy response.
Since there are different domains (proxy and server) does HSTS make the browser automatically change the schema from http://proxyhost.com to https://proxyhost.com? or the preload list will call automatically https://serverhost.com when the user will request http://proxyhost.com?
does HSTS make the browser automatically change the schema from http to https
Indeed! and since:
a reverse proxy HSTS header is also being sent through proxy response.
... the configuration of a reverse proxy can involuntarily make your domain set theHSTS header.
Took some while to see why my apache server sets the HSTS header - for I hadn't configured that in the apache web server. It was due to a ReverseProxy: as the foreign domain sets theHSTS header this header comes then (reverse proxy!) with my domain's name. This was then propagated to the client's browser which stores it. Thus, all my domain's sites (and in this case also all my subdomains!) where forced to use https (not when using e.g. curl of course, but firefox, chromium etc.).
Thanks for your question - it was already the perfect direction!
In my case I simply could use aRewriteRule instead of a reverse proxy :) but this of course depends on your scenario.
You also gave the proper answer in your comment:
in this case I should unset HSTS header in the reverse proxy
Right! Just add Header unset Strict-Transport-Security directly after the ProxyPassReverse directive, and you can use a reverse proxy without inherit the HSTS header.

Access-Control-Allow-Origin: "*" not allowed when credentials flag is true, but there is no Access-Control-Allow-Credentials header

Suddenly, seemingly without changing anything in my web app, I started getting CORS errors when opening it in Chrome. I tried adding an Access-Control-Allow-Origin: * header. Then I get this error:
XMLHttpRequest cannot load http://localhost:9091/sockjs-node/info?t= 1449187563637. A wildcard '*' cannot be used in the 'Access-Control-Allow-Origin' header when the credentials flag is true. Origin 'http://localhost:3010' is therefore not allowed access.
But as you can see in the following image, there is no Access-Control-Allow-Credentials header.
WTF? Chrome bug?
My page is loaded at http://localhost:3010 and that server also uses Access-Control-Allow-Origin: * without problems. Is there a problem if the two endpoints both use it?
"credentials flag" refers to XMLHttpRequest.withCredentials of the request being made, not to an Access-Control-Allow-Credentials header. That was the source of my confusion.
If the request's withCredentials is true, Access-Control-Allow-Origin: * can't be used, even if there is no Access-Control-Allow-Credentials header.
Requests withCredentials:true, on a server configured with Access-Control-Allow-Origin: * CAN be used, but you will need some more extra config on your server:
Using Access-Control-Allow-Origin=* on the server, it will not allow access to any resource (that requires credentials) on any xhr CORS request.
Workarounds:
Make that remote resource on the server accesible without credentials
( and use xhr.withCredentials = false )
Create a rewrite rule on
the server, to modify the response header
Access-Control-Allow-Origin=* to the request's origin. You can
also apply this rewrite under certain criteria, for example, if
request is using certain port or it comes from a list of whitelisted
domains.
Here is some article that explains how to do this on a IIS server, but you can do this in many other servers:
PS: in case of using credentials, you will also need the following header on your server's response: Access-Control-Allow-Credentials=true
PS2: only 1 value is allowed to "access-control-allow-origin" paramenter. If you try to use for instance two domains: domain1.com domain2.com, it won't work.
I solved same problem by using these steps..
1) disable your chrome extension "Allow-Control-Allow-Origin"
2) add these into your service
var xhr = new ();
xhr.withCredentials = true;

Allowing cross origin requests for http and https

My website supports both http and https protocols. However using the code below in .htaccess file, I can only set one domain to allow CORS requests:
Header set Access-Control-Allow-Origin: http://example.com
I want to allow CORS for both http and https versions of my site (not just "*") and tried the solutions here:
Access-Control-Allow-Origin Multiple Origin Domains?
But the problem is that all solutions rely on Origin header in the request which may not exist and also is not secure. (anyone can put a origin header in their request)
I want to know if the request has been served over https and use this info to set the proper CORS header. Something like this:
SetEnvIf servedOverHttps httpsOrigin=true
Header set Access-Control-Allow-Origin: https://example.me env=httpsOrigin
SetEnvIf notServedOverHttps httpOrigin=true
Header set Access-Control-Allow-Origin: http://example.me env=httpOrigin
How can I find out that it's a https request?
Have you tried using HTTPS variable?
It will be set to "on" for all https requests.
Your .htaccess should look like this
Header set Access-Control-Allow-Origin: http://example.com #default
Header set Access-Control-Allow-Origin: https://example.com env=HTTPS #override if https

Very simple authentication using one-time cookie on nginx

I have a site intended only for private consumption by 3 coders. It's simple HTML served by nginx directly but intended for consumption inside and outside the office.
I want to have a simple password or authentication scheme. I could use HTTP auth but these tend to expire fairly often which makes it a pain for people to use. I'm also nervous it's much easier for someone to sniff than cookies.
So I'm wondering if I could just set a cookie on their browsers in JavaScript with a unique long ID and somehow tell nginx to only accept requests (for a particular subdomain) which has this cookie.
Is this simple enough to do? How do I
tell nginx to filter by cookie
in the browser, set a cookie that never expires?
There is a really quite simple looking solution that I found from a blog post by Christian Stocker. It implements the following rules:
If the user is on an internal IP, they are allowed.
If the user has a cookie set, they are allowed.
If neither matches, the user is presented with http basic authentication, and if they successfully authenticate a long term cookie is set
This is really the best of both worlds.
Here's the config:
map $cookie_letmein $mysite_hascookie {
"someRandomValue" "yes";
default "no";
}
geo $mysite_geo {
192.168.0.0/24 "yes"; #some network which should have access
10.10.10.0/24 "yes"; #some other network which should have access
default "no";
}
map $mysite_hascookie$mysite_geo $mysite_authentication{
"yesyes" "off"; #both cookie and IP are correct => OK
"yesno" "off"; #cookie is ok, but IP not => OK
"noyes" "off"; #cookie is not ok, but IP is ok => OK
default "Your credentials please"; #everythingles => NOT OK
}
server {
listen 80;
server_name mysite.example.org;
location / {
auth_basic $mysite_authentication;
auth_basic_user_file htpasswd/mysite;
add_header Set-Cookie "letmein=someRandomValue;max-age=3153600000;path=/"; #set that special cookie, when everything is ok
proxy_pass http://127.0.0.1:8000/;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
To have Nginx filter by a cookie, you could perform some action if the cookie isn't present, and then your real action for the 3 people that have access, for example:
server {
listen 443 ssl http2; # Use HTTPS to protect the secret
...
if ($http_cookie !~ 'secretvalue') {
return 401;
}
location / {
# Auth'd behaviour goes here
}
}
And to set a cookie that never expires, fire up your browser's JavaScript console on a page that's on your server's hostname, and enter:
document.cookie = 'cookie=secretvalue;max-age=3153600000;path=/;secure';
That's technically not forever, but 100 years ought to do it. You can also use expires= for an absolute date in RFC1123 format if you're so inclined and can easily adjust the path if you need to. This also sets the secure flag on the cookie so it will only get sent over HTTPS.
There are also browser add-ons that will allow you to create arbitrary cookies, but all modern browsers have a JavaScript console.