SCTP

SCTP LSM 支持

安全钩子

为了支持安全模块,实现了三个 SCTP 特定的钩子

security_sctp_assoc_request()
security_sctp_bind_connect()
security_sctp_sk_clone()
security_sctp_assoc_established()

这些钩子的用法在下面进行描述,SELinux 的实现则在 SCTP SELinux 支持 章节中描述。

security_sctp_assoc_request()

将关联的 INIT 数据包的 @asoc@chunk->skb 传递给安全模块。成功返回 0,失败返回错误。

@asoc - pointer to sctp association structure.
@skb - pointer to skbuff of association packet.

security_sctp_bind_connect()

根据 @optname 将一个或多个 IPv4/IPv6 地址传递给安全模块进行验证,这将导致绑定或连接服务,如下面的权限检查表所示。成功返回 0,失败返回错误。

  @sk      - Pointer to sock structure.
  @optname - Name of the option to validate.
  @address - One or more ipv4 / ipv6 addresses.
  @addrlen - The total length of address(s). This is calculated on each
             ipv4 or ipv6 address using sizeof(struct sockaddr_in) or
             sizeof(struct sockaddr_in6).

------------------------------------------------------------------
|                     BIND Type Checks                           |
|       @optname             |         @address contains         |
|----------------------------|-----------------------------------|
| SCTP_SOCKOPT_BINDX_ADD     | One or more ipv4 / ipv6 addresses |
| SCTP_PRIMARY_ADDR          | Single ipv4 or ipv6 address       |
| SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address       |
------------------------------------------------------------------

------------------------------------------------------------------
|                   CONNECT Type Checks                          |
|       @optname             |         @address contains         |
|----------------------------|-----------------------------------|
| SCTP_SOCKOPT_CONNECTX      | One or more ipv4 / ipv6 addresses |
| SCTP_PARAM_ADD_IP          | One or more ipv4 / ipv6 addresses |
| SCTP_SENDMSG_CONNECT       | Single ipv4 or ipv6 address       |
| SCTP_PARAM_SET_PRIMARY     | Single ipv4 or ipv6 address       |
------------------------------------------------------------------

以下是 @optname 条目的摘要

SCTP_SOCKOPT_BINDX_ADD - Allows additional bind addresses to be
                         associated after (optionally) calling
                         bind(3).
                         sctp_bindx(3) adds a set of bind
                         addresses on a socket.

SCTP_SOCKOPT_CONNECTX - Allows the allocation of multiple
                        addresses for reaching a peer
                        (multi-homed).
                        sctp_connectx(3) initiates a connection
                        on an SCTP socket using multiple
                        destination addresses.

SCTP_SENDMSG_CONNECT  - Initiate a connection that is generated by a
                        sendmsg(2) or sctp_sendmsg(3) on a new association.

SCTP_PRIMARY_ADDR     - Set local primary address.

SCTP_SET_PEER_PRIMARY_ADDR - Request peer sets address as
                             association primary.

SCTP_PARAM_ADD_IP          - These are used when Dynamic Address
SCTP_PARAM_SET_PRIMARY     - Reconfiguration is enabled as explained below.

为了支持动态地址重配置,必须在两个端点上启用以下参数(或使用适当的 **setsockopt**(2))

/proc/sys/net/sctp/addip_enable
/proc/sys/net/sctp/addip_noauth_enable

然后,当存在相应的 @optname 时,以下 *\_PARAM\_* 会在 ASCONF 数据块中发送给对等方

      @optname                      ASCONF Parameter
     ----------                    ------------------
SCTP_SOCKOPT_BINDX_ADD     ->   SCTP_PARAM_ADD_IP
SCTP_SET_PEER_PRIMARY_ADDR ->   SCTP_PARAM_SET_PRIMARY

security_sctp_sk_clone()

每当通过 **accept**(2) 创建新套接字(即 TCP 样式套接字)或当套接字被“剥离”时(例如,用户空间调用 **sctp_peeloff**(3))调用。

@asoc - pointer to current sctp association structure.
@sk - pointer to current sock structure.
@newsk - pointer to new sock structure.

