【網絡入侵檢測】基于源碼分析Suricata的IP分片重組

【作者主頁】只道當時是尋常

【專欄介紹】Suricata入侵檢測。專注網絡、主機安全,歡迎關注與評論。

目錄

目錄

1.概要

2. 配置信息

2.1 名詞介紹

2.2 defrag 配置

3. 代碼實現

3.1 配置解析

3.1.1 defrag配置

3.1.2 主機系統策略

3.2 分片重組模塊

3.2.1分片追蹤器(DefragTracker )

3.2.2 獲取分片追蹤器(DefragGetTracker)

3.2.3 分片插入(DefragInsertFrag)

3.2.3.1 分片沖突策略

3.2.3.1.1 DEFRAG_POLICY_BSD

3.2.3.1.2 DEFRAG_POLICY_BSD_RIGHT

3.2.3.1.3?DEFRAG_POLICY_LINUX

3.2.3.1.4 DEFRAG_POLICY_WINDOWS

3.2.3.1.5 DEFRAG_POLICY_SOLARIS

3.2.3.2 獲取主機系統策略


1.概要

👋?本文針對網絡入侵檢測中 Suricata 的 IP 分片重組模塊展開源碼分析。IP 分片重組是網絡數據傳輸關鍵,對 NIDS 執行 DPI 至關重要。Suricata 作為開源高性能網絡威脅檢測引擎,通過分析其 IP 分片重組模塊源碼,解析該模塊處理 IP 分片數據、監視重組數據包,并將重組數據傳遞給后續模塊的過程,以確保檢測準確完整。文中主要包含Suricata中分片配置、分片重組以及解決重組沖突信息。

2. 配置信息

2.1 名詞介紹

IP 分片

IP 分片是因不同網絡鏈路 MTU 不同,當 IP 數據包大小超鏈路 MTU 時,將其拆成多個小數據包的機制。

IP 分片流

單個 IP 報文經分片處理后,由其形成的多個分片所構成的傳輸流,被稱為 IP 分片流,其中各分片報文的 IP 包頭 ID 標識保持一致。

分片重組引擎

Suricata 中專門用于對 IP 分片報文實施內部重組的功能模塊。

2.2 defrag 配置

在 Suricata 的配置文件中,defrag 關鍵字包含的配置信息用于配置分片重組引擎。其默認配置信息如下:

defrag:memcap: 32mb# memcap-policy: ignorehash-size: 65536trackers: 65535 # number of defragmented flows to followmax-frags: 65535 # number of fragments to keep (higher than trackers)prealloc: yestimeout: 60# Enable defrag per host settings
#  host-config:
#
#    - dmz:
#        timeout: 30
#        address: [192.168.1.0/24, 127.0.0.0/8, 1.1.1.0/24, 2.2.2.0/24, "1.1.1.1", "2.2.2.2", "::1"]
#
#    - lan:
#        timeout: 45
#        address:
#          - 192.168.0.0/24
#          - 192.168.10.0/24
#          - 172.16.14.0/24
  • memcap:設置分片重組引擎可申請的最大使用內存,這限制了碎片整理過程中內存的使用量。

  • memcap-policy:[drop-packet/pass-packet/reject/ignore(默認)],適用于IPS模式,例如在分片重組時空間申請失敗等因素導致無法重組該分片時,對該分片采取的策略。

  • hash-size:設置哈希表中能存儲的元素的上限。

  • trackers:設置預先申請的分片追蹤器(DefragTracker )的數量,一般和?prealloc?配合使用,prealloc yes,則申請執行數量的DefragTracker 存儲在defragtracker_spare_q結構中,否則不申請。

  • max-frags:設置最大分片數量。

  • prealloc:見 "trackers" 字段解釋。

  • timeout:設置分片重組超時時間,默認 60s。

  • host-config: 針對特定主機單獨設置分片重組策略。

    • timeout:設置分片重組超時時間,默認 60s。

    • address:設置主機IP地址。

3. 代碼實現

3.1 配置解析

3.1.1 defrag配置

DefragInit 函數是Suricata 解析配置文件中?Defrag?配置信息的入口函數,DefragPolicyLoadFromConfig 函數用于解析 defrag.host-config 相關的配置信息,DefragInitConfig 函數用于解析其它配置信息。

3.1.2 主機系統策略

