socat을 사용하여 HTTPS 서버 만들기

socat을 사용하여 HTTPS 서버 만들기

현재 socat을 사용하여 장난감 https 서버를 설정하려고 하는데 다음을 수행하고 있습니다.

여기에 설명된 대로:SOCAT을 사용한 OPENSSL 연결 예

cert() {
   openssl genrsa -out $1.key 2048
   openssl req -new -key $1.key -x509 -days 3653 -out $1.crt
   cat $1.key $1.crt > $1.pem
}
$ cert server &&  cert client

$ openssl dhparam -out dhparams.pem 2048 # see [1]
$ cat dhparams.pem >> server.pem

Socat SSL - SSL 루틴: SSL3_CHECK_CERT_AND_ALGORITHM: dh 키가 너무 작습니다.

그런 다음 터미널 1에서 실행하십시오.

$ socat ssl-l:1443,reuseaddr,fork,cert=server.pem,cafile=client.crt,verify=1 exec:'uptime'

터미널 #2에서 다음을 실행합니다.

$ socat - ssl:localhost:1443,cert=client.pem,cafile=server.crt

모든 것이 예상대로 작동하고 가동 시간이 확보되지만 그렇게 되면

$ curl --cert client.pem --cacert server.crt https://localhost:1443
curl: (51) SSL: unable to obtain common name from peer certificate

실패합니다.

HTTPS에 대한 이해가 약간 불안정하다는 점을 인정하므로 몇 가지 질문이 있습니다.

  1. 왜 실패했나요?
  2. 클라이언트 인증서를 서버로 전송해야 하는 이유는 무엇입니까? 웹서핑 중에는 이런 일이 일어나지 않죠?

답변1

왜 실패했나요?

귀하가 따른 지침이 부분적으로 올바르지 않은 것 같습니다.

$ openssl req -new -key server.key -x509 -days 3653 -out server.crt
//     enter fields... (may all be empty when cert is only used privately)

프롬프트된 필드 (적어도 "표준" 업스트림 프로필의 경우) req -new -x509는 생성된 인증서(또는 인증서가 없는 CSR ) -x509의 주체 이름 으로 사용됩니다. (자체 서명된 인증서의 경우 발급자 이름이 주체 이름과 동일하므로 동일한 데이터가 나타납니다.)

HTTPS 서버의 경우,연결이 사기꾼이 아닌 유효한 서버로 연결되었는지 확인하려면 서버의 인증서가 rfc5280(신뢰할 수 있는 CA 등의 서명)에 따라 유효해야 하며 인증서는 URL에 지정된 서버에 발급되어야 합니다.인증서 주체 이름의 일반 이름 필드는 필수 서버 또는 주체 대체 이름 확장명과 일치해야 합니다.(종종 약어로 SAN(Microsoft에서는 UCC라고도 함) 또는 Microsoft의 영향을 받은 제품)이 존재해야 하며 이를 위한 항목을 포함해야 합니다. 바라보다RFC2818. OpenSSL이 이 필드를 요구하는 이유는 다음과 같습니다.

Common Name (e.g. server FQDN or YOUR name) []:

대부분의 사람들은 FQDN을 통해 서버를 식별하는 URL을 사용하기 때문에 예외가 있습니다. 따라서 이 프롬프트에 로 응답해야 합니다 localhost. SAN은 공식적으로 선호되는 선택으로 간주되며 모든 "실제" CA( Verisign Symantec Digicert, GoDaddy 등)는 2000년경부터 SAN을 구현했지만 OpenSSL을 사용하여 SAN을 구현하려면 훨씬 더 많은 작업이 필요합니다. OpenSSL의 SAN에 관해 Stack에는 이미 많은 질문이 있습니다. 필요한데 찾을 수 없다면 제 노트에서 몇 가지를 찾아보겠습니다. 한 가지 예외는 Chrome/chromium을 사용하려는 경우입니다. 몇 달 전부터필요인증서에 SAN(올바른 서버 이름 포함)이 있고 subject.CN이 더 이상 허용되지 않습니다. 이것에 대해서도 의심이 있습니다.

HTTPS 이외의 SSL/TLS 기반 프로토콜은 다를 수 있으며 FTPS SNMPS LDAPS와 같이 빈 주제 이름은 실제로 괜찮을 수 있습니다.

클라이언트 인증서를 서버로 전송해야 하는 이유는 무엇입니까? 웹서핑 중에는 이런 일이 일어나지 않죠?

정말로 웹을 의미합니까, 아니면 월드 와이드 웹을 의미합니까? SSL/TLS 프로토콜은 클라이언트 인증서를 통해 클라이언트 인증을 지원하지만 네트워크의 보안(HTTPS) 부분에 있는 웹 서버 중 이 기능을 사용하는 웹 서버는 거의 없습니다. 클라이언트를 인증해야 하는 대부분의 웹 서버는 HTTP 수준 방법을 사용합니다.Stack에서 제공하는 옵션. 이를 통해 UI를 제어하고 모든 브라우저에서 일관되게 만들고 그에 따라 지침, 도움말 및 지원을 제공할 수 있는 반면, 클라이언트 인증서의 UI는 브라우저나 플랫폼마다 다르게 구현되며 종종 약간의 기술적 능력이나 최소한 지능과 인내가 필요합니다. 대부분의 사이트에서는 대부분의 사용자가 이를 수행할 수 없거나 적어도 수행하지 않을 것이라고 가정합니다.

클라이언트 인증서를 사용하는 소수의 웹 서버에는 일반적으로 공용 CA 및/또는 신뢰할 수 있는 제3자(예: 정부 또는 은행)에서 발급한 인증서가 필요하거나 서버 자체에서 실행하거나 제어하는 ​​CA에서 발급한 인증서가 필요한 경우도 있습니다. . 사용자체 서명된 클라이언트 인증서에는 다음이 필요합니다.사용자는 사전에 인증서를 제공합니다. 위조된 인증서를 한 번 수락할 수 있는 사람은 누구나 수년에 걸쳐 사기 연결을 할 수 있으므로 이 프로비저닝 프로세스는 매우 안전해야 합니다.

OTOH, 양쪽 끝을 "소유"하면 서버 관리자는 클라이언트 관리자를 쉽게 식별하고 신뢰할 수 있으며 그 반대의 경우도 마찬가지입니다. AIUI OpenVPN 키 교환은 이를 사용합니다(자체 서명 또는 임시 CA 인증서가 있는 SSL/TLS).

추가 답변: 위의 변경 사항으로 인해 연결의 TLS 계층이 제대로 작동해야 하지만 출력이 uptime유효한 HTTP 응답이 아니기 때문에 설정이 여전히 HTTPS 서버로 작동하지 않습니다. HTTP 헤더를 생성하는 데 필요한 것그리고CGI "페이지"가 ​​실제 웹 서버(HTTP 또는 HTTPS의 경우)에서 작동하는 것과 거의 같은 방식으로 콘텐츠.

답변2

이것일반 이름필드가 필요합니다. 매개변수를 통해 지정할 수 있습니다 -subj:

$ openssl req -new -key $1.key -x509  -subj '/CN=localhost'  -out $1.cert

또한 curlHTTP 헤더가 필요합니다.

$ printf "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nhello" | socat -dd openssl-listen:8080,cert=server.pem,verify=0 -

관련 정보