security_sctp_assoc_established()

当收到 COOKIE ACK 时调用,对等 secid 将保存到客户端的 @asoc->peer_secid

@asoc - pointer to sctp association structure.
@skb - pointer to skbuff of the COOKIE ACK packet.

用于关联建立的安全钩子

下图显示了在建立关联时 security_sctp_bind_connect()security_sctp_assoc_request()security_sctp_assoc_established() 的用法。

     SCTP endpoint "A"                                SCTP endpoint "Z"
     =================                                =================
   sctp_sf_do_prm_asoc()
Association setup can be initiated
by a connect(2), sctp_connectx(3),
sendmsg(2) or sctp_sendmsg(3).
These will result in a call to
security_sctp_bind_connect() to
initiate an association to
SCTP peer endpoint "Z".
        INIT --------------------------------------------->
                                                  sctp_sf_do_5_1B_init()
                                                Respond to an INIT chunk.
                                            SCTP peer endpoint "A" is asking
                                            for a temporary association.
                                            Call security_sctp_assoc_request()
                                            to set the peer label if first
                                            association.
                                            If not first association, check
                                            whether allowed, IF so send:
         <----------------------------------------------- INIT ACK
         |                                  ELSE audit event and silently
         |                                       discard the packet.
         |
   COOKIE ECHO ------------------------------------------>
                                                 sctp_sf_do_5_1D_ce()
                                            Respond to an COOKIE ECHO chunk.
                                            Confirm the cookie and create a
                                            permanent association.
                                            Call security_sctp_assoc_request() to
                                            do the same as for INIT chunk Response.
         <------------------------------------------- COOKIE ACK
         |                                               |
   sctp_sf_do_5_1E_ca                                    |
Call security_sctp_assoc_established()                   |
to set the peer label.                                   |
         |                                               |
         |                               If SCTP_SOCKET_TCP or peeled off
         |                               socket security_sctp_sk_clone() is
         |                               called to clone the new socket.
         |                                               |
     ESTABLISHED                                    ESTABLISHED
         |                                               |
   ------------------------------------------------------------------
   |                     Association Established                    |
   ------------------------------------------------------------------

SCTP SELinux 支持

安全钩子

上面的 SCTP LSM 支持 章节描述了以下 SCTP 安全钩子,下面扩展了 SELinux 的具体细节

security_sctp_assoc_request()
security_sctp_bind_connect()
security_sctp_sk_clone()
security_sctp_assoc_established()

security_sctp_assoc_request()

将关联的 INIT 数据包的 @asoc@chunk->skb 传递给安全模块。成功返回 0,失败返回错误。

@asoc - pointer to sctp association structure.
@skb - pointer to skbuff of association packet.
安全模块执行以下操作

如果这是 @asoc->base.sk 上的第一个关联,则将对等 sid 设置为 @skb 中的 sid。这将确保只有一个对等 sid 分配给可能支持多个关联的 @asoc->base.sk

否则,验证 @asoc->base.sk peer_sid@skb peer sid,以确定是否应允许或拒绝关联。

将 SCTP @asoc sid 设置为套接字的 sid(来自 asoc->base.sk),MLS 部分取自 @skb peer sid。这将用于 SCTP TCP 样式套接字和剥离的连接,因为它们会导致生成新套接字。

如果配置了 IP 安全选项(CIPSO/CALIPSO),则在套接字上设置 IP 选项。

security_sctp_bind_connect()

根据 @optname 检查 IPv4/IPv6 地址所需的权限,如下所示

------------------------------------------------------------------
|                   BIND Permission Checks                       |
|       @optname             |         @address contains         |
|----------------------------|-----------------------------------|
| SCTP_SOCKOPT_BINDX_ADD     | One or more ipv4 / ipv6 addresses |
| SCTP_PRIMARY_ADDR          | Single ipv4 or ipv6 address       |
| SCTP_SET_PEER_PRIMARY_ADDR | Single ipv4 or ipv6 address       |
------------------------------------------------------------------