在Suricata中 SCHInfoLoadFromConfig 函數主要用于加載配置文件中?host-os-policy 相關的配置信息。

host-os-policy 的配置格式如下所示,分號前面為操作系統類型,后面列表中包含主機的IP地址,不同的IP地址可使用逗號分割。Suricata依據用戶配置的IP地址區分主機系統類型。

# Host specific policies for defragmentation and TCP stream
# reassembly. The host OS lookup is done using a radix tree, just
# like a routing table so the most specific entry matches.
host-os-policy:windows: [0.0.0.0/0]bsd: []bsd_right: []old_linux: []linux: [10.0.0.0/8, 192.168.1.100, "8762:2352:6241:7245:E000:0000:0000:0000"]old_solaris: []solaris: ["::1"]hpux10: []hpux11: []irix: []macos: []vista: []windows2k3: []

下面sc_hinfo_os_policy_map 結構用于將配置信息中主機類型轉換成宏變量。

/** Enum map for the various OS flavours */
SCEnumCharMap sc_hinfo_os_policy_map[ ] = {{ "none",        OS_POLICY_NONE },{ "bsd",         OS_POLICY_BSD },{ "bsd-right",   OS_POLICY_BSD_RIGHT },{ "old-linux",   OS_POLICY_OLD_LINUX },{ "linux",       OS_POLICY_LINUX },{ "old-solaris", OS_POLICY_OLD_SOLARIS },{ "solaris",     OS_POLICY_SOLARIS },{ "hpux10",      OS_POLICY_HPUX10 },{ "hpux11",      OS_POLICY_HPUX11 },{ "irix",        OS_POLICY_IRIX },{ "macos",       OS_POLICY_MACOS },{ "windows",     OS_POLICY_WINDOWS },{ "vista",       OS_POLICY_VISTA },{ "windows2k3",  OS_POLICY_WINDOWS2K3 },{ NULL,          -1 },
};

3.2 分片重組模塊

Defrag 函數作為分片重組引擎的入口函數,在網絡數據包解碼過程中發揮著關鍵作用。當解碼進入網絡層時,會根據數據包的 IP 版本調用 DecodeIPV4 DecodeIPV6 函數進行處理(有關具體的解碼流程以及這兩個函數的詳細介紹,可查閱 【網絡入侵檢測】基于源碼分析Suricata的解碼模塊)。在調用這兩個解碼函數期間,Defrag 函數可能會被觸發。IPv4 報文觸發的條件是:IP 包頭中的偏移字段值大于零,或者更多分片標志位(MF)被設置為 1。只有滿足這些條件,才會調用 Defrag 函數對分片數據包進行重組操作。IPv6不是本文重點,本文不再關注。

下面是 Suricata 源碼中對于IPv4包頭是否分片判斷:

int DecodeIPV4(ThreadVars *tv, DecodeThreadVars *dtv, Packet *p,const uint8_t *pkt, uint16_t len)
{... .../* If a fragment, pass off for re-assembly. */if (unlikely(IPV4_GET_IPOFFSET(p) > 0 || IPV4_GET_MF(p) == 1)) {Packet *rp = Defrag(tv, dtv, p);if (rp != NULL) {PacketEnqueueNoLock(&tv->decode_pq, rp);}p->flags |= PKT_IS_FRAGMENT;return TM_ECODE_OK;}... ...
}

下面是分片重組模塊四個主要函數:

  • Defrag:分片重組入口函數。

  • DefragGetTracker:獲取分片追蹤器(DefragTracker )。

  • DefragInsertFrag:執行分片重組操作。

  • DefragTrackerRelease:執行 DefragTracker 結構引用計數減一操作,并不是釋放該對象。

下面是分片重組模塊整體設計:

3.2.1分片追蹤器(DefragTracker )

在 Suricata 中 DefragTracker 這個結構體尤為重要,該結構體用于跟蹤和管理 IP 分片重組的過程。它的主要作用是記錄與特定 IP 分片流相關的信息,以便在接收到所有分片后能夠正確地重組原始數據包。下面是該結構體的結構:

