인증서 문제
보안 연결이 실패하는 원인은 대부분 인증서입니다. 이 페이지의 오류 문장은 SDK 예제(opcua_client)에서 실제로 나온 것입니다. 인증서 요건은 보안에서, 인증서를 만드는 방법은 PKI와 신뢰 설정에서 설명합니다.
먼저 확인할 것
섹션 제목: “먼저 확인할 것”인증서의 주체, 대체 이름, 키 용도, 유효 기간을 확인합니다.
openssl x509 -in server.cert.pem -noout -subject -dates -ext subjectAltName,keyUsage,extendedKeyUsageDER 파일이면 -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.20Windows의 컴퓨터 이름
섹션 제목: “Windows의 컴퓨터 이름”일부 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로 만든 인증서를 지정합니다.
광고하는 endpoint URL
섹션 제목: “광고하는 endpoint URL”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의 경로만 확인합니다. 호스트가 달라도 경로가 같으면 받습니다.
ApplicationUri 규칙
섹션 제목: “ApplicationUri 규칙”인증서의 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에서 인증서 만들기
섹션 제목: “Windows에서 인증서 만들기”Windows에는 OpenSSL이 기본으로 없습니다. OpenSSL 3을 설치하고 같은 템플릿과 명령을 씁니다. PowerShell에서는 줄 끝의 \ 대신 한 줄로 이어 씁니다. 개인 키 파일은 실행 계정만 읽을 수 있게 NTFS 권한을 설정합니다.