글 / Modbus·OPC UA

OPC UA 보안 모드와 인증서

모드와 정책을 일치시켜도 양측이 서로의 인증서를 신뢰 목록에 등록해야 접속되고, 사용자 인증은 그와 별개이다.

작성일 · 읽는 시간 3분 · OPC UA 1.05 기준

보안 모드

OPC UA는 주소가 올바르더라도 보안 설정이 서로 일치하지 않으면 접속되지 않는다. 양측이 함께 설정해야 하는 항목은 보안 모드, 보안 정책, 인증서의 세 가지이다. 보안 모드(MessageSecurityMode)는 메시지에 대한 서명과 암호화의 적용 여부를 지정한다.

모드 서명 암호화
None 없음 없음
Sign 있음 없음
SignAndEncrypt 있음 있음

접속을 위해 양측이 설정하는 보안 모드, 보안 정책, 인증서

보안 정책

보안 정책(SecurityPolicy)은 서명과 암호화에 사용할 알고리즘 집합의 이름이다.

  • Basic256Sha256, Aes128_Sha256_RsaOaep, Aes256_Sha256_RsaPss: 현재 사용하는 정책이다.
  • Basic128Rsa15, Basic256: SHA-1을 사용하는 이전 정책으로 폐기되었다.
  • None: 보안을 적용하지 않으며 인증서도 확인하지 않는다.

인증서 상호 신뢰

정책이 None이 아니면 클라이언트와 서버가 각각 애플리케이션 인증서를 보유하고, 채널(SecureChannel)을 열 때 이를 교환한다. 수신 측은 해당 인증서나 이를 발급한 CA가 자신의 신뢰 목록(TrustList)에 있는지 확인한다. 없으면 검증 결과가 Bad_CertificateUntrusted가 되어 수신 측은 접속을 거절한다. 서버가 거절할 때 클라이언트에는 이 코드 대신 Bad_SecurityChecksFailed가 반환된다.

클라이언트 인증서는 서버의 목록에, 서버 인증서는 클라이언트의 목록에 관리자가 등록한다. 어느 한 측에만 등록하면 접속되지 않는다.

서로의 인증서를 신뢰 목록에 등록하는 상호 신뢰 관계

pythonsecure.py
from asyncua import Client


async def connect():
    client = Client("opc.tcp://192.0.2.20:4840")
    # 인증서에 든 애플리케이션 URI와 같아야 한다
    client.application_uri = "urn:example:client"
    # 정책, 모드, 인증서, 개인 키 순서다. 정책 이름은 밑줄 없이 쓴다
    await client.set_security_string("Basic256Sha256,SignAndEncrypt,cert.der,key.pem")
    client.set_user("operator")
    client.set_password("secret")
    await client.connect()

사용자 인증

인증서로는 어느 애플리케이션인지를 확인한다. 사용자 신원은 세션을 열 때 별도로 제시한다. 익명, 사용자 이름과 비밀번호, 사용자 인증서, 발급받은 토큰 가운데 서버가 허용한 방식을 사용한다.

채널을 암호화하더라도 서버가 익명을 허용하면 사용자 확인은 이루어지지 않는다.

채널의 애플리케이션 인증서와 세션의 사용자 인증 구분