/*** A defragmentation tracker.  Used to track fragments that make up a* single packet.*/
typedef struct DefragTracker_ {SCMutex lock; /**< Mutex for locking list operations on* this tracker. */uint16_t vlan_id[VLAN_MAX_LAYERS]; /**< VLAN ID tracker applies to. */uint32_t id; /**< IP ID for this tracker.  32 bits for IPv6, 16* for IPv4. */uint8_t proto; /**< IP protocol for this tracker. */uint8_t policy; /**< Reassembly policy this tracker will use. */uint8_t af; /**< Address family for this tracker, AF_INET or* AF_INET6. */uint8_t seen_last; /**< Has this tracker seen the last fragment? */uint8_t remove; /**< remove */Address src_addr; /**< Source address for this tracker. */Address dst_addr; /**< Destination address for this tracker. */int datalink;           /**< datalink for reassembled packet, set by first fragment */SCTime_t timeout;       /**< When this tracker will timeout. */uint32_t host_timeout;  /**< Host timeout, statically assigned from the yaml *//** use cnt, reference counter */SC_ATOMIC_DECLARE(unsigned int, use_cnt);struct IP_FRAGMENTS fragment_tree;/** hash pointers, protected by hash row mutex/spin */struct DefragTracker_ *hnext;struct DefragTracker_ *hprev;/** list pointers, protected by tracker-queue mutex/spin */struct DefragTracker_ *lnext;struct DefragTracker_ *lprev;
} DefragTracker;

下面我們挑選幾個主要的變量進行解釋:

  • vlan_id:記錄 VLAN ID,用于標識分片所屬的 VLAN 網絡。

  • id:IP 分片的標識符(IP ID),用于區分不同的分片流。

  • proto: IP 協議類型(如 TCP、UDP 等),用于確定分片所屬的協議。

  • policy:分片重組策略,不同的主機系統在遇到重組沖突時遵循的重組策略是不同的。

  • af:地址族,標識是 IPv4 (AF_INET) 還是 IPv6 (AF_INET6)。

  • seen_last:標記是否已經接收到最后一個分片。

  • remove:標記該跟蹤器是否需要被移除。

  • src_addr:記錄分片流的源地址。

  • dst_addr:記錄分片流的目的地址。

  • datalink:數據鏈路層類型,由第一個分片設置。

  • timeout:超時時間,用于確定何時丟棄未完成的分片流。

  • fragment_tree: 用于存儲分片的紅黑樹,按分片偏移量排序。

  • hnext hprev: 哈希表指針,用于在哈希表中鏈接多個跟蹤器。

  • lnext lprev: 鏈表指針,用于在跟蹤器隊列中鏈接多個跟蹤器。

👋?綜上所述,我們能夠明確,每個不同的 IP 分片流都與唯一的 DefragTracker 結構相對應。DefragTracker 結構借助紅黑樹,按照偏移順序對當前 IP 分片流中的各個數據包進行存儲。后續的分片存儲、數據包重組等操作,均依賴這一結構體展開。

3.2.2 獲取分片追蹤器(DefragGetTracker)

在 Defrag 函數對分片包完成統計操作后,會調用 DefragGetTracker 函數,以查找當前分片報文是否存在對應的 DefragTracker 結構。若存在,則返回該 DefragTracker 結構;若不存在,則創建一個新的 DefragTracker 結構,用于存儲該分片包所在分片流的相關信息。具體流程如下圖所示:

3.2.3 分片插入(DefragInsertFrag)

調用 DefragGetTracker 后已經獲取當前分片關聯的 DefragTracker 對象,接著根據當前分片的偏移值,將分片插入到分片隊列中。下面是分片插入操作流程圖:

3.2.3.1 分片沖突策略

分片在重組的過程中可能出現新的分片與舊的分片出現沖突或者覆蓋的現象,如下圖所示(參考自TCP IP協議 卷2 第十章):

通過觀察上圖可以看到分片5與分片1和分片2發生重疊,分片7和分片3發生重疊,分片6與分片4發生重疊。其中分片1、2、3、4先到達目標主機,分片5、6、7后到達主機。

👋?為什么分片在傳輸過程中出現重疊現象?

在正常的網絡通信中,IP分片的“Fragment Offset”字段應確保各分片數據在重組時無重疊。然而,攻擊者可以故意設置多個分片的偏移量和長度,使它們在重組時發生重疊。

例如,攻擊者可能發送兩個分片:

  • 分片A:偏移量為0,長度為100字節

  • 分片B:偏移量為50,長度為100字節

在這種情況下,分片B的前50字節將覆蓋分片A的后50字節,導致數據重疊。

