Linux内核中的IPSEC实现(1)

IPSec 同时被 3 个专栏收录
11 篇文章 0 订阅
146 篇文章 1 订阅
194 篇文章 0 订阅
Java代码   收藏代码
  1. 1. 前言  
  2.   
  3. 在Linux2.6内核中自带了IPSEC的实现,这样就不用象2.4那样打补丁来实现了。该实现包括以下几个部分: PF_KEY类型套接口, 用来提供和用户层空间进行PF_KEY通信,代码在net/key目录下,前面已经介绍过;安全联盟SA和安全策略SP管理,是使用xfrm库来实现的,代码在net/xfrm/目录下定义;ESP,AH等协议实现,在net/ipv4(6)下定义;加密认证算法库,在crypto目录下定义,这些算法都是标准代码了。本系列文章主要描述XFRM库的实现以及在IPV4下相关协议的处理部分, IPV6的忽略。  
  4.   
  5. 本文Linux内核代码版本为2.6.19.2。xfrm是内核中变化比较大的部分,每个版本中都有不小的差异, 同时也说明了该模块的不成熟性。  
  6. 在net/xfrm目录下的各文件大致功能说明如下:  
  7. xfrm_state.c: xfrm状态管理  
  8. xfrm_policy.c: xfrm策略管理  
  9. xfrm_algo.c: 算法管理  
  10. xfrm_hash.c: HASH计算函数  
  11. xfrm_input.c: 安全路径(sec_path)处理,用于进入的ipsec包  
  12. xfrm_user.c:  netlink接口的SA和SP管理  
  13. 在net/ipv4目录下的和ipsec相关各文件大致功能说明如下:  
  14. ah4.c: IPV4的AH协议处理  
  15. esp4.c: IPV4的ESP协议处理  
  16. ipcomp.c: IP压缩协议处理  
  17. xfrm4_input: 接收的IPV4的IPSEC包处理  
  18. xfrm4_output: 发出的IPV4的IPSEC包处理  
  19. xfrm4_state: IPV4的SA处理  
  20. xfrm4_policy: IPV4的策略处理  
  21. xfrm4_tunnel: IPV4的通道处理  
  22. xfrm4_mode_transport: 传输模式  
  23. xfrm4_mode_tunnel: 通道模式  
  24. xfrm4_mode_beet: BEET模式  
  25.   
  26. 2. 数据结构  
  27.   
  28. 内核SA的定义用xfrm_state结构定义,SP用xfrm_policy结构定义,在include/net/xfrm.h中定义。  
  29.   
  30. 2.1 状态(SA)  
  31.   
  32. xfrm_state状态结构用来描述SA在内核中的具体实现:  
  33. struct xfrm_state  
  34. {  
  35.  /* Note: bydst is re-used during gc */  
  36. // 每个状态结构挂接到三个HASH链表中  
  37.  struct hlist_node bydst; // 按目的地址HASH  
  38.  struct hlist_node bysrc; // 按源地址HASH  
  39.  struct hlist_node byspi; // 按SPI值HASH  
  40.  atomic_t  refcnt; // 所有使用计数  
  41.  spinlock_t  lock;   // 状态锁  
  42.  struct xfrm_id  id; // ID结构, 即目的地址,SPI,协议三元组  
  43.  struct xfrm_selector sel; // 状态选择子  
  44.  u32   genid; // 状态的标志值, 防止发生碰撞  
  45.  /* Key manger bits */  
  46.  struct {  
  47.   u8  state;  
  48.   u8  dying;  
  49.   u32  seq;  
  50.  } km;  // KEY回调管理处理结构参数  
  51.  /* Parameters of this state. */  
  52.  struct {  
  53.   u32  reqid; // 请求ID  
  54.   u8  mode;  // 模式: 传输/通道  
  55.   u8  replay_window; // 回放窗口  
  56.   u8  aalgo, ealgo, calgo; // 认证,加密,压缩算法ID值  
  57.   u8  flags; // 一些标准  
  58.   u16  family; // 协议族  
  59.   xfrm_address_t saddr;  // 源地址  
  60.   int  header_len;  // 添加的协议头长度  
  61.   int  trailer_len; //  
  62.  } props; // SA相关参数结构  
  63.  struct xfrm_lifetime_cfg lft; // 生存时间配置  
  64.  /* Data for transformer */  
  65.  struct xfrm_algo *aalg; // hash算法  
  66.  struct xfrm_algo *ealg; // 加密算法  
  67.  struct xfrm_algo *calg; // 压缩算法  
  68.  /* Data for encapsulator */  
  69.  struct xfrm_encap_tmpl *encap; // NAT-T封装信息  
  70.  /* Data for care-of address */  
  71.  xfrm_address_t *coaddr;  
  72.  /* IPComp needs an IPIP tunnel for handling uncompressed packets */  
  73.  struct xfrm_state *tunnel;  // 通道, 实际是另一个SA  
  74.  /* If a tunnel, number of users + 1 */  
  75.  atomic_t  tunnel_users; // 通道的使用数  
  76.  /* State for replay detection */  
  77.  struct xfrm_replay_state replay; // 回放检测结构,包含各种序列号掩码等信息  
  78.  /* Replay detection state at the time we sent the last notification */  
  79.  struct xfrm_replay_state preplay; // 上次的回放记录值  
  80.  /* internal flag that only holds state for delayed aevent at the 
  81.   * moment 
  82.  */  
  83.  u32   xflags; // 标志  
  84.  /* Replay detection notification settings */  
  85.  u32   replay_maxage; // 回放最大时间间隔  
  86.  u32   replay_maxdiff; // 回放最大差值  
  87.  /* Replay detection notification timer */  
  88.  struct timer_list rtimer; // 回放检测定时器  
  89.  /* Statistics */  
  90.  struct xfrm_stats stats; // 统计值  
  91.  struct xfrm_lifetime_cur curlft; // 当前时间计数器  
  92.  struct timer_list timer;  // SA定时器  
  93.  /* Last used time */  
  94.  u64   lastused; // 上次使用时间  
  95.  /* Reference to data common to all the instances of this 
  96.   * transformer. */  
  97.  struct xfrm_type *type;  // 协议, ESP/AH/IPCOMP  
  98.  struct xfrm_mode *mode;  // 模式, 通道或传输  
  99.  /* Security context */  
  100.  struct xfrm_sec_ctx *security; // 安全上下文, 加密时使用  
  101.  /* Private data of this transformer, format is opaque, 
  102.   * interpreted by xfrm_type methods. */  
  103.  void   *data; // 内部数据  
  104. };  
  105.    
  106. 2.2 安全策略(SP)  
  107.   
  108. xfrm_policy结构用于描述SP在内核内部的具体实现:  
  109. struct xfrm_policy  
  110. {  
  111.  struct xfrm_policy *next; // 下一个策略  
  112.  struct hlist_node bydst; // 按目的地址HASH的链表  
  113.  struct hlist_node byidx; // 按索引号HASH的链表  
  114.  /* This lock only affects elements except for entry. */  
  115.  rwlock_t  lock;  // 策略结构锁  
  116.  atomic_t  refcnt; // 引用次数  
  117.  struct timer_list timer; // 策略定时器  
  118.  u8   type;     // 类型  
  119.  u32   priority; // 策略优先级  
  120.  u32   index;    // 策略索引号  
  121.  struct xfrm_selector selector; // 选择子  
  122.  struct xfrm_lifetime_cfg lft;     // 策略生命期  
  123.  struct xfrm_lifetime_cur curlft;  // 当前的生命期数据  
  124.  struct dst_entry       *bundles;  // 路由链表  
  125.  __u16   family;   // 协议族  
  126.  __u8   action;   // 策略动作, 接受/加密/阻塞...  
  127.  __u8   flags;    // 标志  
  128.  __u8   dead;     // 策略死亡标志  
  129.  __u8   xfrm_nr;  // 使用的xfrm_vec的数量  
  130.  struct xfrm_sec_ctx *security; // 安全上下文  
  131.  struct xfrm_tmpl        xfrm_vec[XFRM_MAX_DEPTH]; // 状态模板  
  132. };  
  133.   
  134. xfrm模板结构, 用于状态和策略的查询:  
  135. struct xfrm_tmpl  
  136. {  
  137. /* id in template is interpreted as: 
  138.  * daddr - destination of tunnel, may be zero for transport mode. 
  139.  * spi   - zero to acquire spi. Not zero if spi is static, then 
  140.  *    daddr must be fixed too. 
  141.  * proto - AH/ESP/IPCOMP 
  142.  */  
  143. // SA三元组, 目的地址, 协议, SOI  
  144.  struct xfrm_id  id;  
  145. /* Source address of tunnel. Ignored, if it is not a tunnel. */  
  146. // 源地址  
  147.  xfrm_address_t  saddr;  
  148. // 请求ID  
  149.  __u32   reqid;  
  150. /* Mode: transport, tunnel etc. */  
  151.  __u8   mode;  
  152. /* Sharing mode: unique, this session only, this user only etc. */  
  153.  __u8   share;  
  154. /* May skip this transfomration if no SA is found */  
  155.  __u8   optional;  
  156. /* Bit mask of algos allowed for acquisition */  
  157.  __u32   aalgos;  
  158.  __u32   ealgos;  
  159.  __u32   calgos;  
  160. };  
  161.    
  162. 2.3 协议结构  
  163. 对ESP, AH, IPCOMP等协议的描述是通过xfrm_type结构来描述的, 多个协议的封装就是靠多个协议结构形成的链表来实现:  
  164. struct xfrm_type  
  165. {  
  166.  char   *description; // 描述字符串  
  167.  struct module  *owner; // 协议模块  
  168.  __u8   proto;  // 协议值  
  169.  __u8   flags;  // 标志  
  170. #define XFRM_TYPE_NON_FRAGMENT 1  
  171. // 初始化状态  
  172.  int   (*init_state)(struct xfrm_state *x);  
  173. // 析构函数  
  174.  void   (*destructor)(struct xfrm_state *);  
  175. // 数据输入函数  
  176.  int   (*input)(struct xfrm_state *, struct sk_buff *skb);  
  177. // 数据输出函数  
  178.  int   (*output)(struct xfrm_state *, struct sk_buff *pskb);  
  179. // 拒绝函数  
  180.  int   (*reject)(struct xfrm_state *, struct sk_buff *, struct flowi *);  
  181. // 头部偏移  
  182.  int   (*hdr_offset)(struct xfrm_state *, struct sk_buff *, u8 **);  
  183. // 本地地址  
  184.  xfrm_address_t  *(*local_addr)(struct xfrm_state *, xfrm_address_t *);  
  185. // 远程地址  
  186.  xfrm_address_t  *(*remote_addr)(struct xfrm_state *, xfrm_address_t *);  
  187.  /* Estimate maximal size of result of transformation of a dgram */  
  188. // 最大数据报长度  
  189.  u32   (*get_max_size)(struct xfrm_state *, int size);  
  190. };  
  191. 具体的协议结构定义如下, 通常只定义初始化,析构,输入和输出四个成员函数:  
  192. AH协议定义  
  193. /* net/ipv4/ah4.c */  
  194. static struct xfrm_type ah_type =  
  195. {  
  196.  .description = "AH4",  
  197.  .owner  = THIS_MODULE,  
  198.  .proto       = IPPROTO_AH,  
  199.  .init_state = ah_init_state,  
  200.  .destructor = ah_destroy,  
  201.  .input  = ah_input,  
  202.  .output  = ah_output  
  203. };  
  204. ESP协议定义:  
  205. /* net/ipv4/esp4.c */  
  206. static struct xfrm_type esp_type =  
  207. {  
  208.  .description = "ESP4",  
  209.  .owner  = THIS_MODULE,  
  210.  .proto       = IPPROTO_ESP,  
  211.  .init_state = esp_init_state,  
  212.  .destructor = esp_destroy,  
  213.  .get_max_size = esp4_get_max_size,  
  214.  .input  = esp_input,  
  215.  .output  = esp_output  
  216. };  
  217. IP压缩协议定义:  
  218. /* net/ipv4/ipcomp.c */  
  219. static struct xfrm_type ipcomp_type = {  
  220.  .description = "IPCOMP4",  
  221.  .owner  = THIS_MODULE,  
  222.  .proto       = IPPROTO_COMP,  
  223.  .init_state = ipcomp_init_state,  
  224.  .destructor = ipcomp_destroy,  
  225.  .input  = ipcomp_input,  
  226.  .output  = ipcomp_output  
  227. };  
  228. IPIP协议定义:  
  229. /* net/ipv4/xfrm4_tunnel.c */  
  230. static struct xfrm_type ipip_type = {  
  231.  .description = "IPIP",  
  232.  .owner  = THIS_MODULE,  
  233.  .proto       = IPPROTO_IPIP,  
  234.  .init_state = ipip_init_state,  
  235.  .destructor = ipip_destroy,  
  236.  .input  = ipip_xfrm_rcv,  
  237.  .output  = ipip_output  
  238. };  
  239. 2.4 模式结构  
  240.   
  241. 模式结构用于描述IPSEC连接描述, 可为通道模式或传输模式两种:  
  242. struct xfrm_mode {  
  243. // 数据输入函数  
  244.  int (*input)(struct xfrm_state *x, struct sk_buff *skb);  
  245. // 数据输出函数  
  246.  int (*output)(struct xfrm_state *x,struct sk_buff *skb);  
  247. // 模块指针  
  248.  struct module *owner;  
  249. // 封装  
  250.  unsigned int encap;  
  251. };  
  252. 通道模式结构定义:  
  253. /* net/ipv4/xfrm4_mode_tunnel.c */  
  254. static struct xfrm_mode xfrm4_tunnel_mode = {  
  255.  .input = xfrm4_tunnel_input,  
  256.  .output = xfrm4_tunnel_output,  
  257.  .owner = THIS_MODULE,  
  258.  .encap = XFRM_MODE_TUNNEL,  
  259. };  
  260. 传输模式结构定义:  
  261. /* net/ipv4/xfrm4_mode_transport.c */  
  262. static struct xfrm_mode xfrm4_transport_mode = {  
  263.  .input = xfrm4_transport_input,  
  264.  .output = xfrm4_transport_output,  
  265.  .owner = THIS_MODULE,  
  266.  .encap = XFRM_MODE_TRANSPORT,  
  267. };  
  268. beet模式, 不知道在哪用  
  269. /* net/ipv4/xfrm4_mode_beet.c */  
  270. static struct xfrm_mode xfrm4_beet_mode = {  
  271.  .input = xfrm4_beet_input,  
  272.  .output = xfrm4_beet_output,  
  273.  .owner = THIS_MODULE,  
  274.  .encap = XFRM_MODE_BEET,  
  275. };  
  276.   
  277. 2.5 策略的相关协议处理结构  
  278.   
  279. 以下结构用于描述具体协议族下的的策略处理:  
  280. struct xfrm_policy_afinfo {  
  281. // 协议族  
  282.  unsigned short  family;  
  283. // 协议类型  
  284.  struct xfrm_type *type_map[IPPROTO_MAX];  
  285. // 模式  
  286.  struct xfrm_mode *mode_map[XFRM_MODE_MAX];  
  287. // 目的操作结构  
  288.  struct dst_ops  *dst_ops;  
  289. // 垃圾搜集  
  290.  void   (*garbage_collect)(void);  
  291. // 路由选择  
  292.  int   (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl);  
  293. // 获取源地址  
  294.  int   (*get_saddr)(xfrm_address_t *saddr, xfrm_address_t *daddr);  
  295. // 查找路由项  
  296.  struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy);  
  297. // 创建新路由项  
  298.  int   (*bundle_create)(struct xfrm_policy *policy,  
  299.        struct xfrm_state **xfrm,  
  300.        int nx,  
  301.        struct flowi *fl,  
  302.        struct dst_entry **dst_p);  
  303. // 解码会话  
  304.  void   (*decode_session)(struct sk_buff *skb,  
  305.         struct flowi *fl);  
  306. };  
  307.   
  308. IPV4的策略协议相关处理结构定义如下:  
  309. /* net/ipv4/xfrm4_policy.c */  
  310. static struct xfrm_policy_afinfo xfrm4_policy_afinfo = {  
  311.  .family =   AF_INET,  
  312.  .dst_ops =  &xfrm4_dst_ops,  
  313.  .dst_lookup =  xfrm4_dst_lookup,  
  314.  .get_saddr =  xfrm4_get_saddr,  
  315.  .find_bundle =   __xfrm4_find_bundle,  
  316.  .bundle_create = __xfrm4_bundle_create,  
  317.  .decode_session = _decode_session4,  
  318.   
  319. 2.5 状态的相关协议处理结构  
  320. 以下结构用于描述具体协议族下的的状态处理:  
  321. struct xfrm_state_afinfo {  
  322. // 协议族  
  323.  unsigned short  family;  
  324. // 初始化标志  
  325.  int   (*init_flags)(struct xfrm_state *x);  
  326. // 初始化模板选择  
  327.  void   (*init_tempsel)(struct xfrm_state *x, struct flowi *fl,  
  328.       struct xfrm_tmpl *tmpl,  
  329.       xfrm_address_t *daddr, xfrm_address_t *saddr);  
  330. // 模板排序  
  331.  int   (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);  
  332. // 状态排序  
  333.  int   (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);  
  334. };  
  335. IPV4的状态相关协议处理结构  
  336. /* net/ipv4/xfrm4_state.c */  
  337. static struct xfrm_state_afinfo xfrm4_state_afinfo = {  
  338.  .family   = AF_INET,  
  339.  .init_flags  = xfrm4_init_flags,  
  340.  .init_tempsel  = __xfrm4_init_tempsel,  
  341. };  
  342.   
  343. 2.6 回调通知信息结构  
  344. struct xfrm_mgr  
  345. {  
  346.  struct list_head list;  
  347.  char   *id;  
  348. // 状态通知  
  349.  int   (*notify)(struct xfrm_state *x, struct km_event *c);  
  350. // 获取, 如获取SA  
  351.  int   (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir);  
  352. // 编译策略  
  353.  struct xfrm_policy *(*compile_policy)(struct sock *sk, int opt, u8 *data, int len, int *dir);  
  354. // 映射  
  355.  int   (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport);  
  356. // 策略通知  
  357.  int   (*notify_policy)(struct xfrm_policy *x, int dir, struct km_event *c);  
  358. // 报告  
  359.  int   (*report)(u8 proto, struct xfrm_selector *sel, xfrm_address_t *addr);  
  360. };  
  361.   
  362. 在net/key/pf_key.c中定义了pkeyv2_mgr结构:  
  363. static struct xfrm_mgr pfkeyv2_mgr =  
  364. {  
  365.  .id  = "pfkeyv2",  
  366.  .notify  = pfkey_send_notify,  
  367.  .acquire = pfkey_send_acquire,  
  368.  .compile_policy = pfkey_compile_policy,  
  369.  .new_mapping = pfkey_send_new_mapping,  
  370.  .notify_policy = pfkey_send_policy_notify,  
  371. };  
  372.   
  373. 3. 初始化  
  374.   
  375. /* net/xfrm/xfrm_policy.c */  
  376. // xfrm初始化函数包括状态, 策略和输入处理的三初始化函数  
  377. // xfrm是不支持模块方式的  
  378. void __init xfrm_init(void)  
  379. {  
  380.  xfrm_state_init();  
  381.  xfrm_policy_init();  
  382.  xfrm_input_init();  
  383. }  
  384.   
  385. 3.1 xfrm状态初始化  
  386. /* net/xfrm/xfrm_state.c */  
  387. void __init xfrm_state_init(void)  
  388. {  
  389.  unsigned int sz;  
  390. // 初始HASH表不大, 每个HASH中初始化为8个链表, 但随着状态数量的增加  
  391. // 会动态增加HASH表数量  
  392.  sz = sizeof(struct hlist_head) * 8;  
  393. // 建立3组HASH, 分别按SA的源地址, 目的地址和SPI值  
  394.  xfrm_state_bydst = xfrm_hash_alloc(sz);  
  395.  xfrm_state_bysrc = xfrm_hash_alloc(sz);  
  396.  xfrm_state_byspi = xfrm_hash_alloc(sz);  
  397.  if (!xfrm_state_bydst || !xfrm_state_bysrc || !xfrm_state_byspi)  
  398.   panic("XFRM: Cannot allocate bydst/bysrc/byspi hashes.");  
  399. // xfrm_state_hmask初始值为=7, 计算出的HASH值与该值与来得到链表号  
  400.  xfrm_state_hmask = ((sz / sizeof(struct hlist_head)) - 1);  
  401. // 初始化工作队列work_queue, 完成对状态垃圾的搜集和释放  
  402.  INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL);  
  403. }  
  404.   
  405. 3.2 策略初始化  
  406.   
  407. static void __init xfrm_policy_init(void)  
  408. {  
  409.  unsigned int hmask, sz;  
  410.  int dir;  
  411. // 建立一个内核cache, 用于分配xfrm_dst结构()  
  412.  xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache",  
  413.         sizeof(struct xfrm_dst),  
  414.         0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,  
  415.         NULL, NULL);  
  416. // 分配状态HASH表, 初始是8个HASH链表,以后随着策略数量的增加  
  417. // 会动态增加HASH表的数量  
  418.  hmask = 8 - 1;  
  419.  sz = (hmask+1) * sizeof(struct hlist_head);  
  420. // 该HASH表是按策略的index参数进行索引的  
  421.  xfrm_policy_byidx = xfrm_hash_alloc(sz);  
  422.  xfrm_idx_hmask = hmask;  
  423.  if (!xfrm_policy_byidx)  
  424.   panic("XFRM: failed to allocate byidx hash\n");  
  425. // 输入, 输出, 转发三个处理点, 双向  
  426.  for (dir = 0; dir < XFRM_POLICY_MAX * 2; dir++) {  
  427.   struct xfrm_policy_hash *htab;  
  428. // 初始化inexact链表头, inexact处理选择子相关长度不是标准值的一些特别策略  
  429.   INIT_HLIST_HEAD(&xfrm_policy_inexact[dir]);  
  430. // 分配按地址HASH的HASH表  
  431.   htab = &xfrm_policy_bydst[dir];  
  432.   htab->table = xfrm_hash_alloc(sz);  
  433.   htab->hmask = hmask;  
  434.   if (!htab->table)  
  435.    panic("XFRM: failed to allocate bydst hash\n");  
  436.  }  
  437. // 初始化策略垃圾搜集的工作队列, 完成对策略垃圾的搜集和释放  
  438.  INIT_WORK(&xfrm_policy_gc_work, xfrm_policy_gc_task, NULL);  
  439. // 登记网卡通知  
  440.  register_netdevice_notifier(&xfrm_dev_notifier);  
  441. }  
  442. xfrm的网卡通知回调结构  
  443. static struct notifier_block xfrm_dev_notifier = {  
  444.  xfrm_dev_event,  
  445.  NULL,  
  446.  0  
  447. };  
  448. // 网卡通知回调函数  
  449. static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)  
  450. {  
  451.  switch (event) {  
  452. // 如果网卡down掉的话, 清除相关的所有的xfrm路由项  
  453.  case NETDEV_DOWN:  
  454.   xfrm_flush_bundles();  
  455.  }  
  456.  return NOTIFY_DONE;  
  457. }  
  458. // 清除相关的所有的xfrm路由项  
  459. static int xfrm_flush_bundles(void)  
  460. {  
  461. // 将不用的路由项删除  
  462.  xfrm_prune_bundles(stale_bundle);  
  463.  return 0;  
  464. }  
  465.    
  466. 3.3 输入初始化  
  467. /* net/xfrm/xfrm_input.c */  
  468. void __init xfrm_input_init(void)  
  469. {  
  470. // 建立一个内核cache, 用于分配sec_path结构(安全路径)  
  471.  secpath_cachep = kmem_cache_create("secpath_cache",  
  472.         sizeof(struct sec_path),  
  473.         0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,  
  474.         NULL, NULL);  
  475. }  
  476. struct sec_path结构是对输入的加密包进行层层解包的处理, 在sk_buff中有该结构的指针sp, 如果sp非空表示这是个IPSEC解密后的包。  
  477.    
  478. ...... 待续 ......  
  479.    
  480.   
  481. 发表于: 2007-06-03,修改于: 2007-06-03 00:27,已浏览6239次,有评论23条 推荐 投诉  
  482.     网友: 本站网友    时间:2007-10-12 15:19:10 IP地址:222.64.17.★  
  483.       
  484.   
  485. 强烈的顶顶顶!!!   
  486.   
  487.  15G空间=5个网站=500元/年 可免费试用   
  488.   
  489. www.abcnic.com    QQ:1012727  
  490.   
  491. 5GB 独立WEB空间、5GB 企业邮箱空间、5GB MSSQL数据库     
  492.   
  493. IIS连接数据 500 个、500GB/月流量、共享日志文件空间   
  494.   
  495. 数据库功能   
  496.   
  497. 支持5GB MSSQL数据库空间,5个用户数据库、Access   
  498.   
  499. 主机功能支持   
  500.   
  501. 采用安全稳定的Win2003 .net2.0 架构   
  502.   
  503. 支持ASP、PHP、ASP.NET、PERL等脚本、支持自定义CGI   
  504.   
  505. 全面支持.net2.0版本,独立的Application应用池,  
  506.   
  507. 支持SSI(Shtml),支持FrontPage扩展   
  508.   
  509. 可免费自行绑定5个域名、500个解析、500个子域名  
  510.   
  511.  企业邮箱功能   
  512.   
  513. 赠送5GB 超大企业邮箱,500个Email企业邮箱用户   
  514.   
  515. 自动回复、自动转发、POP3、SMTP收发信、SMTP发信认证   
  516.   
  517. 邮件过滤、邮件拒收、邮件夹管理、邮件域管理、定制邮件数   
  518.   
  519.   
  520.     网友: zetalog     时间:2007-11-19 10:57:41 IP地址:218.81.225.★  
  521.       
  522.   
  523. 为什么bundle是路由?!!  
  524.   
  525. 根据RFC2401,对于外出处理SPD entry直接指向SA Bundle,是这SA束吧!  
  526.   
  527. 看看注释也知道了:  
  528.   
  529.    dst -. xfrm  .-> xfrm_state #1  
  530.   
  531.     |---. child .-> dst -. xfrm .-> xfrm_state #2  
  532.   
  533.                      |---. child .-> dst -. xfrm .-> xfrm_state #3  
  534.   
  535.                                       |---. child .-> NULL  
  536.   
  537. dst_entry和xfrm_dst都是包含xfrm_state的,而且通过.child连接为SA束。  
  538.   
  539.   
  540.     网友: yfydz   时间:2007-11-19 12:36:03 IP地址:218.247.216.★  
  541.       
  542.   
  543. 那你觉得这SA束又是什么东西?  
  544.   
  545.   
  546.     网友: yfydz   时间:2007-11-19 12:36:56 IP地址:218.247.216.★  
  547.       
  548.   
  549. 或者说dst_entry/xfrm_dst又是什么东西?  
  550.   
  551.   
  552.     网友: zetalog     时间:2007-11-20 11:27:13 IP地址:218.81.225.★  
  553.       
  554.   
  555. 安全关联束(Security Association Bundle)是一个SA序列,传输必须通过它处理以满足一个安全策略。组成束的SA可以终止于不同端点。  
  556.   
  557.   
  558.     网友: Zetalog     时间:2007-11-20 11:29:39 IP地址:218.81.225.★  
  559.       
  560.   
  561. 我再来提个小意见。  
  562.   
  563. struct xfrm_policy  
  564.   
  565. {  
  566.   
  567.  struct xfrm_policy *next; // 下一个策略  
  568.   
  569. next是不要的,我保证你去掉它可以编译通过,策略存储是通过byidx和bydst还有inexact哈希表完成的。这些哈希表都是动态哈希表,会根据节点数量的多少自动增加。  
  570.   
  571. next留在那里一定是改造不彻底,我打算发个patch去。  
  572.   
  573.   
  574.     网友: Zetalog     时间:2007-11-20 11:33:17 IP地址:218.81.225.★  
  575.       
  576.   
  577. 我再来补充一下SA bundle。  
  578.   
  579. RFC2401定义了组成SA bundle的几种方式:  
  580.   
  581. 传输邻接(transport adjacency),只能是AH应用于ESP输出,其他方式没有意义。  
  582.   
  583. 迭代隧道(iterated tunneling):允许多重迭代,仅road warrior和VPN两种情况需要支持。  
  584.   
  585. 隧道模式和传输模式两种方式也可以被任意组合。  
  586.   
  587.   
  588.     网友: Zetalog     时间:2007-11-20 11:44:44 IP地址:218.81.225.★  
  589.       
  590.   
  591. 根据RFC2401定义,策略必须有一个参数用来表示报文的流向。  
  592.   
  593. 为什么xfrm_policy里面没有呢?其实index的第三位就是方向。  
  594.   
  595.   
  596.     网友: yfydz   时间:2007-11-20 12:34:14 IP地址:218.247.216.★  
  597.       
  598.   
  599. 你说的没错,但RFC只定义了SA bundle的形式,却没限制这个bundle是如何实现的. xfrm的实现就是扩展了路由dst_entry为xfrm_dst,这个xfrm_dst的in/output函数就是IPSEC的解封/加封操作,通过dst链表实现bundle的处理.不要一提路由就立即为就是发送数据包,我在该系列后面文章也详细分析了这个路由链的处理,这里直接称其为路由是透过现象说本质的说法,当然如果是其他方式的实现,当然就不会称其为路由  
  600.   
  601.   
  602.     网友: Zetalog     时间:2007-11-20 12:41:17 IP地址:218.81.225.★  
  603.       
  604.   
  605. 这么说可以理解了,呵呵。  
  606.   
  607.   
  608.     网友: yfydz   时间:2007-11-20 13:23:22 IP地址:218.247.216.★  
  609.       
  610.   
  611. 由此就可以把xfrm和klips归为一类,都是靠路由来实现安全策略的,如果从FW+VPN角度说,FW的访问控制策略和VPN连接就需要分开定义的,VPN只处理点到点。而以前用过checkpoint的FW,可以在访问控制策略的动作中定义加密,也就是IPSEC封装,这说明其SA bundle应该和路由没关系,所以强调这点也是在区分不同的IPSEC的实现流派.  
  612.   
  613.   
  614.     网友: Zetalog     时间:2007-11-20 16:25:57 IP地址:218.81.225.★  
  615.       
  616.   
  617. 我这样理解不知道是否可以:  
  618.   
  619. 在报文进行路由处理的时候,xfrm_lookup会被调用。在xfrm_lookup处理中,如果对当前的传输流有对应的policy(可能是sk_policy也可能是一般的policy),则查找dst_entry中是否缓存过IPsec处理的表项。如果没有,则根据policy的xfrm_tmpl解析出一个SA bundle,并且将它创建为dst_entry并缓存在bundle成员中,这个新创建或者查找到的dst_entry挂载在插入点中(xfrm_lookup)传入的dst_p。这样当报文发送的时候外出处理的回调就会被调用到。不知道是不是这样的?好像您在该系列的第三篇里面有描述,不过跟我现在看的git_kernel的代码有些不同。  
  620.   
  621.   
  622.     网友: Zetalog     时间:2007-11-20 16:34:40 IP地址:218.81.225.★  
  623.       
  624.   
  625. 如果我的理解正确,bundle里面只是缓存了跟IPsec处理相关的处理项,其它路由项还是在__xfrm_lookup函数的传入参数的dst_p所关联的另一个链表中中。所以xfrm_policy的成员bundle就是RFC2401描述的那个SPD表项必然实现的SA bundle缓存。  
  626.   
  627.   
  628.     网友: Zetalog     时间:2007-11-20 16:46:19 IP地址:218.81.225.★  
  629.       
  630.   
  631. 我是对着RFC2401在看xfrm_policy。RFC描述SPD表项必须要有以下参数:  
  632.   
  633. 流向:linux的dir应该在index里面了  
  634.   
  635. 动作:linux应该就是action  
  636.   
  637. 有序:linux应该是priority  
  638.   
  639. 由选择符索引:linux中应该是family和selector,因为xfrm_address_t没有协议族,所以xfrm里面到处都要family  
  640.   
  641. 有一个外出处理SA bundle缓存:linux就是bundle  
  642.   
  643. 有一个管理接口(xfrm_mgr)  
  644.   
  645. 主机端允许、用户对单独的流修改策略(sk_policy)  
  646.   
  647. 允许SA选择继承SPD表项还是传输流的选择子,好像linux实现在试验这个功能,在XFRM_SUB_POLICY有效时能看到相关代码。  
  648.   
  649. 。。。。。。  
  650.   
  651.   
  652.     网友: Zetalog     时间:2007-11-20 17:04:46 IP地址:218.81.225.★  
  653.       
  654.   
  655. 呵呵,我有点追求名字了。  
  656.   
  657. 本质上说Linux就是路由型的IPsec处理。  
  658.   
  659.   
  660.     网友: yfydz   时间:2007-11-21 12:40:58 IP地址:218.247.216.★  
  661.       
  662.   
  663. 基本就是这样吧  
  664.   
  665.   
  666.     网友: zetalog     时间:2007-11-21 20:53:31 IP地址:58.33.88.★  
  667.       
  668.   
  669. 楼主,你好。  
  670.   
  671. 我这两天一直在分析xfrm代码,今天的总体感觉xfrm里面dst_entry好像还是用来实现PMTUD对应的功能。  
  672.   
  673. 在xfrm_state里面有一个genid参数,当新的SA加入时候会调用__xfrm_state_bump_genids把所有目标源地址相同的SA(他们的路由也应该一样)的genid改成一样。xfrm_dst里面也有genid。看到注释中说好像也和PMTUD相关的。不过实在没看明白是干吗的。不知道楼主对genid了解吗?  
  674.   
  675.   
  676.     网友: yfydz   时间:2007-11-23 11:06:37 IP地址:218.247.216.★  
  677.       
  678.   
  679. xfrm_dst里的genid和xfrm_state的没关系,前者只是flow的ID,因为是路由,xfrm_dst也是flow的一种  
  680.   
  681.   
  682.     网友: 本站网友    时间:2008-03-22 12:07:41 IP地址:202.198.16.★  
  683.       
  684.   
  685. 斑竹你好,想把red算法的平均队列,瞬时队列,以及时间作为日志输出到一文件中,却不知怎么下手,请指点....  
  686.   
  687.   
  688.     网友: _Lightsky_  时间:2008-04-01 10:27:31 IP地址:222.88.1.★  
  689.       
  690.   
  691. 这些天一直在阅读XFRM里的源代码,却发现里面全是.h和.C,找不到调用的源头在那里?指点一下!谢谢了!  
  692.   
  693.   
  694.     网友: _Lightsky_  时间:2008-04-01 10:30:52 IP地址:222.88.1.★  
  695.       
  696.   
  697. XFRM里面有一个USER,好像是调用的接口,但不知道编程的时候该怎么调用,不知道楼主有没有相关的文档?  
  698.   
  699.   
  700.     网友: _Lightsky_  时间:2008-04-01 11:05:18 IP地址:222.88.1.★  
  701.       
  702.   
  703. 我的邮箱是yangzhongxiqq@163.com,谢谢帮助啊!你的邮箱呢?  
  704.   
  705.   
  706.     网友: yfydz   时间:2008-04-02 13:11:39 IP地址:218.247.216.★  
  707.       
  708.   
  709. 看最新的iproute2代码,就是用户层接口  
  • 0
    点赞
  • 0
    评论
  • 7
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值