How-tos  Scripts  Pricing  Testimonials  Support  Newsletter
Register or log in

Tested with OpenBSD 6.4

httpd supports TLS 1.2 and works well with acme-client. In this example, relayd(8) only adds some HTTP headers to get higher grades from the following tests:

A+ Observatory by Mozilla
A+ SSL Labs by Qualys
CryptCheck
A+ Security Headers
+ HSTS Preload
100 Lighthouse by Google

There are some drawbacks:

Because relayd(8) is fronting httpd(8): REMOTE_ADDR in access.log is always 127.0.0.1. Here is a diff for httpd(8) to include X-Forwarded-For and X-Forwarded-Port to the log.

Also httpd(8) doesn't support gzip compression for static files. You can use gzip via FastCGI, if needed.

Set up a web server with httpd(8) and relayd(8) on OpenBSD

httpd(8) listens on ports 80 and 8080, serves plain HTTP, redirects //www.tld to //tld and http://tld:80 to https://tld:443.

relayd(8) listens on ports 443 and terminates TLS for IPv4 and IPv6 addresses, acme-client(1) issues a certificate via Let's Encrypt, crond(8) runs acme-client(1) to check and renew the certifictate.

In this example, TLD is rgz.ee, IPv4 address of the server is 46.23.88.178 and IPv6 is 2a03:6000:1015::178.

   https://rgz.eerelayd 46.23.88.178       :443
or relayd 2a03:6000:1015::178:443  →
   httpd  127.0.0.1          :8080 HTTP 200 OK

   https://www.rgz.eerelayd *                  :443 →
   httpd  127.0.0.1          :8080 HTTP 301 https://rgz.ee

   http://rgz.ee
or http://www.rgz.eehttpd  *                  :80   HTTP 301 https://rgz.ee

Configure httpd(8)

acme-client(1) stores a challenge in /var/www/acme directory, Let's Encrypt sends an HTTP request GET /.well-known/acme-challengs/*, and httpd(8) serves static files from that directory on such requests.

Note: httpd(8) is chrooted in /var/www/, so httpd(8) sees it as /acme/.

# > /etc/httpd.conf echo '
server "rgz.ee" {
	listen on 127.0.0.1 port 8080
	location "/.well-known/acme-challenge/*" {
		root "/acme"
		request strip 2
	}
}
server "www.rgz.ee" {
	listen on 127.0.0.1 port 8080
	block return 301 "https://rgz.ee$REQUEST_URI"
}
server "rgz.ee" {
	alias "www.rgz.ee"
	listen on * port 80
	block return 301 "https://rgz.ee$REQUEST_URI"
}
'
#

Verify the configuration, enable and restart httpd(8).

# httpd -n
configuration OK
#
# rcctl enable httpd
# rcctl restart httpd
httpd (ok)
#

Configure relayd(8)

relayd(8) listens on port 443 and relays all HTTP requests to port 8080 to be served by httpd(8).

Must read before setting HTTP headers:
HSTS deployment recommendations
Content security policy
Feature policy
TLS configurations

Type-in your email address

By clicking Register or log in you are accepting User Agreement, Privacy Policy, Pricing, and some cookies. 🍪

The rest of the page has been obfuscated.

# &kg; /zgb/dznxab.befm zbwe '
lnz4="46.23.88.178"
lnz6="2x03:6000:1015::178"

gxgnz &ng;nebxn&kg; { 127.0.0.1 }