👋?發生分片重疊時應該怎么處理?

不同操作系統和網絡設備在處理重疊分片時的行為可能不同:

  • 某些系統可能保留第一個到達的分片數據,忽略后續重疊部分。

  • 另一些系統可能使用后到達的分片數據覆蓋先前的內容。

  • 還有的系統可能在檢測到重疊時直接丟棄整個數據包。

Suricata 支持多種分片重組策略來適配多種不同的操作系統,而在配置文件中 host-os-policy 配置可指定目標主機系統類型。

3.2.3.1.1 DEFRAG_POLICY_BSD

該策略遵循左側優先法,即優先保留左側偏移較小的分片數據。如果新分片與舊分片完全重合的情況下,優先保留舊分片。如果新分片左側偏移與舊分片左側偏移相等的情況下,優先裁剪新分片數據。

該部分邏輯代碼實現如下所示:

/*** Insert a new IPv4/IPv6 fragment into a tracker.** \todo Allocate packet buffers from a pool.*/
static Packet *
DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
{... ...case DEFRAG_POLICY_BSD:if (frag_offset < prev->offset + prev->data_len) {if (prev->offset <= frag_offset) {  /* We prefer the data from the previous* fragment, so trim off the data in the new* fragment that exists in the previous* fragment. */uint16_t prev_end = prev->offset + prev->data_len;if (prev_end > frag_end) { /* Just skip. *//* TODO: Set overlap flag. */goto done;}ltrim = prev_end - frag_offset;if ((next != NULL) && (frag_end > next->offset)) {next->ltrim = frag_end - next->offset;}goto insert;}/* If the end of this fragment overlaps the start* of the previous fragment, then trim up the* start of previous fragment so this fragment is* used.** See:* DefragBsdSubsequentOverlapsStartOfOriginal.*/if (frag_offset <= prev->offset && frag_end > prev->offset + prev->ltrim) {uint16_t prev_ltrim = frag_end - prev->offset;if (prev_ltrim > prev->ltrim) {prev->ltrim = prev_ltrim;}}if ((next != NULL) && (frag_end > next->offset)) {next->ltrim = frag_end - next->offset;}goto insert;}break;... ...
}
3.2.3.1.2 DEFRAG_POLICY_BSD_RIGHT

該策略遵循右側覆蓋策略,即右邊的分片覆蓋前面的分片數據。

3.2.3.1.3?DEFRAG_POLICY_LINUX

該策略遵循左側優先法,即優先保留左側偏移較小的分片數據。如果新分片與舊分片完全重合的情況下,優先保留新分片。如果新分片左側偏移與舊分片左側偏移相等的情況下,優先裁剪舊分片數據。

該部分邏輯代碼實現如下所示:

/*** Insert a new IPv4/IPv6 fragment into a tracker.** \todo Allocate packet buffers from a pool.*/
static Packet *
DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
{... ...case DEFRAG_POLICY_LINUX:/* Check if new fragment overlaps the end of previous* fragment, if it does, trim the new fragment.** Old: AAAAAAAA AAAAAAAA AAAAAAAA* New:          BBBBBBBB BBBBBBBB BBBBBBBB* Res: AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB*/if (prev->offset + prev->ltrim < frag_offset + ltrim &&prev->offset + prev->data_len > frag_offset + ltrim) {ltrim += prev->offset + prev->data_len - frag_offset;}/* Check if new fragment overlaps the beginning of* previous fragment, if it does, tim the previous* fragment.** Old:          AAAAAAAA AAAAAAAA* New: BBBBBBBB BBBBBBBB BBBBBBBB* Res: BBBBBBBB BBBBBBBB BBBBBBBB*/if (frag_offset + ltrim < prev->offset + prev->ltrim &&frag_end > prev->offset + prev->ltrim) {prev->ltrim += frag_end - (prev->offset + prev->ltrim);goto insert;}/* If the new fragment completely overlaps the* previous fragment, mark the previous to be* skipped. Re-assembly would succeed without doing* this, but this will prevent the bytes from being* copied just to be overwritten. */if (frag_offset + ltrim <= prev->offset + prev->ltrim &&frag_end >= prev->offset + prev->data_len) {prev->skip = 1;goto insert;}break;... ...
}
3.2.3.1.4 DEFRAG_POLICY_WINDOWS

