벤치에서는 태그 browse가 잘 된다. client를 None에서 Basic256Sha256으로 바꾸는 순간 첫 Read도 못 해보고 secure channel이 끊긴다. 선로에는 이상이 없다. ping도 되고 포트도 열려 있고 서버도 살아 있다. OPC UA 시운전에서 내가 제일 자주 만나는 실패가 바로 이거고, 원인은 거의 항상 셋 중 하나다. 신뢰 관계, 인증서 이름, 아니면 client가 알아서 골라버린 endpoint.
보안은 통신 다 짜고 나서 위에 얹는 IT 항목이 아니다. OPC UA 보안 모델(스펙 Part 2)에서 secure channel은 태그, 알람, 트렌드, write 전부의 아래에 깔린다. 이 채널이 안 서거나 갱신하다 자꾸 끊기면, 주소 공간이 아무리 깔끔해도 그 위 데이터는 믿을 수 없다.
endpoint를 client 자동 선택에 맡기지 마라
대부분의 서버는 GetEndpoints로 여러 endpoint를 낸다. URL, 보안 모드(None / Sign / SignAndEncrypt), 보안 정책이 다 다르다. 기본값으로 두면 많은 드라이버가 처음 쓸 수 있는 걸 잡는데, 그 "쓸 수 있는" 게 대개 제일 약한 쪽이다. client가 None을 알아서 골라 놓고 아무도 확인 안 해서 운영에서 None으로 돌던 시스템을 여러 번 봤다.
endpoint를 명시적으로 고정하고, 뭘 고정했는지 적어 둔다. 실제로 발목 잡는 건 이런 것들이다.
- 보안 정책.
Basic256Sha256을 하한으로 잡는다.Basic128Rsa15와 그냥Basic256은 SHA-1에 기대기 때문에 현재 프로파일(OPC UA Part 7)에서 폐기·제외됐다. 서버가 아직 이걸 내주면 선택지가 아니라 경고 신호다. 양쪽이 다 되면Aes128Sha256RsaOaep,Aes256Sha256RsaPss가 더 새로운 선택지다. - 보안 모드.
Sign은 인증과 무결성,SignAndEncrypt는 여기에 기밀성까지 준다. 의도를 갖고 하나를 고른다. "문제 생기면 쓰려고"Noneendpoint를 켜둔 채 넘기지 마라. 누군가 조용히 그리로 되돌아간다. - User token. Anonymous, 계정/비밀번호, 인증서. Anonymous로 browse는 되는데 다른 identity에서 write가 막힐 수 있으니, 운영에서 실제로 돌 identity로 테스트한다.
고른 endpoint URL과 정책을 프로젝트 노트에 남긴다. 안 남기면 다음 엔지니어가 불안정한 연결을 "고친답시고" 약한 endpoint로 내려버리고 아무한테도 말 안 한다.
신뢰는 양방향이고, 여기서 자주 걸린다
OPC UA 인증서 신뢰는 양방향이다. client가 server 인증서를 trust해야 하고, server도 client 인증서를 trust해야 한다. 대부분의 제품은 처음 본 인증서를 rejected 폴더에 넣고, 옮겨줄 때까지 연결을 거부한다. 그래서 정석 순서는 이렇다.
- client 애플리케이션 인스턴스 인증서를 설치하거나 생성한다.
- 일단 한 번 붙여본다. 실패하지만, 이제 server가 그 인증서를 보고 rejected에 담아둔다.
- server에서 그 client 인증서를 rejected에서 trusted로 옮긴다.
- server 인증서를 받아 client의 trusted 저장소에 넣는다.
- 제품이 요구하면 OPC UA service를 reload한다(요구하는 제품이 많다).
- 다시 붙여서, 살아 있는 세션이 fallback이 아니라 의도한 endpoint·정책을 쓰는지 확인한다.
폴더 이름은 벤더마다 다르지만 흐름은 다 같다. secure 연결이 안 서면 scan rate나 tag address를 건드리기 전에 양쪽 trust store를 먼저 본다. 이중화 쌍에서는 이게 그 유명한 "한쪽 서버만 정상" 버그다. server A에는 client 인증서를 trust하고 server B는 깜빡한 것이다.
노드가 몇 개를 넘어가면 이 수작업은 감당이 안 된다. Global Discovery Server와 push/pull 인증서 관리(Part 12)가 바로 그래서 있다. 노드마다 폴더를 만지는 대신 신뢰 목록을 중앙에서 관리한다. 서버 두 대짜리 현장에서는 과하지만, 엣지 장비 쉰 대짜리 플랜트에서는 교체가 반나절이냐 일주일이냐를 가른다.
인증서 이름은 접속하는 URL과 맞아야 한다
OPC UA 애플리케이션 인스턴스 인증서는 일반 TLS 인증서가 아니다. 인증서 SubjectAltName의 URI 필드에 든 ApplicationUri가 애플리케이션이 알리는 URI와 맞아야 하고, 접속하는 URL의 호스트명이 인증서 subject나 SAN에 (RFC 5280 이름 매칭 기준) 포함돼야 한다. 둘 중 하나만 어긋나도, 장비가 ping이 돼도 채널은 거부된다.
현장 단골 버전은 이렇다. 개발 PC 호스트명으로 만든 인증서를 그대로 가져왔는데, 운영은 IP나 다른 DNS alias로 붙는다. 이제 SAN이 endpoint를 못 덮으니 host-name 거부가 난다. 현장 떠나기 전에 확인한다.
- client가 쓰는 endpoint 호스트명이 server 인증서 subject/SAN에 들어 있는가.
- 테스트한 한 서버만이 아니라 양쪽 SCADA 서버에서 DNS가 같은 이름으로 해석되는가.
- 서버 이름을 바꿨다면 그 뒤에 인증서를 다시 만들었는가(rename은 옛 인증서를 갱신하지 않는다).
- NAT나 포트 포워딩, jump network가 endpoint를 인증서가 못 덮는 형태로 바꾸지 않는가.
ping은 도달성을 증명한다. 보안 스택이 합의했는지는 아무것도 증명하지 않는다.
인증서는 만료되고, 그걸 아무도 안 맡는다
기본 유효기간은 보통 12년이다. 교체를 아무도 안 맡으면 첫 알림은 인증서가 만료된 날 아침의 생산 중단이다. 서버와 client 만료일이 가까우면 양쪽이 동시에 죽는다. 목록을 만들어라. server·client 인증서마다 만료일과 붙어 있는 노드를 적는다. 만료 3060일 전에 정비 알림이 뜨게 한다. 이전 인증서와 trust store 상태를 rollback용으로 남기고, 교체는 필요해지기 전에 이중화 쌍에서 미리 테스트한다. 함정이 primary는 멀쩡한데 standby의 신뢰를 깨는 거라서 그렇다.
인증서를 바꾼 뒤에는 짧은 회귀 테스트를 돈다. browse, read, 허용된 write, 알람 갱신, 히스토리언 값 저장까지. 검증·규제 대상 설비면 인증서 교체도 다른 기준선 변경처럼 변경 관리 패키지에 넣는다. 인증서는 떠도는 파일이 아니라 통신 기준선의 일부다.
상태 코드 읽기
secure-channel 오류는 OPC UA 상태 코드(Part 4)로 돌아오고, 문구가 짧다. 각각이 현장에서 보통 뜻하는 것.
Bad_SecurityChecksFailed— 포괄 코드. 인증서 미신뢰, 이름 불일치, 만료, 아니면 한쪽이 정책을 지원 안 함. 여기서 시작한다.Bad_CertificateTimeInvalid— 시간이 틀렸거나 인증서 유효 시작 전. 인증서 탓하기 전에 양쪽 NTP부터 본다.Bad_CertificateHostNameInvalid— endpoint 호스트명이 인증서 SAN에 없다.Bad_CertificateUriInvalid— ApplicationUri와 인증서 SAN URI가 안 맞는다. 다시 import가 아니라 맞는 URI로 인증서를 다시 만드는 게 해법이다.Bad_UserAccessDenied— 채널은 섰다. 그 identity가 browse나 write 권한이 없을 뿐이다. 인증서 문제가 아니라 권한 문제고, 오진하기 쉽다.
패킷 캡처는 TCP 소켓이 열리고 OpenSecureChannel 교환이 일어났는지는 확인해준다. 하지만 서버가 왜 인증서를 거부했는지는 못 풀어준다. 그건 서버의 보안 로그나 진단 화면이 훨씬 빨리, 훨씬 자세히 알려준다.
현장 떠나기 전에
- 남은
Noneendpoint는 전부 비활성화하거나, 하나 남겨야 하면 이유를 문서화한다. - 살아 있는 세션이 auto-select fallback이 아니라 의도한 모드·정책인지 확인한다.
- 신뢰를 양방향으로, 모든 이중화 노드에서 확인한다.
- 인증서 만료일을 전부 정비 시스템에 넣는다.
- 운영에 투입될 모든 서버·게이트웨이·standby에서 붙어본다. 재부팅하고 다시 붙여 DNS 함정을 잡는다.
- client가 운영에서 write할 거라면 허용된 write를 한 번 돌린다.
내가 지키는 기준. 보안 없는 테스트 endpoint로 OPC UA 통신을 사인오프하지 마라. 운영이 실제로 돌 endpoint, 인증서 체인, 신뢰 상태, 사용자 identity로 증명해라. 운전자가 걸고 있는 건 바로 그 연결이다.