Yukun Zhang(张玉昆)@Sun Microsystems

I am a software member of Solaris core technologies engaged in networking virtualization.
The weblog is dedicated to Solaris adaption.

All | Industry | Life | Networking | Solaris

« Previous month (Sep 2006) | Main | Next month (Nov 2006) »
20061104 Saturday November 04, 2006

Solaris 网络虚拟化: Firewall 部分 Solaris 的 Containers(AKA zones) 的模型 在 Solaris 10 中就出现了, CPU, 内存,Disk 空间的虚拟化已经可以提供出基本的 OS 级的虚拟环境, 但是网络部分还是没能完善。 Solaris 10 的zone 提供了独立的name space(logic IP 地址, TCP/UDP/SCTP 端口, ), 但是基本的说, 一个系统中 Zones 共享这一个 TCP/IP 协议栈。 - Routing - ARP - Firewall policy - Statitics 都是共享着的, 这也就意味着: - Zone 与 Zone 之间有安全漏洞: 一个Zone 的网络配置和信息可能(或一定)为别的Zone 开到 - 配置问题: 为 一个 Zone 做配置(如路由配置)可能会使得别的zone 也受影响甚至不能工作 The Old Solaris 10 Network Model Zone A Zone B +_________________++________________ | APPLICATION || APPLICATION | | || | | TCP UDP || TCP UDP | |_________________||________________| __________|________________|________ | | | IP/ARP/IPSEC/Firewall | |___________________________________| ______|_______ _____|______ | NIC1 | | NIC2 | |------------| |----------| The New Solaris 10 Network Model Zone A Zone B +_________________++________________ | APPLICATION | | APPLICATION | | | | | | TCP UDP | | TCP UDP | |_________________| |________________| __________|________ ________|_______ | | | | | IP/ARP/ | | IP/ARP/ | | IPSEC/Firewall | | IPSEC/Firewall | |_________________| |________________| ______|_______ _____|______ | NIC1 | | NIC2 | |------------| |----------| 我设计和实现了Solaris Firewall 的虚拟化。 Soaris 的 Firewall 有 pfhook framework(neti 和 hook) 以及 firewall 引擎 ipf 组成。 Architecture: IP +---------+ module: neti Firewall | | +----------------------------------------------+ +-----------+ | | | | | | | | | | | | | | | | | | | | -----------> net_register/unregister | | | | | net_lookup <------ | | | | net_release | | | | | | | | | | net_walk | | | | | | | | | | -----------> net_register_family/unregister | | | | | -----------> net_register_event/unregister | | | | | \ \ net_register_hook/unregister <------ | | | \-- | | | | | | | | \ | net_getifname <------ | | | | \ | net_getmtu <------ | | | | \ | net_getpmtuenabled <------ | | | | | | net_lifaddr <------ | | | | \ | net_phygetnext <------ | | | | \ | net_phylookup <------ | | | | \ | net_lifgetnext <------ | | | | \ | net_inject <------ | | | | \ | net_routeto <------ | | | | | | net_ispartialchecksum <------ | | | | | | net_isvalidchecksum <------ | | | | \ | | | | | | | \| | | | | | +-------------------^^^^^----------------------+ | | | | || | (neti, hook interaction) | | | | module: hook || | | | | | +-------------------<<>>|----------------------+ | | | | | | | | | | -----------> hook_run | | | | | | | | | | | +----------------------------------------------+ +-----------+ | | +---------+ Note: A few external functions in module hook called by neti hook_family_add/remove hook_event_add/remove hook_register/unregister The steps: 1. neti, and hook initialization 2. ip stack in ip_ddi_init - call ip_neti_init() - call net_register(&ipv4info) - call net_register(&ipv6info) - create task queue for eventq_queue_out eventq_queue_in eventq_queue_nic - call ipv4_hook_init() - call net_register_family(ipv4, &ipv4root) - call net_register_event(ipv4, &ip4_physical_in_event) - call net_register_event(ipv4, &ip4_physical_out_event) - call net_register_event(ipv4, &ip4_physical_forwarding_event) - call net_register_event(ipv4, &ip4_loopback_in_event) - call net_register_event(ipv4, &ip4_loopback_out_event) - call net_register_event(ipv4, &ip4_nic_events) - call ipv6_hook_init() - call net_register_family(ipv6, &ipv6root) - call net_register_event(ipv6, &ip6_physical_in_event) - call net_register_event(ipv6, &ip6_physical_out_event) - call net_register_event(ipv6, &ip6_physical_forwarding_event) - call net_register_event(ipv6, &ip6_loopback_in_event) - call net_register_event(ipv6, &ip6_loopback_out_event) - call net_register_event(ipv6, &ip6_nic_events) 3. arp - call arp_hook_init() - call net_register_family(arp, &arproot) - call net_register_event(arp, &arp_physical_in_event) - call net_register_event(arp, &arp_physical_out_event) - call net_register_event(arp, &arp_nic_events) 4. ipf iplattach: - ipf_ipv4 = net_lookup(NHF_INET); - net_register_hook(ipf_ipv4, NH_NIC_EVENTS, &ipfhook_nicevents) - net_register_hook(ipf_ipv4, NH_PHYSICAL_IN, &ipfhook_in) - net_register_hook(ipf_ipv4, NH_PHYSICAL_OUT, &ipfhook_out) - net_register_hook(ipf_ipv4, NH_LOOPBACK_IN, &ipfhook_in) - net_register_hook(ipf_ipv4, NH_LOOPBACK_OUT, &ipfhook_out) - ipf_ipv6 = net_lookup(NHF_INET6); - net_register_hook(ipf_ipv6, NH_NIC_EVENTS, &ipfhook_nicevents) - net_register_hook(ipf_ipv6, NH_PHYSICAL_IN, &ipfhook_in) - net_register_hook(ipf_ipv6, NH_PHYSICAL_OUT, &ipfhook_out) - net_register_hook(ipf_ipv6, NH_LOOPBACK_IN, &ipfhook_in) - net_register_hook(ipf_ipv6, NH_LOOPBACK_OUT, &ipfhook_out) 5. - when packets come in/out, nic event happens, IP calls hook_run() The data structures relationship looks like: netd_head -- \ \ net_data_t(ip4) ip6 arp \ ->+------------+ ---------> +------------+ -------------> +------------+ \ |net_info | |net_info | |net_info | | | | | | | | | | netd_hooks___ | netd_hooks___ | netd_hooks___ | +------------+ \ +------------+ \ +------------+ \ | neti \ \ \ / | | | / | | | / | | | | | | | | | \|/ \|/ \|/ \ familylist -------> +----------+ ----------> +----------+ -------------> +----------+ \ | | | | | | \ | | | | | | | hook_family_int_t | ____ | | | | | +----------+ \ +----------+ +----------+ | \ | +------+ | hook_event_int_t | |-------+----+ hook_int_t | hook | | | | | +------+ +----+ | | | | | +------+ | hook_event_int_t | |-------+----+ hook_int_t | | | | | | +------+ +----+ | | | | | +------+ | hook_event_int_t | |-------+----+ hook_int_t / | | | | / +------+ +----+ / 虚拟化之后的过程是: 1. kernel module neti: has the neti_stack_t, and neti_stack_init(), which malloc the local storage; 2. kernel module hook has the hook_stack_t, and hook_stack_init(), which malloc the local storage; 3. arp module changes: move the following from arp_ddi_init to arp_stack_init - call arp_neti_init(as) - call net_register(&arpinfo) - call arp_hook_init() - call net_register_family(arp, &arproot) - call net_register_event(arp, &arp_physical_in_event) - call net_register_event(arp, &arp_physical_out_event) - call net_register_event(arp, &arp_nic_events) 4. ip module: Move the following from ip_ddi_init to ip_stack_init, to make the - call ip_neti_init(pfs) - call net_register(&ipv4info) - call net_register(&ipv6info) - create task queue for eventq_queue_out eventq_queue_in eventq_queue_nic - call ipv4_hook_init() - call net_register_family(ipv4, &ipv4root) - call net_register_event(ipv4, &ip4_physical_in_event) - call net_register_event(ipv4, &ip4_physical_out_event) - call net_register_event(ipv4, &ip4_physical_forwarding_event) - call net_register_event(ipv4, &ip4_loopback_in_event) - call net_register_event(ipv4, &ip4_loopback_out_event) - call net_register_event(ipv4, &ip4_nic_events) - call ipv6_hook_init() - call net_register_family(ipv6, &ipv6root) - call net_register_event(ipv6, &ip6_physical_in_event) - call net_register_event(ipv6, &ip6_physical_out_event) - call net_register_event(ipv6, &ip6_physical_forwarding_event) - call net_register_event(ipv6, &ip6_loopback_in_event) - call net_register_event(ipv6, &ip6_loopback_out_event) - call net_register_event(ipv6, &ip6_nic_events) 下面的函数接口增加了一个 netstack_t * net_register(..., netstack_t *) net_lookup(..., netstack_t *) net_walk(..., netstack_t *) 其他函数保持不变: net_unregister(...) net_release(...) net_register_family(...) net_unregister_family(...) net_register_family(...) net_unregister_family(...) net_register_hook(...) net_unregister_hook(...) net_getifname(...) net_getmtu(...) net_getpmtuenabled(...) net_lifaddr(...) net_phygetnext(...) net_phylookup(...) net_lifgetnext(...) net_inject(...) net_routeto(...) net_ispartialchecksum(...) net_isvalidchecksum(...) 相应的这些数据结构和原型也有了一些变化: ------------------------------------------------------------------------------------- Old: 118 typedef struct net_info { 119 int neti_version; 120 char *neti_protocol; 121 int (*neti_getifname)(phy_if_t, char *, const size_t); 122 int (*neti_getmtu)(phy_if_t, lif_if_t); 123 int (*neti_getpmtuenabled)(void); 124 int (*neti_getlifaddr)(phy_if_t, lif_if_t, size_t, 125 net_ifaddr_t [], void *); 126 phy_if_t (*neti_phygetnext)(phy_if_t); 127 phy_if_t (*neti_phylookup)(const char *); 128 lif_if_t (*neti_lifgetnext)(phy_if_t, lif_if_t); 129 int (*neti_inject)(inject_t, net_inject_t *); 130 phy_if_t (*neti_routeto)(struct sockaddr *); 131 int (*neti_ispartialchecksum)(mblk_t *); 132 int (*neti_isvalidchecksum)(mblk_t *); 133 } net_info_t; New: 118 typedef struct net_info { 119 int neti_version; 120 char *neti_protocol; 121 int (*neti_getifname)(phy_if_t, char *, const size_t, netstack_t*); 122 int (*neti_getmtu)(phy_if_t, lif_if_t); 123 int (*neti_getpmtuenabled)(netstack_t *); 124 int (*neti_getlifaddr)(phy_if_t, lif_if_t, size_t, 125 net_ifaddr_t [], void *); 126 phy_if_t (*neti_phygetnext)(phy_if_t, netstack_t *); 127 phy_if_t (*neti_phylookup)(const char *, netstack_t *); 128 lif_if_t (*neti_lifgetnext)(phy_if_t, lif_if_t); 129 int (*neti_inject)(inject_t, net_inject_t *, netstack_t *); 130 phy_if_t (*neti_routeto)(struct sockaddr *, netstack_t *); 131 int (*neti_ispartialchecksum)(mblk_t *); 132 int (*neti_isvalidchecksum)(mblk_t *); 133 } net_info_t; ------------------------------------------------------------------------------------- Old: 139 struct net_data { 140 LIST_ENTRY(net_data) netd_list; 141 net_info_t netd_info; 142 int netd_refcnt; 143 hook_family_int_t *netd_hooks; 144 }; New: 139 struct net_data { 140 LIST_ENTRY(net_data) netd_list; 141 net_info_t netd_info; 142 int netd_refcnt; 143 hook_family_int_t *netd_hooks; 144 void * netd_netstack; 145 }; 146 ------------------------------------------------------------------------------------- Old: 147 typedef struct injection_s { 148 net_inject_t inj_data; 149 boolean_t inj_isv6; 150 } injection_t; New: 148 typedef struct injection_s { 149 net_inject_t inj_data; 150 boolean_t inj_isv6; 151 void * inj_ptr; 152 } injection_t; ------------------------------------------------------------------------------------- Old: 165 extern net_data_t net_register(const net_info_t *); New: 180 extern net_data_t net_register(const net_info_t *, netstack_t *); ------------------------------------------------------------------------------------- Old: 167 extern net_data_t net_lookup(const char *); New: 182 extern net_data_t net_lookup(const char *, netstack_t *); ------------------------------------------------------------------------------------- Old: 169 extern net_data_t net_walk(net_data_t); New: 184 extern net_data_t net_walk(net_data_t, netstack_t *); ( Nov 04 2006, 05:18:37 AM EST ) Permalink


Today's Page Hits: 20