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

보안 연결 문제

Modbus/TCP Security의 실패는 세 단계에서 납니다. 메시지의 앞부분으로 단계를 구분합니다.

단계 메시지 형태 언제
인증서 파일 읽기 Config(...), Crypto(...), Io(...) connect에서 TLS를 시작하기 전
TLS 핸드셰이크 Security("Handshake(...)") connect 중
연결 뒤 Io(Other, "...SSL alert ..."), 예외 01 첫 요청이나 권한 검사에서

PDComm은 보안 연결이 실패해도 평문 TCP나 인증 전용 모드로 낮추지 않습니다. 인증서 검증도 끌 수 없습니다.

메시지 원인과 해결
Config("Chain must include its root CA") chain 파일이 루트 CA로 끝나지 않습니다. 자기 인증서, 중간 CA, 루트 CA 순서로 이어 붙입니다.
Config("Device certificate must be X509v3") 장치 인증서가 X.509 v1입니다. v3으로 다시 발급합니다. OpenSSL 3의 x509 -req는 기본으로 v3을 만듭니다.
Config("Empty certificate chain") chain 파일에 인증서가 없습니다.
Config("Revocation checking requires CRLs") require_revocation이 true인데 crls가 비어 있습니다.
Config("Cannot load CRL") CRL 파일을 읽을 수 없거나 형식이 틀렸습니다.
Crypto(ErrorStack([... "calling fopen(<경로>, r)" ...])) private_key나 trust 경로의 파일이 없습니다. 메시지 안의 경로를 확인합니다.
Crypto(ErrorStack([... reason: "key values mismatch" ...])) private_key가 chain의 첫 인증서와 짝이 아닙니다.
Io(Os { code: 2, kind: NotFound, message: "No such file or directory" }) chain 파일이 없습니다.
Invalid Security configuration chain, private_key, trust 중 빈 값이 있거나 mode가 틀렸습니다. 직렬 구성에 security를 넣어도 이 오류입니다.
메시지 원인과 해결
Security("Handshake(\"error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:...\")") 클라이언트가 서버 인증서를 검증하지 못했습니다. 아래 표를 봅니다.
Security("Handshake(\"...ssl/tls alert handshake failure...SSL alert number 40\")") 양쪽의 mode가 다르거나 공통 암호 방식이 없습니다. 양쪽을 같은 모드로 맞춥니다. authentication_only는 RSA 인증서가 필요합니다.
Security("Handshake(\"unexpected EOF\")") 상대가 TLS를 쓰지 않습니다. 평문 Modbus TCP 서버에 보안 클라이언트로 접속했습니다.
Io(ConnectionRefused, ...) 서버가 그 포트에서 기다리지 않습니다. 보안 서버의 포트(예: 1802, 802)를 확인합니다.

certificate verify failed의 흔한 원인은 다음과 같습니다.

원인 확인
호스트 이름 불일치 클라이언트의 hostname(기본 localhost)이 서버 인증서 SAN에 있어야 합니다. IP로 접속하면 hostname에 그 IP를 넣고 SAN에도 IP: 항목이 있어야 합니다.
신뢰하지 않는 CA 클라이언트의 trust가 서버 인증서를 발급한 CA여야 합니다.
만료되었거나 아직 유효하지 않은 인증서 openssl x509 -in server.pem -noout -dates로 유효 기간과 PC 시계를 확인합니다.
v3이 아니거나 역할 확장이 잘못된 인증서 장치 인증서는 X.509v3이어야 하고, 역할 확장은 UTF8String 하나여야 합니다.

서버 쪽에서 클라이언트 인증서 검증이 실패하면, TLS 1.3에서는 클라이언트의 connect가 먼저 성공하고 첫 요청에서 실패합니다(다음 절).

메시지 원인과 해결
Io(Other, "error:0A000414:SSL routines:ssl3_read_bytes:ssl/tls alert certificate revoked:...SSL alert number 44") 서버가 CRL에서 클라이언트 인증서의 폐기를 확인했습니다. 새 인증서를 발급받습니다.
Io(Other, "error:0A000418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca:...SSL alert number 48") 서버가 클라이언트 인증서를 발급한 CA를 신뢰하지 않습니다. 서버의 trust가 클라이언트 인증서를 발급한 CA인지 확인합니다.
Io(ConnectionReset, "Connection reset by peer (os error 54)") 평문 클라이언트가 보안 서버에 접속했습니다. 클라이언트에 security를 넣습니다.
응답이 예외 01(예: [134,1]) TLS는 정상이지만 서버의 역할 정책이 그 기능을 허용하지 않습니다. 서버의 roles와 null_role, 클라이언트 인증서의 역할을 확인합니다.

이런 실패 뒤 state의 connected는 false입니다. 원인을 고친 뒤 다시 connect합니다.

클라이언트 인증서의 역할은 다음 명령으로 봅니다.

터미널 창
openssl x509 -in reader.pem -noout -text | grep -A1 '50316'
1.3.6.1.4.1.50316.802.1:
..reader
  • 확장이 없으면 서버는 null_role을 적용합니다.
  • 역할 이름은 대소문자를 구분하며, 값 전체가 이름 하나입니다. reader,operator는 역할 두 개가 아니라 reader,operator라는 이름 하나입니다.

인증서 만들기부터 다시 확인하려면 Modbus/TCP Security 튜토리얼을 따릅니다. 문의할 때는 개인 키를 보내지 않고, 인증서의 지문과 유효 기간, 오류 메시지만 보냅니다.