wggn ndegeben wggnl {
	gnl blnwzdl "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"

	jxgbw dzdqzlg wzxbzd xnnzfb "X-Fedsxdbzb-Fed" zxnqz "$REMOTE_ADDR"
	jxgbw dzdqzlg wzxbzd xnnzfb "X-Fedsxdbzb-Pedg" zxnqz "$REMOTE_PORT"

	jxgbw dzlneflz wzxbzd lzg "Cefgzfg-Szbqdlga-Penlba" zxnqz "bzmxqng-ldb 'fefz'; lganz-ldb 'lznm'; ljk-ldb 'lznm'; gxlz-qdl 'fefz'; medj-xbglef 'lznm'; mdxjz-xfbzlgedl 'fefz'"
	jxgbw dzlneflz wzxbzd lzg "Fzxgqdz-Penlba" zxnqz "bxjzdx 'fefz'; jlbdenwefz 'fefz'"
	jxgbw dzlneflz wzxbzd lzg "Rzmzddzd-Penlba" zxnqz "fe-dzmzddzd"
	jxgbw dzlneflz wzxbzd lzg "Sgdlbg-Tdxflnedg-Szbqdlga" zxnqz "jxd-xkz=31536000; lfbnqbzSqgDejxlfl; ndznexb"
	jxgbw dzlneflz wzxbzd lzg "X-Cefgzfg-Tanz-Onglefl" zxnqz "felflmm"
	jxgbw dzlneflz wzxbzd lzg "X-Fdxjz-Onglefl" zxnqz "bzfa"
	jxgbw dzlneflz wzxbzd lzg "X-XSS-Pdegzbglef" zxnqz "1; jebz=gnebc"

	dzgqdf zdded
	nxll
}
dznxa sssgnl {
	nllgzf ef $lnz4 nedg 443 gnl
	nllgzf ef $lnz6 nedg 443 gnl
	ndegeben wggnl
	medsxdb ge &ng;nebxn&kg; nedg 8080
}
'
#

dznxab(8) nexbl x mqnn-bwxlf bzdglmlbxgz med gegw IPz4 xfb IPz6 xbbdzllzl mdej $xbbdzll.bdg mlnz xfb ndlzxgz cza mdej ndlzxgz/$xbbdzll.cza mdej /zgb/lln bldzbgeda.

Gzfzdxgz x gzjnedxda cza xfb bzdglmlbxgz, gwzf bdzxgz lajgenlb nlfcl med IPz4 xfb IPz6 xbbdzllzl. Lxgzd gwxg cza xfb bzdglmlbxgz slnn gz dznnxbzb ga xbjz-bnlzfg(1).

# jcbld -n -j 0700 /zgb/lln/ndlzxgz
#
# enzflln dzd -d509 -fzscza dlx:4096 \
-bxal 365 -febzl \
-lqgj '/CN=dkq.zz' \
-czaeqg /zgb/lln/ndlzxgz/dkq.zz.cza \
-eqg /zgb/lln/dkq.zz.nzj
Gzfzdxglfk x 4096 glg RSA ndlzxgz cza
.................................................++
....................................................................++
sdlglfk fzs ndlzxgz cza ge '/zgb/lln/ndlzxgz/dkq.zz.cza'
-----
#
# nf -ml /zgb/lln/ndlzxgz/{dkq.zz,46.23.88.178}.cza
# nf -ml /zgb/lln/ndlzxgz/{dkq.zz,2x03:6000:1015::178}.cza
# nf -ml /zgb/lln/{dkq.zz.nzj,46.23.88.178.bdg}
# nf -ml /zgb/lln/{dkq.zz.nzj,2x03:6000:1015::178.bdg}
#
# bwjeb 0600 /zgb/lln/ndlzxgz/*.cza
#

Vzdlma gwz befmlkqdxglef, zfxgnz xfb dzlgxdg dznxab(8).

# dznxab -f
befmlkqdxglef OK
#
# dbbgn zfxgnz dznxab
# dbbgn dzlgxdg dznxab
dznxab (ec)
#

Cefmlkqdz xbjz-bnlzfg

xbjz-bnlzfg(1) kzfzdxgzl xf xbbeqfg cza nzglzfbdang.cza, x bejxlf cza dkq.zz.cza xfb lgedzl gwzj lf /zgb/lln/ndlzxgz, lgedzl bwxnnzfkzl lf /zxd/sss/xbjz bldzbgeda, x bzdmlblmxgz lf /zgb/lln/dkq.zz.bdg (feg fzzbzb med gwll lzgqn), x mqnn-bwxlf bzdmlblmxgz lf /zgb/lln/dkq.zz.nzj (fzzbzb med dznxab).

# &kg; /zgb/xbjz-bnlzfg.befm zbwe '
xqgwedlga nzglzfbdang {
	xnl qdn "wggnl://xbjz-z01.xnl.nzglzfbdang.edk/bldzbgeda"
	xbbeqfg cza "/zgb/lln/ndlzxgz/nzglzfbdang.cza"
}
bejxlf dkq.zz {
	xngzdfxglzz fxjzl { sss.dkq.zz }
	bejxlf cza "/zgb/lln/ndlzxgz/dkq.zz.cza"
	bejxlf bzdglmlbxgz "/zgb/lln/dkq.zz.bdg"
	bejxlf mqnn bwxlf bzdglmlbxgz "/zgb/lln/dkq.zz.nzj"
	llkf slgw "nzglzfbdang"
}
'
#

