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, cron(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.

# &st; /eta/seczus.aewo eahe '
fhe4="46.23.88.178"
fhe6="2z03:6000:1015::178"

tzuce &ct;ceazc&st; { 127.0.0.1 }

htth hseteaec htthk {
	tck afhhesk "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"

	jztah seygekt hezses zhhews "X-Fesqzsses-Fes" ezcge "$REMOTE_ADDR"
	jztah seygekt hezses zhhews "X-Fesqzsses-Pest" ezcge "$REMOTE_PORT"

	jztah sekhewke hezses ket "Cewtewt-Seagsftu-Pecfau" ezcge "seozgct-ksa 'wewe'; ktuce-ksa 'keco'; fjs-ksa 'keco'; uzke-gsf 'wewe'; oesj-zatfew 'keco'; oszje-zwaektesk 'wewe'"
	jztah sekhewke hezses ket "Feztgse-Pecfau" ezcge "azjesz 'wewe'; jfasehhewe 'wewe'"
	jztah sekhewke hezses ket "Reoesses-Pecfau" ezcge "we-seoesses"
	jztah sekhewke hezses ket "Stsfat-Tszwkhest-Seagsftu" ezcge "jza-zse=31536000; fwacgseSguDejzfwk; hsecezs"
	jztah sekhewke hezses ket "X-Cewtewt-Tuhe-Ohtfewk" ezcge "wekwfoo"
	jztah sekhewke hezses ket "X-Fszje-Ohtfewk" ezcge "sewu"
	jztah sekhewke hezses ket "X-XSS-Pseteatfew" ezcge "1; jese=uceao"

	setgsw esses
	hzkk
}
seczu qqqtck {
	cfktew ew $fhe4 hest 443 tck
	cfktew ew $fhe6 hest 443 tck
	hseteaec htthk
	oesqzss te &ct;ceazc&st; hest 8080
}
'
#

seczus(8) cezsk z ogcc-ahzfw aestfofazte oes ueth IPe4 zws IPe6 zsssekkek osej $zsssekk.ast ofce zws hsfezte oeu osej hsfezte/$zsssekk.oeu osej /eta/kkc sfseatesu.

Geweszte z tejheszsu oeu zws aestfofazte, thew asezte kujuecfa cfwok oes IPe4 zws IPe6 zsssekkek. Lztes thzt oeu zws aestfofazte qfcc ue sehczaes uu zaje-acfewt(1).

# josfs -h -j 0700 /eta/kkc/hsfezte
#
# ehewkkc sey -a509 -weqoeu skz:4096 \
-szuk 365 -wesek \
-kguf '/CN=ssn.ee' \
-oeuegt /eta/kkc/hsfezte/ssn.ee.oeu \
-egt /eta/kkc/ssn.ee.hej
Gewesztfws z 4096 uft RSA hsfezte oeu
.................................................++
....................................................................++
qsftfws weq hsfezte oeu te '/eta/kkc/hsfezte/ssn.ee.oeu'
-----
#
# cw -ok /eta/kkc/hsfezte/{ssn.ee,46.23.88.178}.oeu
# cw -ok /eta/kkc/hsfezte/{ssn.ee,2z03:6000:1015::178}.oeu
# cw -ok /eta/kkc/{ssn.ee.hej,46.23.88.178.ast}
# cw -ok /eta/kkc/{ssn.ee.hej,2z03:6000:1015::178.ast}
#
# ahjes 0600 /eta/kkc/hsfezte/*.oeu
#

Vesfou the aewofsgsztfew, ewzuce zws sektzst seczus(8).

# seczus -w
aewofsgsztfew OK
#
# saatc ewzuce seczus
# saatc sektzst seczus
seczus (eo)
#

Cewofsgse zaje-acfewt

zaje-acfewt(1) sewesztek zw zaaegwt oeu cetkewasuht.oeu, z sejzfw oeu ssn.ee.oeu zws ktesek thej fw /eta/kkc/hsfezte, ktesek ahzccewsek fw /ezs/qqq/zaje sfseatesu, z aesofafozte fw /eta/kkc/ssn.ee.ast (wet weeses oes thfk ketgh), z ogcc-ahzfw aesofafozte fw /eta/kkc/ssn.ee.hej (weeses oes seczus).

# &st; /eta/zaje-acfewt.aewo eahe '
zgthesftu cetkewasuht {
	zhf gsc "htthk://zaje-e01.zhf.cetkewasuht.ess/sfseatesu"
	zaaegwt oeu "/eta/kkc/hsfezte/cetkewasuht.oeu"
}
sejzfw ssn.ee {
	zcteswztfee wzjek { qqq.ssn.ee }
	sejzfw oeu "/eta/kkc/hsfezte/ssn.ee.oeu"
	sejzfw aestfofazte "/eta/kkc/ssn.ee.ast"
	sejzfw ogcc ahzfw aestfofazte "/eta/kkc/ssn.ee.hej"
	kfsw qfth "cetkewasuht"
}
'
#

Rejeee the tejheszsu aesofafozte zws oeuk, fo zwu. Csezte the sfseatesu oes ahzccewsek.

# sj -o /eta/kkc/ssn.ee.hej
# sj -o /eta/kkc/ssn.ee.ast
# sj -o /eta/kkc/hsfezte/ssn.ee.oeu
# sj -o /eta/kkc/hsfezte/cetkewasuht.oeu
#
# josfs -h -j 755 /ezs/qqq/zaje
#

Vesfou the aewofsgsztfew, sgw zaje-acfewt(1), zws secezs seczus(8).

# zaje-acfewt -w ssn.ee
zgthesftu cetkewasuht {
        zhf gsc "htthk://zaje-e01.zhf.cetkewasuht.ess/sfseatesu"
        zaaegwt oeu "/eta/kkc/hsfezte/cetkewasuht.oeu"
}

sejzfw ssn.ee {
        sejzfw oeu "/eta/kkc/hsfezte/ssn.ee.oeu"
        sejzfw aestfofazte "/eta/kkc/ssn.ee.ast"
        sejzfw ogcc ahzfw aestfofazte "/eta/kkc/ssn.ee.hej"
        kfsw qfth "cetkewasuht"
}
#
# zaje-acfewt -eFAD ssn.ee
zaje-acfewt: /eta/kkc/hsfezte/cetkewasuht.oeu: sewesztes RSA zaaegwt oeu
zaje-acfewt: /eta/kkc/hsfezte/ssn.ee.oeu: sewesztes RSA sejzfw oeu
zaje-acfewt: htthk://zaje-e01.zhf.cetkewasuht.ess/sfseatesu: sfseatesfek
zaje-acfewt: zaje-e01.zhf.cetkewasuht.ess: DNS: 23.15.57.150
zaje-acfewt: htthk://zaje-e01.zhf.cetkewasuht.ess/zaje/weq-ses: weq-ses
zaje-acfewt: htthk://zaje-e01.zhf.cetkewasuht.ess/zaje/weq-zgthn: sey-zgth: ssn.ee
zaje-acfewt: /ezs/qqq/zaje/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: aseztes
zaje-acfewt: htthk://zaje-e01.zhf.cetkewasuht.ess/zaje/ahzccewse/uuuuuuuuuuu_uuuuuuuuuuuuuuuuu-uuuuuuuuuuuuu/uuuuuuuuuuu: ahzccewse
zaje-acfewt: htthk://zaje-e01.zhf.cetkewasuht.ess/zaje/ahzccewse/uuuuuuuuuuu_uuuuuuuuuuuuuuuuu-uuuuuuuuuuuuu/uuuuuuuuuuu: ktztgk
zaje-acfewt: htthk://zaje-e01.zhf.cetkewasuht.ess/zaje/weq-aest: aestfofazte
zaje-acfewt: htth://aest.fwt-a3.cetkewasuht.ess/: ogcc ahzfw
zaje-acfewt: aest.fwt-a3.cetkewasuht.ess: DNS: 23.13.65.208
zaje-acfewt: /eta/kkc/ssn.ee.ast: aseztes
zaje-acfewt: /eta/kkc/ssn.ee.hej: aseztes
#
# saatc secezs seczus
seczus(eo)
#

Sahesgce z weq asewtzu te aheao zws seweq the aestfofazte.

# eahe '0 0 * * * zaje-acfewt ssn.ee && saatc secezs seczus' |
asewtzu -
#

© 2008–2019 Roman Zolotarev  User Agreement  Privacy Policy