該策略遵循"先到先得"原則,即盡量保全先到來的數據包分片。除非新分片包含且不完全重合于舊分片的情況下,保留新分片。如果新分片左側偏移與舊分片左側偏移相等的情況下,優先裁剪新分片數據。

該部分邏輯代碼實現如下所示:

/*** Insert a new IPv4/IPv6 fragment into a tracker.** \todo Allocate packet buffers from a pool.*/
static Packet *
DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
{... ...case DEFRAG_POLICY_WINDOWS:/* If new fragment fits inside a previous fragment, drop it. */if (frag_offset + ltrim >= prev->offset + ltrim &&frag_end <= prev->offset + prev->data_len) {goto done;}/* If new fragment starts before and ends after* previous fragment, drop the previous fragment. */ if (frag_offset + ltrim < prev->offset + ltrim &&frag_end > prev->offset + prev->data_len) {prev->skip = 1;goto insert;}/* Check if new fragment overlaps the end of previous* fragment, if it does, trim the new fragment.** Old: AAAAAAAA AAAAAAAA AAAAAAAA* New:          BBBBBBBB BBBBBBBB BBBBBBBB* Res: AAAAAAAA AAAAAAAA AAAAAAAA BBBBBBBB*/if (frag_offset + ltrim > prev->offset + prev->ltrim &&frag_offset + ltrim < prev->offset + prev->data_len) {  ltrim += prev->offset + prev->data_len - frag_offset; goto insert;}/* If new fragment starts at same offset as an* existing fragment, but ends after it, trim the new* fragment. */if (frag_offset + ltrim == prev->offset + ltrim &&frag_end > prev->offset + prev->data_len) {ltrim += prev->offset + prev->data_len - frag_offset;goto insert;}break;... ...
}
3.2.3.1.5 DEFRAG_POLICY_SOLARIS

該策略遵循左側優先法,即優先保留左側偏移較小的分片數據。如果新分片與舊分片完全重合的情況下,優先保留舊分片。如果新分片左側偏移與舊分片左側偏移相等的情況下,優先裁剪新分片數據。

該部分邏輯代碼實現如下所示:

/*** Insert a new IPv4/IPv6 fragment into a tracker.** \todo Allocate packet buffers from a pool.*/
static Packet *
DefragInsertFrag(ThreadVars *tv, DecodeThreadVars *dtv, DefragTracker *tracker, Packet *p)
{... ...case DEFRAG_POLICY_SOLARIS:if (frag_offset < prev->offset + prev->data_len) {if (frag_offset >= prev->offset) {ltrim = prev->offset + prev->data_len - frag_offset;}if ((frag_offset < prev->offset) &&(frag_end >= prev->offset + prev->data_len)) {prev->skip = 1;}goto insert;}break;... ...
}
3.2.3.2 獲取主機系統策略

在Suricata的配置文件中通過host-os-policy關鍵字已經配置好主機系統策略,而在初始化DefragTracker對象時,即調用DefragTrackerInit函數時,會通過當前分片的IP地址,結合host-os-policy配置來選擇重組策略。

調用邏輯如下所示:

在 DefragGetOsPolicy 函數中,Suricata會將不同的系統策略歸為7類。注意,如果未配置,默認重組策略為DEFRAG_POLICY_BSD。

系統策略

分片重組策略

DEFRAG_POLICY_BSD

OS_POLICY_BSD

OS_POLICY_HPUX10

OS_POLICY_IRIX

DEFRAG_POLICY_BSD_RIGHT

OS_POLICY_BSD_RIGHT

DEFRAG_POLICY_LINUX

OS_POLICY_OLD_LINUX

OS_POLICY_LINUX

DEFRAG_POLICY_FIRST

OS_POLICY_OLD_SOLARIS

OS_POLICY_HPUX11

OS_POLICY_MACOS

OS_POLICY_FIRST

DEFRAG_POLICY_SOLARIS

OS_POLICY_SOLARIS

DEFRAG_POLICY_WINDOWS

OS_POLICY_WINDOWS

OS_POLICY_VISTA

OS_POLICY_WINDOWS2K3

DEFRAG_POLICY_LAST

OS_POLICY_LAST

分片重組策略結構如下所示:

