보안과 사용자 구성
이 페이지는 보안 엔드포인트만 광고하고 사용자 이름과 암호를 요구하는 서버를 시뮬레이터로 구성합니다. 이어서 SDK 응용 프로그램에서 같은 보안을 설정하는 옵션을 정리합니다. 개념은 보안에서 설명합니다.
시뮬레이터 서버의 보안 설정
섹션 제목: “시뮬레이터 서버의 보안 설정”구성(server) |
GUI | 효과 |
|---|---|---|
allow_none |
Offer SecurityPolicy None | None 엔드포인트(보안 수준 0)를 광고합니다. |
secure |
Offer signed and encrypted policies | 세 정책의 Sign(20), SignAndEncrypt(30) 엔드포인트를 광고합니다. |
allow_anonymous |
Allow anonymous users | 익명 토큰을 광고합니다. |
user_name + server_start의 password |
User name, Password | 보안 엔드포인트에 사용자 이름 토큰을 광고합니다. None 엔드포인트에는 광고하지 않습니다. |
certificate, private_key |
프로젝트 파일 | 서버 인증서와 개인 키. 비우면 localhost, 수신 IP 주소, advertised_host용 자체 서명 인증서를 메모리에서 만듭니다. |
trust |
프로젝트 파일 | 신뢰할 클라이언트 인증서 목록. 같은 시뮬레이터의 클라이언트 인증서는 자동으로 신뢰합니다. |
서버는 계정을 하나만 받습니다. 암호는 구성에 저장하지 않고 서버를 시작할 때마다 넘깁니다. 같은 클라이언트가 사용자 인증에 5번 연속 실패하면 10분 동안 잠기고, 서버를 다시 시작하면 풀립니다.
1. 보안 전용 서버 시작
섹션 제목: “1. 보안 전용 서버 시작”PKI와 신뢰 설정에서 만든 인증서를 씁니다. 첫 번째 터미널에서 $PKI 폴더로 이동해 헤드리스 시뮬레이터를 실행합니다.
cd "$PKI""$OPCUA_APPS/bin/pdcomm-opcua-headless"None 엔드포인트와 익명 사용자를 끄고, 인증서와 신뢰할 클라이언트 인증서를 지정합니다.
{"action":"configure","config":{"server":{"address":"127.0.0.1:4841","allow_none":false,"allow_anonymous":false,"certificate":"server.cert.pem","private_key":"server.key.pem","trust":["client.der"]}}}암호를 넘겨 서버를 시작합니다. 사용자 이름은 기본값 operator입니다.
{"action":"server_start","password":"Lab-password-1"}{"ok":true,"result":{"audit":[],"endpoint":"opc.tcp://localhost:4841/pdcomm/simulator","error":null,"running":true,"secure":true,"sessions":0}}2. 클라이언트 구성과 엔드포인트 확인
섹션 제목: “2. 클라이언트 구성과 엔드포인트 확인”두 번째 터미널에서도 $PKI 폴더에서 시뮬레이터를 하나 더 실행하고 클라이언트를 구성합니다.
cd "$PKI""$OPCUA_APPS/bin/pdcomm-opcua-headless"{"action":"configure","config":{"client":{"url":"opc.tcp://localhost:4841/pdcomm/simulator","policy":"Aes256_Sha256_RsaPss","mode":"SignAndEncrypt","identity":"username","certificate":"client.cert.pem","private_key":"client.key.pem","trust":["server.der"]}}}{"action":"discover"}{"ok":true,"result":{"endpoints":[{"application_uri":"urn:pdcomm:opcua:server","has_certificate":true,"level":20,"mode":"Sign","policy":"Basic256Sha256","tokens":["username"],"url":"opc.tcp://localhost:4841/pdcomm/simulator"},{"application_uri":"urn:pdcomm:opcua:server","has_certificate":true,"level":30,"mode":"SignAndEncrypt","policy":"Basic256Sha256","tokens":["username"],"url":"opc.tcp://localhost:4841/pdcomm/simulator"},{"application_uri":"urn:pdcomm:opcua:server","has_certificate":true,"level":20,"mode":"Sign","policy":"Aes128_Sha256_RsaOaep","tokens":["username"],"url":"opc.tcp://localhost:4841/pdcomm/simulator"},{"application_uri":"urn:pdcomm:opcua:server","has_certificate":true,"level":30,"mode":"SignAndEncrypt","policy":"Aes128_Sha256_RsaOaep","tokens":["username"],"url":"opc.tcp://localhost:4841/pdcomm/simulator"},{"application_uri":"urn:pdcomm:opcua:server","has_certificate":true,"level":20,"mode":"Sign","policy":"Aes256_Sha256_RsaPss","tokens":["username"],"url":"opc.tcp://localhost:4841/pdcomm/simulator"},{"application_uri":"urn:pdcomm:opcua:server","has_certificate":true,"level":30,"mode":"SignAndEncrypt","policy":"Aes256_Sha256_RsaPss","tokens":["username"],"url":"opc.tcp://localhost:4841/pdcomm/simulator"}],"url":"opc.tcp://localhost:4841/pdcomm/simulator"}}None 엔드포인트가 없고 모든 엔드포인트가 username 토큰만 받습니다.
3. 사용자로 접속
섹션 제목: “3. 사용자로 접속”틀린 암호는 거부됩니다.
{"action":"connect","password":"wrong-password"}{"error":"OPC UA status BadUserAccessDenied (0x801F0000)","ok":false}올바른 암호로 접속합니다.
{"action":"connect","password":"Lab-password-1"}{"ok":true,"result":{"connected":true,"identity":"username","items":[],"mode":"SignAndEncrypt","pending_cancelled":0,"policy":"Aes256_Sha256_RsaPss","session":"ns=1;s=pdcomm.diagnostics/session/f94df08c9e0d18293afc3eaa6b742393","subscription":null,"url":"opc.tcp://localhost:4841/pdcomm/simulator"}}인증된 사용자는 Simulator.Protected를 읽고 쓸 수 있습니다.
{"action":"read","nodes":["ns=2;s=Simulator.Protected"]}{"ok":true,"result":{"values":[{"good":true,"node":"ns=2;s=Simulator.Protected","server_time":1791998271248,"source_time":1791998270971,"status":"Good (0x00000000)","type":"Int32","value":0}]}}4. 거부되는 경우
섹션 제목: “4. 거부되는 경우”연결을 끊은 뒤 익명으로 바꿔 접속하면, 클라이언트가 서버의 엔드포인트에 익명 토큰이 없다는 것을 알고 요청하지 않습니다.
{"action":"disconnect"}{"action":"configure","config":{"client":{"url":"opc.tcp://localhost:4841/pdcomm/simulator","policy":"Aes256_Sha256_RsaPss","mode":"SignAndEncrypt","identity":"anonymous","certificate":"client.cert.pem","private_key":"client.key.pem","trust":["server.der"]}}}{"action":"connect"}{"error":"OPC UA protocol: anonymous identity not supported","ok":false}None 정책을 요청하면 서버가 광고하지 않으므로 접속하지 않습니다.
{"action":"configure","config":{"client":{"url":"opc.tcp://localhost:4841/pdcomm/simulator","policy":"None","mode":"None"}}}{"action":"connect"}{"error":"The server does not offer the selected security policy and mode","ok":false}configure에서 넘기지 않은 필드는 기본값으로 돌아갑니다. 위 구성은 certificate와 trust를 넘기지 않았으므로, 이 상태에서 보안 정책만 바꿔 접속하면 서버 인증서를 신뢰하지 않아 OPC UA security CertificateUntrusted가 납니다. 구성을 바꿀 때는 state로 받은 현재 구성을 고쳐 넘깁니다.
서버 쪽 기록은 server_status의 audit에 남습니다. 거부한 인증은 {"action":"user authentication rejected","channel":3,"status":"BadUserAccessDenied (0x801F0000)"}처럼 보입니다. 정리하려면 두 터미널에 {"action":"shutdown"}을 입력합니다.
GUI에서 같은 구성 쓰기
섹션 제목: “GUI에서 같은 구성 쓰기”GUI 화면에는 인증서 파일과 신뢰 목록 항목이 없습니다. 헤드리스에서 구성한 뒤 project_export의 결과를 JSON 파일로 저장하고 GUI의 Project > **Open…**으로 엽니다. 프로젝트 파일에는 파일 경로만 들어갑니다. GUI의 작업 폴더는 실행 방법에 따라 달라지므로 인증서와 개인 키는 절대 경로로 씁니다. 암호는 GUI의 Password 칸에 직접 입력합니다.
SDK의 보안 옵션
섹션 제목: “SDK의 보안 옵션”클라이언트(pdcomm_opcua_client_options, .NET ClientOptions)
| 필드 | 설명 |
|---|---|
policy, mode |
요청할 정책과 모드. 서버가 같은 조합을 광고해야 하며 대체하지 않습니다. |
flags |
PDCOMM_OPCUA_ALLOW_NONE(None 허용), PDCOMM_OPCUA_USER_SECRET_HEADER_POLICY_ONLY(64바이트 초과 암호의 EncryptedSecret에서 알고리즘 URI 생략) |
application_uri |
클라이언트 인증서의 URI와 같아야 합니다(기본 urn:pdcomm:opcua:client). |
certificate_der, private_key_pem |
클라이언트 신원(각 64 KiB 이하). 연결 직후 호출자의 키를 지웁니다. |
trusted_server_der |
신뢰할 서버 인증서 하나 |
timeout_ms |
네트워크 교환과 요청마다의 제한 시간(1~300000 ms, 기본 10000) |
사용자 이름으로 세션을 활성화하려면 pdcomm_opcua_client_activate_user_name을 부릅니다. 사용자 이름은 1~1024바이트, 암호는 16 KiB 이하입니다. 보안 정책 None 채널에서는 실패합니다. 암호 버퍼는 호출 뒤 직접 지웁니다. Qt와 MFC 작업자는 구성의 anonymous가 거짓이면 사용자 이름으로 활성화합니다.
서버(pdcomm_opcua_server_options, .NET ServerOptions)
| 필드 | 설명 |
|---|---|
flags |
PDCOMM_OPCUA_ALLOW_NONE이면 None 엔드포인트를 추가합니다. 기본은 보안 엔드포인트만 광고합니다. |
endpoint |
클라이언트에 광고할 endpoint URL |
application_uri |
서버 인증서의 URI와 같아야 합니다(기본 urn:pdcomm:opcua:server). |
certificate_der, private_key_pem |
서버 신원 |
trusted_client_der |
신뢰할 클라이언트 인증서 하나 |
max_connections, max_sessions |
동시 보안 채널(기본 33)과 세션(기본 32) |
SDK 메모리 서버는 익명 사용자 토큰만 받습니다. 원격 클라이언트가 읽고 쓸 변수는 PDCOMM_OPCUA_VARIABLE_PUBLIC 플래그로 추가합니다. 이 플래그가 없는 변수는 익명 세션에 BadUserAccessDenied를 돌려주며, 서버 응용 프로그램이 pdcomm_opcua_server_set_value와 pdcomm_opcua_server_read_value로만 다룹니다.