------------------------------------------------------------------
|                 CONNECT Permission Checks                      |
|       @optname             |         @address contains         |
|----------------------------|-----------------------------------|
| SCTP_SOCKOPT_CONNECTX      | One or more ipv4 / ipv6 addresses |
| SCTP_PARAM_ADD_IP          | One or more ipv4 / ipv6 addresses |
| SCTP_SENDMSG_CONNECT       | Single ipv4 or ipv6 address       |
| SCTP_PARAM_SET_PRIMARY     | Single ipv4 or ipv6 address       |
------------------------------------------------------------------

SCTP LSM 支持 给出了 @optname 条目的摘要,并且还描述了启用动态地址重配置时的 ASCONF 数据块处理。

security_sctp_sk_clone()

每当通过 **accept**(2) 创建新套接字(即 TCP 样式套接字)或当套接字被“剥离”时(例如,用户空间调用 **sctp_peeloff**(3))调用。security_sctp_sk_clone() 将新套接字的 sid 和对等 sid 分别设置为 @asoc sid@asoc peer sid 中包含的 sid。

@asoc - pointer to current sctp association structure.
@sk - pointer to current sock structure.
@newsk - pointer to new sock structure.

security_sctp_assoc_established()

当收到 COOKIE ACK 时调用,它将连接的对等 sid 设置为 @skb 中的 sid

@asoc - pointer to sctp association structure.
@skb - pointer to skbuff of the COOKIE ACK packet.

策略声明

以下类和权限可用于在内核中支持 SCTP

class sctp_socket inherits socket { node_bind }

只要启用以下策略功能

policycap extended_socket_class;

SELinux SCTP 支持添加了用于连接特定端口类型的 name_connect 权限和下面部分中解释的 association 权限。

如果用户空间工具已更新,SCTP 将支持 portcon 语句,如下例所示

portcon sctp 1024-1036 system_u:object_r:sctp_ports_t:s0

SCTP 对等标记

一个 SCTP 套接字只分配一个对等标签。这将在建立第一个关联时分配。此套接字上的任何进一步关联都将将其数据包对等标签与套接字对等标签进行比较,并且只有当它们不同时,才会验证 association 权限。这是通过检查套接字对等 sid 与接收到的数据包的对等 sid 来验证的,以确定是否应允许或拒绝关联。

注意
  1. 如果未启用对等标记,则对等上下文将始终为 SECINITSID_UNLABELED(参考策略中的 unlabeled_t)。

  2. 由于 SCTP 可以在单个套接字上支持每个端点的多个传输地址(多宿主),因此可以配置策略和 NetLabel 为每个传输地址提供不同的对等标签。由于套接字对等标签由第一个关联的传输地址确定,因此建议所有对等标签保持一致。

  3. 用户空间可以使用 **getpeercon**(3) 来检索套接字的对等上下文。

  4. 虽然不是 SCTP 特定的,但请注意,当使用 NetLabel 时,如果将标签分配给特定的接口,并且该接口“关闭”,则 NetLabel 服务将删除该条目。因此,请确保网络启动脚本调用 **netlabelctl**(8) 来设置所需的标签(有关详细信息,请参见 **netlabel-config**(8) 帮助脚本)。

  5. NetLabel SCTP 对等标记规则适用,如以下标记为“netlabel”的帖子中所讨论的:https://www.paul-moore.com/blog/t

  6. CIPSO 仅支持 IPv4 寻址:socket(AF_INET, ...) CALIPSO 仅支持 IPv6 寻址:socket(AF_INET6, ...)

    测试 CIPSO/CALIPSO 时请注意以下事项
    1. 如果由于标签无效而无法传递 SCTP 数据包,CIPSO 将发送 ICMP 数据包。

    2. CALIPSO 不发送 ICMP 数据包,只是静默地丢弃它。

  7. IPSEC 不受支持,因为用户空间(**racoon**(8) 或 **ipsec_pluto**(8))尚未实现 RFC 3554 - sctp/ipsec 支持,尽管内核支持 SCTP/IPSEC。