Relayd and headers
Because httpd can't manage headers itself, you can put relayd "before" httpd. It helps add headers or modify others.
As you can guess, relayd is included in base installation.
Visit this link to test your website headers.
Relayd configuration
Edit /etc/relayd.conf to configure relayd. Inside, add the following lines as example :
http protocol "http" { match request header remove "Proxy" match response header set "X-Xss-Protection" value "1; mode=block" return error pass } relay "www" { listen on 192.0.2.2 port 80 protocol "http" forward to 127.0.0.1 port 80 }
Those lines means :
- http protocol "http" { : you open a new configuration section for protocol http called later.
- match request header remove "Proxy" : you remove the header "Proxy" to avoid httpoxy exploit.
- match response header set "X-Xss-Protection" value "1;..." : we add a headera to mitigate XSS attacks
- return error : if there is a problem, return an error
- pass : otherwise, go on
- relay "www" { : you add a section to redirect traffic to httpd daemomn.
- listen on 192.0.2.2 port 80 : we listen on port 80 on your public IP.
- protocol "http" : we use the previously defined protocol
- forward to localhost port 80 : we redirect to httpd now supposed to listen on localhost.
That's why you must edit httpd configuration accodingly :
# httpd's configuration listen on localhost port 80
To sum up, things goes like this now :
1. A client ask to see your website and knocks at port 80.
2. relayd modify a few headers and redirect to httpd which still serve the website.
Dont forget to reload relayd and httpd:
# rcctl enable relayd # rcctl restart httpd # rcctl start relayd
Notice logs will show incoming connections from 127.0.0.1 (relayd local address). You may want to use "forwarded" log format for httpd :
log style forwarded
You can find a configuration example at the end of this documentation.
TLS / https
Find below an example to add TLS support to relayd. There are a few things to take care of about certificates and keys.
http protocol "https" { match request header remove "Proxy" match response header set "X-Xss-Protection" value "1; mode=block" return error pass tls keypair athome.tld tls keypair here.tld } relay "tlsforward" { listen on 192.0.2.2 port 443 tls protocol "https" forward with tls to 127.0.0.1 port 443 }
Look at the lines starting with "tls keypair". They define the certificate and keys to use for TLS. In the above example, two certificates for two different domains are used, you can add as much as you have certificates to use.
However, thos certificates MUST be stored with the appropriate filename in the correct location :
/etc/ssl/private/athome.tld.key /etc/ssl/athome.tld.crt
Make sure /etc/ssl/athome.tld.crt is the "full chain".
This means you should have such configuration in acme-client configuration :
domain athome.tld { domain key "/etc/ssl/private/athome.tld.key" domain certificate "/etc/ssl/athome.tld-cert.crt" domain chain certificate "/etc/ssl/athome.tld-chain.crt" domain full chain certificate "/etc/ssl/athome.tld.crt" sign with letsencrypt }
This way, relayd will automatically pick up the right certificate.
Renew certificates
Remember to reload relayd after certificate renewal :
/usr/sbin/acme-client -v athome.tld && \ /usr/sbin/rcctl reload relayd
IPv6
If you want to add ipv6 support with relayd, it is obviously possible.
First, make sure you set the local address in "/etc/hosts" :
127.0.0.1 localhost ::1 localhost
You can now use "localhost" to refer to both ipv4 or ipv6 local depending on context.
Now add two entries in relayd configuration:
relay "http" { listen on $ext_ip4 port 80 protocol "http" forward to 127.0.0.1 port 80 } relay "http6" { listen on $ext_ip6 port 80 protocol "http" forward to ::1 port 80 }
httpd's configuration will make use of "localhost" so it's simpler :
listen on localhost port 80
Deal with headers
Security headers
You can set a few headers to improve your website security. It's mostly useful if you host huge webapps, not really for static websites.
match request header remove "Proxy" match response header set "X-Xss-Protection" value "1; mode=block" match response header set "Frame-Options" value "SAMEORIGIN" match response header set "X-Frame-Options" value "SAMEORIGIN" match response header set "X-Robots-Tag" value "index,nofollow" match response header set "X-Permitted-Cross-Domain-Policies" value "none" match response header set "X-Download-Options" value "noopen" match response header set "X-Content-Type-Options" value "nosniff" match response header set "Permissions-Policy" value "interest-cohort=()"
If you only host one domain, add :
match response header set "Access-Control-Allow-Origin" value "athome.tld"
Optimize client cache and bandwidth usage
You should consider to tune up th amount of request a client should make each time he checks on your website. As example, you can specify to keep in cache files such as pictures, stylesheets or fonts for a few days before asking again.
In "protocol" section, just before "pass" keyword, add :
match request path "/*.css" tag "CACHE" match request path "/*.js" tag "CACHE" match request path "/*.atom" tag "CACHE" match request path "/*.rss" tag "CACHE" match request path "/*.xml" tag "CACHE" match request path "/*.jpg" tag "CACHE" match request path "/*.png" tag "CACHE" match request path "/*.svg" tag "CACHE" match request path "/*.gif" tag "CACHE" match request path "/*.ico" tag "CACHE" match response tagged "CACHE" header set "Cache-Control" value "max-age=1814400"
Everytime a client ask for a file ending with ".css" or ".js" or ".atom" (...), relayd tag the resquest with "CACHE". At last we add a header to increase cache to 21 days to requests with this tag.
Set default encoding
Following the same scheme, you can specify the default encoding according to file extension :
match request path "/*.html" tag "UTF8" match request path "*/" tag "UTF8" match response tagged "UTF8" header set "Content-Type" value "text/html;charset=UTF-8"
About tags
Understand you can't set multiple tags at once. If you want to apply the two above headers (cache-control and content-type), you must do it separately since relayd configuration is processed in order :
match request path "/*.html" tag "CACHE" match response tagged "CACHE" header set "Cache-Control" value "max-age=1814400" match request path "/*.html" tag "UTF8" match response tagged "UTF8" header set "Content-Type" value "text/html;charset=UTF-8"