Post

[ROS2 심화] Day 2: SROS2 - DDS 보안과 접근 제어

[ROS2 심화] Day 2: SROS2 - DDS 보안과 접근 제어

서론: 로봇 통신에도 보안이 필요하다

ROS1은 보안이 없었다. 같은 네트워크에 있으면 누구나 모든 토픽을 읽고 쓸 수 있었다. 자율주행차나 산업용 로봇에 이 구조를 그대로 쓰면 원격 조작 공격에 무방비다. SROS2는 DDS Security 표준 위에 구축된 ROS2 보안 레이어다.

1. SROS2가 제공하는 것

1
2
3
4
5
6
7
8
9
10
11
인증 (Authentication)
  - 노드마다 X.509 인증서
  - 서로를 검증한 노드만 통신 허용

암호화 (Encryption)
  - 토픽 데이터를 TLS로 암호화
  - 네트워크 스니핑 방어

접근 제어 (Access Control)
  - 어떤 노드가 어떤 토픽을 publish/subscribe 할 수 있는지 정책으로 관리
  - 카메라 노드가 /cmd_vel을 publish하는 것을 정책으로 차단

2. 키스토어 생성

1
2
3
4
5
6
7
8
9
10
# 키스토어 초기화
ros2 security create_keystore ~/sros2_keystore

# 구조
~/sros2_keystore/
  enclaves/           ← 노드별 인증서 디렉터리
  public/
    ca.cert.pem       ← 루트 CA 인증서
  private/
    ca.key.pem        ← 루트 CA 키 (비공개)

3. 노드별 인증서 생성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# talker 노드용 인증서
ros2 security create_enclave \
  ~/sros2_keystore /talker_listener/talker

# listener 노드용 인증서
ros2 security create_enclave \
  ~/sros2_keystore /talker_listener/listener

# 생성 결과
~/sros2_keystore/enclaves/talker_listener/talker/
  cert.pem            ← 노드 인증서
  key.pem             ← 노드 개인키
  identity_ca.cert.pem
  permissions_ca.cert.pem
  permissions.xml     ← 접근 제어 정책
  permissions.p7s     ← 서명된 정책
  governance.xml      ← 도메인 보안 정책
  governance.p7s

4. 접근 제어 정책 (permissions.xml)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!-- enclaves/talker_listener/talker/permissions.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<dds xmlns:xsi="...">
  <permissions>
    <grant name="talker_permissions">
      <subject_name>CN=talker</subject_name>
      <validity>
        <not_before>2026-01-01T00:00:00</not_before>
        <not_after>2027-01-01T00:00:00</not_after>
      </validity>
      <allow_rule>
        <!-- talker는 /chatter에만 publish 가능 -->
        <domains><id>0</id></domains>
        <publish>
          <topics><topic>rt/chatter</topic></topics>
        </publish>
        <!-- subscribe는 불가 -->
      </allow_rule>
      <default>DENY</default>
    </grant>
  </permissions>
</dds>

<default>DENY</default>가 핵심이다. 명시적으로 허용하지 않은 토픽은 모두 차단된다.

5. 보안 활성화 환경변수

1
2
3
4
5
6
7
8
9
10
11
export ROS_SECURITY_KEYSTORE=~/sros2_keystore
export ROS_SECURITY_ENABLE=true
export ROS_SECURITY_STRATEGY=Enforce  # 인증서 없으면 실행 거부

# talker 실행 (인증서 경로를 enclave로 지정)
ros2 run demo_nodes_py talker \
  --ros-args --enclave /talker_listener/talker

# listener 실행
ros2 run demo_nodes_py listener \
  --ros-args --enclave /talker_listener/listener
1
2
3
4
ROS_SECURITY_STRATEGY 옵션:
  Enforce   - 인증서 없으면 노드 실행 실패 (프로덕션 권장)
  Permissive - 인증서 없으면 보안 없이 실행 (개발용)
  NodeIsolation - 보안 노드끼리만 통신

6. 거버넌스 정책 (governance.xml)

도메인 전체의 보안 수준을 설정한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- governance.xml -->
<dds>
  <domain_access_rules>
    <domain_rule>
      <domains><id>0</id></domains>

      <!-- 발견 정보 보호 -->
      <enable_discovery_protection>true</enable_discovery_protection>
      <!-- 리우 정보 암호화 -->
      <enable_liveliness_protection>true</enable_liveliness_protection>
      <!-- RTF 메타데이터 보호 -->
      <enable_read_access_control>true</enable_read_access_control>
      <enable_write_access_control>true</enable_write_access_control>

      <topic_access_rules>
        <topic_rule>
          <topic_expression>*</topic_expression>
          <!-- 페이로드 암호화 -->
          <encryption_algorithm>AES-256-GCM</encryption_algorithm>
        </topic_rule>
      </topic_access_rules>
    </domain_rule>
  </domain_access_rules>
</dds>

7. 런치 파일에서 보안 적용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    security_env = {
        'ROS_SECURITY_KEYSTORE': '/home/user/sros2_keystore',
        'ROS_SECURITY_ENABLE': 'true',
        'ROS_SECURITY_STRATEGY': 'Enforce',
    }

    return LaunchDescription([
        Node(
            package='demo_nodes_py',
            executable='talker',
            ros_arguments=['--enclave', '/talker_listener/talker'],
            additional_env=security_env,
        ),
        Node(
            package='demo_nodes_py',
            executable='listener',
            ros_arguments=['--enclave', '/talker_listener/listener'],
            additional_env=security_env,
        ),
    ])

8. 보안 적용 확인

1
2
3
4
5
6
7
8
# 보안 없는 노드에서 토픽 도청 시도 (차단 확인)
# ROS_SECURITY_ENABLE 없이 실행
ros2 topic echo /chatter
# → 메시지가 보이지 않아야 정상 (암호화됨)

# 키스토어 인증서 만료일 확인
openssl x509 -in ~/sros2_keystore/enclaves/talker_listener/talker/cert.pem \
  -noout -dates

9. Day 2 체크리스트

  1. ros2 security create_keystore로 CA와 키스토어를 생성했다.
  2. 노드마다 create_enclave로 X.509 인증서를 발급했다.
  3. permissions.xml에 허용할 토픽 publish/subscribe를 명시했다.
  4. ROS_SECURITY_STRATEGY=Enforce로 인증서 없는 노드를 차단했다.
  5. governance.xml에서 페이로드 암호화 알고리즘을 설정했다.

다음 글 예고

Day 3에서는 실시간 ROS2를 다룬다. RTOS 환경에서 Executor 선택, 스레드 우선순위 설정, 데드라인 미스 탐지로 결정론적 실행을 달성하는 방법을 정리한다.

This post is licensed under CC BY 4.0 by the author.