OpenBSD, 릴레이 및 acme-client: 하위 도메인의 TLS 인증서를 읽을 수 없습니다: "서버에서 빈 응답"

OpenBSD, 릴레이 및 acme-client: 하위 도메인의 TLS 인증서를 읽을 수 없습니다: "서버에서 빈 응답"

Relayd/httpd/acme-client가 있는 OpenBSD 서버. 달리려고 노력하다https://mydomain.com(애플리케이션 서버 포트 32489),https://webmail.mydomain.com(48293) 및https://forum.mydomain.com(28192). 세 사이트 모두 동일한 TLS 인증서를 공유합니다. 일반 HTTP는 TLS 인증서(acme-client)를 생성하는 데에만 사용됩니다.

지금까지https://mydomain.com예상대로 작동하지만 나머지 두 개는 다음을 반환합니다.

curl -vvv https://webmail.mydomain.com

* Rebuilt URL to: https://webmail.mydomain.com/
*   Trying XXX...
* TCP_NODELAY set
* Connected to webmail.mydomain.com (XXX) port 443 (#0)
* schannel: SSL/TLS connection with webmail.mydomain.com port 443 (step 1/3)
* schannel: checking server certificate revocation
* schannel: sending initial handshake data: sending 180 bytes...
* schannel: sent initial handshake data: sent 180 bytes
* schannel: SSL/TLS connection with webmail.mydomain.com port 443 (step 2/3)
* schannel: failed to receive handshake, need more data
* schannel: SSL/TLS connection with webmail.mydomain.com port 443 (step 2/3)
* schannel: encrypted data got 4096
* schannel: encrypted data buffer: offset 4096 length 4096
* schannel: encrypted data length: 4032
* schannel: encrypted data buffer: offset 4032 length 4096
* schannel: received incomplete message, need more data
* schannel: SSL/TLS connection with webmail.mydomain.com port 443 (step 2/3)
* schannel: encrypted data got 907
* schannel: encrypted data buffer: offset 4939 length 5056
* schannel: sending next handshake data: sending 93 bytes...
* schannel: SSL/TLS connection with webmail.mydomain.com port 443 (step 2/3)
* schannel: encrypted data got 51
* schannel: encrypted data buffer: offset 51 length 5056
* schannel: SSL/TLS handshake complete
* schannel: SSL/TLS connection with webmail.mydomain.com port 443 (step 3/3)
* schannel: stored credential handle in session cache
> GET / HTTP/1.1
> Host: webmail.mydomain.com
> User-Agent: curl/7.55.1
> Accept: */*
>
* schannel: client wants to read 102400 bytes
* schannel: encdata_buffer resized 103424
* schannel: encrypted data buffer: offset 0 length 103424
* schannel: encrypted data got 31
* schannel: encrypted data buffer: offset 31 length 103424
* schannel: server closed the connection
* schannel: schannel_recv cleanup
* Empty reply from server
* Connection #0 to host webmail.mydomain.com left intact
curl: (52) Empty reply from server

acme-client.conf

authority letsencrypt {
  api url "https://acme-v02.api.letsencrypt.org/directory"
  account key "/etc/ssl/private/letsencrypt.key"
}

domain mydomain.com {
  alternative names { www.mydomain.com webmail.mydomain.com forum.mydomain.com }
  domain key "/etc/ssl/private/mydomain.com.key"
  domain full chain certificate "/etc/ssl/mydomain.com.crt"
  sign with letsencrypt
}

httpd.conf

ext_if="vio0"

types {
  include "/usr/share/misc/mime.types"
}

server "mydomain.com" {
  alias "www.mydomain.com"
  listen on $ext_if port 80
  location "/.well-known/acme-challenge/*" {
    root "/acme"
    request strip 2
  }
  location "*" {
    block return 301 "https://mydomain.com$REQUEST_URI"
  }
}

server "webmail.mydomain.com" {
  listen on $ext_if port 80
  location "/.well-known/acme-challenge/*" {
    root "/acme"
    request strip 2
  }
  location "*" {
    block return 301 "https://webmail.mydomain.com$REQUEST_URI"
  }
}

server "forum.mydomain.com" {
  listen on $ext_if port 80
  location "/.well-known/acme-challenge/*" {
    root "/acme"
    request strip 2
  }
  location "*" {
    block return 301 "https://forum.mydomain.com$REQUEST_URI"
  }
}

relayd.conf

ip="XXX"

table <cms> { 127.0.0.1 }
cms_port="32489"

table <webmail> { 127.0.0.1 }
webmail_port="48293"

table <forum> { 127.0.0.1 }
forum_port="28192"

table <httpd> { 127.0.0.1 }
httpd_port="80"

log connection errors

http protocol "http" {
  match request header set "Connection" value "close"
  match response header remove "Server"
}

relay "http_relay" {
  listen on $ip port http
  protocol "http"
  forward to <httpd> port $httpd_port
}

http protocol "https" {
  match header log "Host"
  match header log "X-Forwarded-For"
  match header log "User-Agent"
  match header log "Referer"
  match url log

  match header set "X-Forwarded-For" value "$REMOTE_ADDR"
  match header set "X-Forwarded-By" value "$SERVER_ADDR:$SERVER_PORT"
  match header set "Keep-Alive" value "$TIMEOUT"

  # Best practice security headers
  match response header remove "Server"
  match response header append "Strict-Transport-Security" value "max-age=31536000; includeSubDomains"
  match response header append "X-Frame-Options" value SAMEORIGIN
  match response header append "X-XSS-Protection" value "1; mode=block"
  match response header append "X-Content-Type-Options" value nosniff
  match response header append "Referrer-Policy" value strict-origin
  match response header append "Feature-Policy" value "accelerometer 'none'; camera 'none'; geolocation 'none'; gyroscope 'none'; magnetometer 'none'; microphone 'none'; payment 'none'; usb 'none'"

  pass request header "Host" value "mydomain.com" forward to <cms>
  pass request header "Host" value "www.mydomain.com" forward to <cms>
  pass request header "Host" value "webmail.mydomain.com" forward to <webmail>
  pass request header "Host" value "forum.mydomain.com" forward to <forum>
  tls keypair "mydomain.com"
}

relay "https_relay" {
  listen on $ip port https tls

  protocol "https"

  forward to <cms> port $cms_port
  forward to <webmail> port $webmail_port
  forward to <forum> port $forum_port
}

답변1

relaydTLS SNI는 아직 처리되지 않았으므로 tls keypair전달된 각 도메인에 대해 하나의 항목이 필요합니다. 이는 귀하가 서비스를 제공하는 각 도메인에 대해 개인 .key과 파일을 제공해야 함을 의미합니다. .crt이는 심볼릭 링크를 통해 쉽게 처리할 수 있습니다. 예를 들면 다음과 같습니다.

# cd /etc/ssl
# ln -s mydomain.com.crt www.mydomain.com.crt
# cd /etc/ssl/private
# ln -s mydomain.com.key www.mydomain.com.key

그런 다음 추가

tls keypair "www.mydomain.com"

http protocol "https" {...}부분 에 relayd.conf. 달리기

# relayd -n

모든 것이 괜찮은지 알려줄 것입니다.

relayd인증서를 업데이트한 후에는 다시 로드해야 합니다. 이는 일반적으로 작업 httpd에 의해 처리됩니다. 상태 페이지cronmanacme-client

A cron(8) job can renew the certificate as necessary.  On renewal,
httpd(8) is reloaded:

       ~ * * * * acme-client example.com && rcctl reload httpd

따라서 이 경우 합계를 relayd다시 로드하려면 줄 끝에 추가해야 합니다 . 다른 방법이나 스크립트를 사용하는 경우 적절하게 조정해야 합니다.httpdrelayd

관련 정보