/** Fragment reassembly policies. */
enum defrag_policies {DEFRAG_POLICY_FIRST = 1,DEFRAG_POLICY_LAST,DEFRAG_POLICY_BSD,DEFRAG_POLICY_BSD_RIGHT,DEFRAG_POLICY_LINUX,DEFRAG_POLICY_WINDOWS,DEFRAG_POLICY_SOLARIS,DEFRAG_POLICY_DEFAULT = DEFRAG_POLICY_BSD,
};

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/83080.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/83080.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/83080.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

二分查找的邊界問題

前言 二分查找(Binary Search)是一種高效的查找算法&#xff0c;時間復雜度為O(log n)。它適用于已排序的數組或列表。本文將詳細介紹二分查找的兩種常見寫法&#xff1a;閉區間寫法和左閉右開區間寫法。 一、二分查找基本思想 二分查找的核心思想是"分而治之"&am…

重慶醫科大學附屬第二醫院外科樓外擋墻自動化監測

1.項目概述 重慶醫科大學附屬第二醫院&#xff0c;重醫附二院&#xff0c;是集醫療、教學、科研、預防保健為一體的國家三級甲等綜合醫院。前身為始建于1892年的“重慶寬仁醫院”。醫院現有開放床位 1380張&#xff0c;年門診量超過百萬人次&#xff0c;年收治住院病人4.5萬人…

【Redis實戰篇】秒殺優化

1. 秒殺優化-異步秒殺思路 我們來回顧一下下單流程 當用戶發起請求&#xff0c;此時會請求nginx&#xff0c;nginx會訪問到tomcat&#xff0c;而tomcat中的程序&#xff0c;會進行串行操作&#xff0c;分成如下幾個步驟 1、查詢優惠卷 2、判斷秒殺庫存是否足夠 3、查詢訂單…

【idea】調試篇 idea調試技巧合集

前言&#xff1a;之前博主寫過一篇idea技巧合集的文章&#xff0c;由于技巧過于多了&#xff0c;文章很龐大&#xff0c;所以特地將調試相關的技巧單獨成章, 調試和我們日常開發是息息相關的&#xff0c;用好調試可以事半功倍 文章目錄 1. idea調試異步線程2. idea調試stream流…

postman 用法 LTS

postman 用法 LTS File ---- View ---- Show Postman Console

MySQL 數據庫故障排查指南

MySQL 數據庫故障排查指南 本指南旨在幫助您識別和解決常見的 MySQL 數據庫故障。我們將從問題識別開始&#xff0c;逐步深入到具體的故障類型和排查步驟。 1. 問題識別與信息收集 在開始排查之前&#xff0c;首先需要清晰地了解問題的現象和范圍。 故障現象&#xff1a; 數…

用AI寫簡歷是否可行?

讓AI批量寫簡歷然后投簡歷是絕對不行的&#xff01;&#xff01;&#xff01; 為什么不行&#xff0c;按照 "招聘經理" 工作經歷舉例&#xff1a; ai提示詞&#xff1a;請幫我寫一份招聘經理的工作經歷內容&#xff1a; 招聘經理 | XXX科技有限公司 | 2020年…

【從零實現JsonRpc框架#1】Json庫介紹

1.JsonCpp第三方庫 JSONCPP 是一個開源的 C 庫&#xff0c;用于解析和生成 JSON&#xff08;JavaScript Object Notation&#xff09;數據。它提供了簡單易用的接口&#xff0c;支持 JSON 的序列化和反序列化操作&#xff0c;適用于處理配置文件、網絡通信數據等場景。 2.Jso…

Ubuntu——執行echo $USE什么都不顯示

問題&#xff1a;“執行 echo $USER 什么都不顯示”&#xff1f; 一、原因分析 環境變量 $USER 未正確設置 $USER 是系統自動定義的環境變量&#xff0c;通常用于表示當前登錄的用戶名。若該變量未設置或為空&#xff0c;執行 echo $USER 會無輸出。可能場景&#xff1a; 用戶通…

uni-app學習筆記五--vue3插值表達式的使用

vue3快速上手導航&#xff1a;簡介 | Vue.js 模板語法 插值表達式 最基本的數據綁定形式是文本插值&#xff0c;它使用的是“Mustache”語法 (即雙大括號)&#xff1a; <span>Message: {{ msg }}</span> 雙大括號標簽會被替換為相應組件實例中 msg 屬性的值。同…

