├── LICENSE ├── README.md ├── defaulter.png └── src └── etc ├── daily.local ├── httpd.conf ├── pf.conf.defaulter └── relayd.conf /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Horia Racoviceanu 2 | 3 | Permission to use, copy, modify, and distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # defaulter 2 | 3 | Default OpenBSD Web Server 4 | ```console 5 | server "default" {} 6 | ``` 7 | 8 | ![defaulter logo](defaulter.png) 9 | 10 | ## About 11 | > nice default servers for httpd(8) 12 | 13 | The most underused feature of the [`httpd`](https://man.openbsd.org/httpd.8) HTTP daemon is the default server. 14 | 15 | The default server is automatically used by httpd(8) in the absence of a custom server configuration. 16 | 17 | Using default servers can simplify website hosting. 18 | 19 | ## Why 20 | 21 | * reduce configuration clutter 22 | * simplify webhosting operations 23 | * keep your custom servers or add new ones 24 | * keep your existing apps or add new ones 25 | 26 | ## How 27 | 28 | To add a new website, simply [create a directory](#add-the-document-root-for-wwwexamplecom) and [configure TLS](#configure-tls). 29 | 30 | ## Features 31 | 32 | * default http server to redirect the request scheme "http" to "https" 33 | * opt-in https server to redirect the parent domain to its "www" subdomain 34 | * default https server with dynamic document root 35 | 36 | ## Getting started 37 | 38 | Let's add the `www.example.com` website using default servers. 39 | 40 | *please keep reading, a reward for all defaulters' waiting at the end* 41 | 42 | Add DNS resource records A[AAA] or CNAME for your domain(s) 43 | ```console 44 | example.com. IN A 203.0.113.4 45 | example.com. IN AAAA 2001:0db8::4 46 | www.example.com. IN CNAME example.com. 47 | ``` 48 | 49 | If needed, include [*pf.conf.defaulter*](src/etc/pf.conf.defaulter) in */etc/pf.conf* 50 | ```console 51 | # pf.conf 52 | # Allow traffic on port 80 and 443 to and from the external interface 53 | # 54 | anchor "defaulter" on egress { 55 | # inbound for relayd 56 | pass in log proto tcp to (egress) port { http https } \ 57 | keep state (max 500, max-src-conn-rate 100/10) 58 | 59 | # outbound for other services and apps 60 | pass out log proto tcp from (egress) to port { http https } 61 | } 62 | anchor "relayd/*" 63 | ... 64 | ``` 65 | 66 | Install and configure [*httpd.conf*](src/etc/httpd.conf) 67 | 68 | Add the parent domain *example.com* alias to redirect it to `www.example.com`: 69 | ```console 70 | # httpd.conf 71 | server "defaulter https redirect to www" { 72 | alias "example.com" 73 | ... 74 | ``` 75 | ```sh 76 | rcctl reload httpd 77 | ``` 78 | 79 | #### Add the document root for `www.example.com` 80 | ```sh 81 | mkdir /var/www/htdocs/www.example.com 82 | echo Hello > /var/www/htdocs/www.example.com/index.html 83 | ``` 84 | 85 | Install and configure [*relayd.conf*](src/etc/relayd.conf) 86 | 87 | To initialize `relayd` without certificates, comment out the relay "https" and "https2" as well as the *tls keypair* statements from [*relayd.conf*](src/etc/relayd.conf) 88 | ```sh 89 | rcctl restart relayd 90 | ``` 91 | 92 | #### Configure TLS 93 | ```console 94 | # acme-client.conf 95 | domain www.example.com { 96 | alternative names { example.com } 97 | domain key "/etc/ssl/private/www.example.com.key" 98 | domain full chain certificate "/etc/ssl/www.example.com.crt" 99 | sign with letsencrypt 100 | } 101 | ... 102 | ``` 103 | ```sh 104 | acme-client -v www.example.com 105 | ocspcheck -vNo /etc/ssl/www.example.com.{ocsp,crt} 106 | ``` 107 | 108 | Uncomment the earlier comments from [*relayd.conf*](src/etc/relayd.conf) 109 | 110 | Add the `www.example.com` keypair: 111 | ```console 112 | # relayd.conf 113 | tls keypair www.example.com 114 | ... 115 | ``` 116 | ```sh 117 | rcctl restart relayd 118 | ``` 119 | 120 | For the promised reward, please note that subsequent TLS modifications only involve `acme-client` and changin the *tls keypair* for `relayd`. 121 | 122 | Install [*daily.local*](src/etc/daily.local) for daily updates: 123 | ```console 124 | # daily.local 125 | name="$(awk '/^[[:space:]]*tls keypair/{printf "%s ",$NF}' /etc/relayd.conf)" 126 | for n in ${name} 127 | do 128 | next_part "Let's Encrypt $n" 129 | acme-client -v $n 130 | ocspcheck -vNo /etc/ssl/$n.{ocsp,crt} 131 | done 132 | rcctl restart relayd 133 | ``` 134 | 135 | -------------------------------------------------------------------------------- /defaulter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/horia/defaulter/fe0999f001f300e48638b4fecbedba1b703d01c0/defaulter.png -------------------------------------------------------------------------------- /src/etc/daily.local: -------------------------------------------------------------------------------- 1 | name="$(awk '/^[[:space:]]*tls keypair/{printf "%s ",$NF}' /etc/relayd.conf)" 2 | for n in ${name} 3 | do 4 | next_part "Let's Encrypt $n" 5 | acme-client -v $n 6 | ocspcheck -vNo /etc/ssl/$n.{ocsp,crt} 7 | done 8 | rcctl restart relayd 9 | 10 | -------------------------------------------------------------------------------- /src/etc/httpd.conf: -------------------------------------------------------------------------------- 1 | # $OpenBSD: httpd.conf,v 1.20 2018/06/13 15:08:24 reyk Exp $ 2 | 3 | # 4 | # Macros 5 | # 6 | IP="lo0" 7 | 8 | # 9 | # Servers 10 | # 11 | # default http server to redirect the request scheme "http" to "https" 12 | server "defaulter http redirect scheme" { 13 | listen on $IP port http 14 | 15 | tcp nodelay 16 | log style forwarded 17 | 18 | # ACME challenge 19 | location "/.well-known/acme-challenge/*" { 20 | root "/acme" 21 | request strip 2 22 | } 23 | 24 | location "*" { 25 | block return 302 "https://$HTTP_HOST$REQUEST_URI" 26 | } 27 | } 28 | 29 | # default https server 30 | server "defaulter https" { 31 | listen on $IP port https # using relayd TLS server 32 | 33 | hsts subdomains 34 | 35 | tcp nodelay 36 | log style forwarded 37 | 38 | # ACME challenge over TLS 39 | location "/.well-known/acme-challenge/*" { 40 | root "/acme" 41 | request strip 2 42 | } 43 | 44 | # Set the directory index file to index.html 45 | location "*/" { 46 | request rewrite "/$HTTP_HOST$DOCUMENT_URI/index.html?$QUERY_STRING" 47 | } 48 | 49 | location "/*" { 50 | request rewrite "/$HTTP_HOST$REQUEST_URI" 51 | } 52 | } 53 | 54 | # opt-in https server to redirect the parent domain to its "www" subdomain 55 | server "defaulter https redirect to www" { 56 | # parent domain 57 | alias "example.com" 58 | 59 | listen on $IP port https # using relayd TLS server 60 | 61 | hsts subdomains 62 | 63 | tcp nodelay 64 | log style forwarded 65 | 66 | # ACME challenge over TLS 67 | location "/.well-known/acme-challenge/*" { 68 | root "/acme" 69 | request strip 2 70 | } 71 | 72 | location "*" { 73 | block return 302 "$REQUEST_SCHEME://www.$HTTP_HOST$REQUEST_URI" 74 | } 75 | } 76 | 77 | # a custom http[s] server 78 | #server "openbsd.mirror.example.com" { 79 | # listen on $IP port http 80 | # listen on $IP port https # using relayd TLS server 81 | # 82 | # tcp nodelay 83 | # log style forwarded 84 | # 85 | # # ACME challenge over TLS 86 | # location "/.well-known/acme-challenge/*" { 87 | # root "/acme" 88 | # request strip 2 89 | # } 90 | # 91 | # # Serve up ftp space mounted in /var/www/pub 92 | # # 93 | # # Mirror for distribution sets (!) https://www.openbsd.org/httpd.conf 94 | # location "/pub/OpenBSD*" { 95 | # root "/" 96 | # directory auto index 97 | # } 98 | # 99 | # # Send man.cgi requests to man.openbsd.org 100 | # location "/cgi-bin/man.cgi*" { 101 | # block return 301 "https://man.openbsd.org$REQUEST_URI" 102 | # } 103 | # # Send cvsweb requests to cvsweb.openbsd.org 104 | # location "/cgi-bin/cvsweb*" { 105 | # block return 301 "https://cvsweb.openbsd.org$REQUEST_URI" 106 | # } 107 | #} 108 | 109 | # 110 | # Include MIME types instead of the built-in ones 111 | # 112 | types { 113 | # system-wide 114 | include "/usr/share/misc/mime.types" 115 | 116 | # custom (overwrite) 117 | # 118 | # Data interchange 119 | application/ld+json jsonld 120 | application/vnd.geo+json geojson 121 | 122 | # Manifest files 123 | application/manifest+json webmanifest 124 | application/x-web-app-manifest+json webapp 125 | text/cache-manifest appcache 126 | 127 | # Media files 128 | audio/x-wav wav 129 | image/jxr jxr hdp wdp 130 | video/ogg ogv 131 | 132 | # Microsoft Office 133 | application/vnd.openxmlformats-officedocument.wordprocessingml.document docx 134 | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx 135 | application/vnd.openxmlformats-officedocument.presentationml.presentation pptx 136 | 137 | # Web fonts 138 | application/font-woff2 woff2 139 | application/x-font-ttf ttc ttf 140 | 141 | # Other 142 | application/x-bb-appworld bbaw 143 | application/x-bittorrent torrent 144 | application/x-chrome-extension crx 145 | application/x-opera-extension oex 146 | application/xslt+xml xsl 147 | text/markdown md 148 | text/vcard vcard vcf 149 | text/vnd.rim.location.xloc xloc 150 | text/vtt vtt 151 | 152 | # Necessary to ensure patch files show up as text not binary 153 | text/plain sig 154 | } 155 | 156 | -------------------------------------------------------------------------------- /src/etc/pf.conf.defaulter: -------------------------------------------------------------------------------- 1 | # Allow traffic on port 80 and 443 to and from the external interface 2 | # 3 | anchor "defaulter" on egress { 4 | # inbound for relayd 5 | pass in log proto tcp to (egress) port { http https } \ 6 | keep state (max 500, max-src-conn-rate 100/10) 7 | 8 | # outbound for other services and apps 9 | pass out log proto tcp from (egress) to port { http https } 10 | } 11 | anchor "relayd/*" 12 | 13 | -------------------------------------------------------------------------------- /src/etc/relayd.conf: -------------------------------------------------------------------------------- 1 | # $OpenBSD: relayd.conf,v 1.5 2018/05/06 20:56:55 benno Exp $ 2 | # 3 | # Macros 4 | # 5 | ext_ip1="203.0.113.4" 6 | ext_ip2="2001:0db8::4" 7 | app_port="31337" 8 | table { 10.0.0.4 } 9 | table { 127.0.0.1, ::1 } 10 | 11 | # 12 | # Global Options 13 | # 14 | log connection errors 15 | 16 | # 17 | # Redirections 18 | # 19 | redirect "http" { 20 | listen on $ext_ip1 port http 21 | listen on $ext_ip2 port http 22 | 23 | forward to check tcp 24 | } 25 | 26 | # 27 | # Relays 28 | # 29 | http protocol "https" { 30 | match request header append "X-Forwarded-For" value "$REMOTE_ADDR" 31 | match request header append "X-Forwarded-By" \ 32 | value "$SERVER_ADDR:$SERVER_PORT" 33 | match request header set "Connection" value "close" 34 | 35 | match request header "Host" value "app.*" forward to 36 | 37 | tcp { sack, backlog 128 } 38 | 39 | tls ciphers "HIGH:!AES128:!kRSA:!aNULL" # default: "HIGH:!aNULL" 40 | tls ecdhe "P-384,P-256,X25519" # default: "X25519,P-256,P-384" 41 | 42 | tls keypair www.example.com 43 | tls keypair app.example.com 44 | } 45 | 46 | # a relay for each IP 47 | 48 | relay "https" { 49 | listen on $ext_ip1 port https tls 50 | 51 | protocol "https" 52 | 53 | forward to check tcp 54 | forward to port $app_port check tcp 55 | } 56 | 57 | relay "https2" { 58 | listen on $ext_ip2 port https tls 59 | 60 | protocol "https" 61 | 62 | forward to check tcp 63 | forward to port $app_port check tcp 64 | } 65 | 66 | --------------------------------------------------------------------------------