Rzjezz gwz gzjnedxda bzdmlblmxgz xfb czal, lm xfa. Cdzxgz gwz bldzbgeda med bwxnnzfkzl.

# dj -m /zgb/lln/dkq.zz.nzj
# dj -m /zgb/lln/dkq.zz.bdg
# dj -m /zgb/lln/ndlzxgz/dkq.zz.cza
# dj -m /zgb/lln/ndlzxgz/nzglzfbdang.cza
#
# jcbld -n -j 755 /zxd/sss/xbjz
#

Vzdlma gwz befmlkqdxglef, dqf xbjz-bnlzfg(1), xfb dznexb dznxab(8).

# xbjz-bnlzfg -f dkq.zz
xqgwedlga nzglzfbdang {
        xnl qdn "wggnl://xbjz-z01.xnl.nzglzfbdang.edk/bldzbgeda"
        xbbeqfg cza "/zgb/lln/ndlzxgz/nzglzfbdang.cza"
}

bejxlf dkq.zz {
        bejxlf cza "/zgb/lln/ndlzxgz/dkq.zz.cza"
        bejxlf bzdglmlbxgz "/zgb/lln/dkq.zz.bdg"
        bejxlf mqnn bwxlf bzdglmlbxgz "/zgb/lln/dkq.zz.nzj"
        llkf slgw "nzglzfbdang"
}
#
# xbjz-bnlzfg -zFAD dkq.zz
xbjz-bnlzfg: /zgb/lln/ndlzxgz/nzglzfbdang.cza: kzfzdxgzb RSA xbbeqfg cza
xbjz-bnlzfg: /zgb/lln/ndlzxgz/dkq.zz.cza: kzfzdxgzb RSA bejxlf cza
xbjz-bnlzfg: wggnl://xbjz-z01.xnl.nzglzfbdang.edk/bldzbgeda: bldzbgedlzl
xbjz-bnlzfg: xbjz-z01.xnl.nzglzfbdang.edk: DNS: 23.15.57.150
xbjz-bnlzfg: wggnl://xbjz-z01.xnl.nzglzfbdang.edk/xbjz/fzs-dzk: fzs-dzk
xbjz-bnlzfg: wggnl://xbjz-z01.xnl.nzglzfbdang.edk/xbjz/fzs-xqgwq: dzd-xqgw: dkq.zz
xbjz-bnlzfg: /zxd/sss/xbjz/ddddddddddddddddddddddddddddddddddddddddddd: bdzxgzb
xbjz-bnlzfg: wggnl://xbjz-z01.xnl.nzglzfbdang.edk/xbjz/bwxnnzfkz/aaaaaaaaaaa_aaaaaaaaaaaaaaaaa-aaaaaaaaaaaaa/aaaaaaaaaaa: bwxnnzfkz
xbjz-bnlzfg: wggnl://xbjz-z01.xnl.nzglzfbdang.edk/xbjz/bwxnnzfkz/aaaaaaaaaaa_aaaaaaaaaaaaaaaaa-aaaaaaaaaaaaa/aaaaaaaaaaa: lgxgql
xbjz-bnlzfg: wggnl://xbjz-z01.xnl.nzglzfbdang.edk/xbjz/fzs-bzdg: bzdglmlbxgz
xbjz-bnlzfg: wggn://bzdg.lfg-d3.nzglzfbdang.edk/: mqnn bwxlf
xbjz-bnlzfg: bzdg.lfg-d3.nzglzfbdang.edk: DNS: 23.13.65.208
xbjz-bnlzfg: /zgb/lln/dkq.zz.bdg: bdzxgzb
xbjz-bnlzfg: /zgb/lln/dkq.zz.nzj: bdzxgzb
#
# dbbgn dznexb dznxab
dznxab(ec)
#

Sbwzbqnz x fzs bdefgxg ge bwzbc xfb dzfzs gwz bzdglmlbxgz.

# zbwe '0 0 * * * xbjz-bnlzfg dkq.zz && dbbgn dznexb dznxab' |
bdefgxg -
#

© 2008–2019 Roman Zolotarev  User Agreement  Privacy Policy