【PSINS工具箱】基于工具箱的單獨GNSS導航、單獨INS導航、兩者結合組合導航,三種導航的對比程序。附完整的代碼

本文給出基于PSINS工具箱的單獨GNSS導航、單獨INS導航、兩者結合組合導航(153EKF)的程序。并提供三者的軌跡對比、誤差對比。 文章目錄 運行結果MATLAB代碼代碼的簡單介紹簡介2. 平均絕對誤差 (MAE)主要模塊運行結果 三軸軌跡圖: 各軸誤差曲線: 命令行窗口的結果輸出: …

C. scanf 函數基礎

scanf 函數 1. scanf 函數基礎1.1 函數原型與頭文件1.2 格式化輸入的基本概念2.1 常見格式說明符整數格式說明符浮點數格式說明符字符和字符串格式說明符其他格式說明符2.2 格式說明符的高級用法寬度修飾符精度修飾符跳過輸入字段寬度組合修飾符對齊修飾符實際應用示例3.2 精度…

spring cloud loadbalancer實現機房感知的負載均衡

1 概述 在同城多機房情景下&#xff0c;各個機房各自部署一套微服務集群&#xff0c;正常情況下微服務調用在本機房閉環。在如下某些災難情景&#xff0c;可以嘗試拉遠調用以最大程度維持業務連續性&#xff0c;這些情景例如&#xff1a; A機房多個服務器宕機。應用由于BUG發…

vue中,created和mounted兩個鉤子之間調用時差值受什么影響

在 Vue 中&#xff0c;created 和 mounted 是兩個生命周期鉤子&#xff0c;它們之間的調用時差主要受以下幾個因素影響&#xff1a; &#x1f7e2; 1. 模板復雜度與渲染耗時&#xff08;最主要因素&#xff09; mounted 的觸發時間是在組件的 DOM 被掛載之后&#xff08;也就是…

Linux篇 第2章Linux基礎指令

Linux篇 第2章Linux基礎指令 文章目錄 前言一、基礎的一些命令1.pwd2.mkdir3.ls4.cd5.clear 二、ls1.ls -l2.ls -a3.ls -l -a 三、touch四、 cd1.cd /2.cd ..3.cd ~4. cd - 五、tree1. Linux系統文件的結構2.絕對路徑和相對路徑 六、mkdir -p七、rmdir&#xff08;沒啥用&#…

Scrapyd 詳解:分布式爬蟲部署與管理利器

Scrapyd 是 Scrapy 官方提供的爬蟲部署與管理平臺&#xff0c;支持分布式爬蟲部署、定時任務調度、遠程管理爬蟲等功能。本文將深入講解 Scrapyd 的核心功能、安裝配置、爬蟲部署流程、API 接口使用&#xff0c;以及如何結合 Scrapy-Redis 實現分布式爬蟲管理。通過本文&#x…

國產免費工作流引擎star 6.5k,Warm-Flow升級1.7.2(新增案例和修復缺陷)

文章目錄 主要更新內容項目介紹功能思維導圖設計器流程圖演示地址官網Warm-Flow視頻 主要更新內容 [feat] 開啟流程實例&#xff0c;新增流程定義是否存在校驗[feat] 新增合同簽訂流程案例[feat] 新增企業采購流程案例[update] mybatis-plus邏輯刪除&#xff0c;刪除值和未刪除…

數據倉庫Hive

1.數據倉庫 1.1數據倉庫的概念 數據倉庫&#xff08;Data Warehouse&#xff09;是一個面向主題的、集成的、相對穩定的、反映歷史變化的數據集合&#xff0c;用于支持管理決策。 面向主題。操作型數據庫的數據組織面向事務處理任務&#xff0c;而數據倉庫中的數據按照一定的…

dify 連接不上ollama An error occurred during credentials validation:

三大報錯 An error occurred during credentials validation: HTTPConnectionPool(hosthost.docker.internal, port11434): Max retries exceeded with url: /api/chat (Caused by NameResolutionError("<urllib3.connection.HTTPConnection object at 0x7f26fc3c00b0&…

uniapp 生成海報二維碼 (微信小程序)

先下載qrcodenpm install qrcode 調用 community_poster.vue <template><view class"poster-page"><uv-navbar title"物業推廣碼" placeholder autoBack></uv-navbar><view class"community-info"><text clas…