콘텐츠로 이동
무료 평가 시작

인증서 문제

보안 연결이 실패하는 원인은 대부분 인증서입니다. 이 페이지의 오류 문장은 SDK 예제(opcua_client)에서 실제로 나온 것입니다. 인증서 요건은 보안에서, 인증서를 만드는 방법은 PKI와 신뢰 설정에서 설명합니다.

인증서의 주체, 대체 이름, 키 용도, 유효 기간을 확인합니다.

터미널 창
openssl x509 -in server.cert.pem -noout -subject -dates -ext subjectAltName,keyUsage,extendedKeyUsage

DER 파일이면 -inform DER를 붙입니다. 어느 쪽에서 거부했는지는 오류 문장으로 구분합니다.

오류 문장 거부한 쪽
OPC UA security <이름> 이 클라이언트. 서버 인증서나 자신의 인증서를 검사하다 실패했습니다.
OPC UA status: 0x80130000 서버. 클라이언트 인증서를 거부했고 이유는 알리지 않습니다.
Error: connect failed (SDK status 5): OPC UA security CertificateUntrusted

클라이언트에 지정한 신뢰할 서버 인증서(TRUSTED_SERVER_DER, trusted_server_der)가 서버가 실제로 쓰는 인증서와 다릅니다. 서버 인증서를 다시 만들었다면 클라이언트 쪽 파일도 바꿔야 합니다. 서버가 쓰는 DER 파일을 지정합니다.

Error: connect failed (SDK status 5): OPC UA status: 0x80130000

서버가 클라이언트 인증서를 신뢰하지 않습니다(BadSecurityChecksFailed). 서버의 신뢰할 클라이언트 인증서(trusted_client_der, 시뮬레이터 server.trust)에 클라이언트의 DER 인증서를 넣고 서버를 다시 시작합니다.

PDComm 클라이언트는 endpoint URL의 호스트를 서버 인증서의 subjectAltName과 비교합니다.

  • URL의 호스트가 이름이면 DNS: 항목과, IP 주소면 IP: 항목과 비교합니다. 주체의 CN은 쓰지 않습니다.
  • 와일드카드는 이름 전체 레이블에만 맞습니다. *.example.com은 plc.example.com에 맞지만 부분 와일드카드는 쓰지 않습니다.
  • 비교에 쓰는 이름은 사용자가 넘긴 URL의 호스트입니다. 서버가 GetEndpoints로 알려 준 URL이 아닙니다.

서버 인증서에 접속한 이름이 없으면 다음 오류가 납니다.

Error: connect failed (SDK status 5): OPC UA security CertificateHostInvalid

위 오류는 DNS:plc-01.example.invalid만 가진 서버 인증서로 opc.tcp://localhost:4840/pdcomm에 접속했을 때 나왔습니다. 클라이언트가 쓰는 모든 이름과 주소를 서버 인증서에 넣습니다.

subjectAltName = URI:urn:pdcomm:opcua:server, DNS:localhost, DNS:my-pc, DNS:my-pc.plant.example, IP:127.0.0.1, IP:192.168.10.20

일부 Windows 클라이언트는 endpoint URL의 localhost를 그 컴퓨터의 이름으로 바꿔 접속하고, 서버 인증서의 호스트 이름도 그 이름으로 검사합니다. 서버 인증서에 localhost만 있으면 이런 클라이언트는 같은 컴퓨터에서도 호스트 이름 오류(BadCertificateHostNameInvalid)를 보고하거나 경고를 띄웁니다. 서버가 GetEndpoints로 localhost URL을 광고할 때도 같은 일이 생깁니다.

  • 서버 인증서에 컴퓨터 이름을 넣습니다. Windows에서는 hostname 명령으로 확인합니다. 도메인에 속한 컴퓨터라면 전체 이름(FQDN)도 넣습니다.
  • 다른 컴퓨터의 클라이언트가 접속한다면, 그 클라이언트가 쓰는 이름이나 IP 주소도 넣습니다.
  • PDComm 시뮬레이터가 인증서 파일 없이 만드는 신원에는 DNS:localhost, 수신 IP 주소(0.0.0.0이 아닐 때), server.advertised_host가 들어갑니다. 컴퓨터 이름으로 접속한다면 advertised_host에 그 이름을 넣습니다. 여러 이름이 필요하면 server.certificate와 server.private_key로 만든 인증서를 지정합니다.

GetEndpoints 응답에는 서버가 광고하는 endpoint URL이 들어갑니다.

  • SDK 메모리 서버는 pdcomm_opcua_server_options의 endpoint를 그대로 광고합니다. 클라이언트가 실제로 쓰는 이름으로 설정합니다.
  • 시뮬레이터 서버는 기본적으로 클라이언트가 GetEndpoints, FindServers, CreateSession 요청에 넣은 URL의 호스트와 포트를 그대로 돌려줍니다. 그래서 opc.tcp://192.168.10.20:4841/pdcomm/simulator로 탐색한 클라이언트는 같은 주소의 endpoint를 받습니다. server.advertised_host(헤드리스·MCP의 --advertised-host)를 정하면 언제나 그 이름을 돌려줍니다. NAT 너머의 공개 이름처럼 서버가 알 수 없는 이름을 써야 할 때 정합니다.

PDComm 서버는 Hello 메시지에서 URL의 경로만 확인합니다. 호스트가 달라도 경로가 같으면 받습니다.

인증서의 subjectAltName에는 URI: 항목이 정확히 하나 있어야 하고, 그 값이 응용 프로그램의 ApplicationUri와 같아야 합니다.

Error: connect failed (SDK status 5): OPC UA security CertificateUriInvalid

위 오류는 클라이언트 신원으로 서버 인증서(URI:urn:pdcomm:opcua:server)를 넘겼을 때 나왔습니다. 클라이언트는 연결 전에 자신의 인증서도 검사합니다. 클라이언트의 ApplicationUri 기본값은 urn:pdcomm:opcua:client, 서버는 urn:pdcomm:opcua:server입니다. 다른 값을 쓰려면 인증서의 URI와 옵션의 application_uri를 함께 바꿉니다.

인증서가 만료되었거나 아직 유효하지 않으면 다음 오류가 납니다.

Error: connect failed (SDK status 5): OPC UA security CertificateTimeInvalid

서버 인증서가 만료되었으면 서버가 시작하지 않습니다.

Error: create failed (SDK status 5): OPC UA security CertificateTimeInvalid

인증서를 새로 만들고 상대 쪽의 신뢰 설정도 새 인증서로 바꿉니다. 두 컴퓨터의 시각이 맞는지도 확인합니다.

Error: connect failed (SDK status 5): OPC UA security InvalidKey

개인 키가 인증서와 짝이 아닙니다. 인증서를 만들 때 함께 만든 *.key.pem을 지정합니다. RSA 키는 2048~4096비트여야 합니다.

Error: cannot read the certificate, private key or trusted server certificate

예제가 파일을 읽지 못했습니다. 경로, 권한, 파일 크기(64 KiB 이하, 빈 파일 아님)를 확인합니다.

Windows에는 OpenSSL이 기본으로 없습니다. OpenSSL 3을 설치하고 같은 템플릿과 명령을 씁니다. PowerShell에서는 줄 끝의 \ 대신 한 줄로 이어 씁니다. 개인 키 파일은 실행 계정만 읽을 수 있게 NTFS 권한을 설정합니다.