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()

將一個或多個 IPv4/IPv6 地址傳遞給安全模組進行驗證,驗證基於 @optname,這將導致繫結或連線服務,如下面的許可權檢查表所示。成功返回 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 分配給 @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 中包含的值。

@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 中的值。

@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 不受支援,因為 RFC 3554 - sctp/ipsec 支援尚未在使用者空間實現(racoon(8) 或 ipsec_pluto(8)),儘管核心支援 SCTP/IPSEC。