0%

前言

不管引入什么概念,什么算法,密码的核心永远不变
让原文获得密文容易,没有key的帮助反向解密出原文并正确很难
各种算法/机制都是在加强这句话

传输安全的目标:在不可靠的信道中建立可靠通讯

传输安全的三个要素:加密+校验+基于证书的身份识别机制,缺一不可

  • 真实数据不会被看到:需要加解密
  • 数据不被篡改:需要完整性校验
  • 确定对端的真实身份:防止中间人攻击
阅读全文 »

LVS(linux virtual server) 做网关的几种转发模式

DR(direct routing)

路由收包后先给到同vlan的LB,LB根据负载均衡策略选择后端X,将dest mac改为X的mac地址,src-mac为网关mac。用于X的回程
核心一点:RS和LVS都使用同一个入口VIP,初次收包LVS改MAC发给RS,RS的dest-ip也是LVS的dest-ip。

linux/net/netfilter/ipvs/ip_vs_xmit.c at 7e46731ed902354a86caf3510011eb2b827a8f73 · taikulawo/linux · GitHub
dpvs
neigh_output
neigh_fill_mac

优势:

阅读全文 »

tcp rev + tcp syn send

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
__dev_xmit_skb (\root\codes\kernel-dev\linux\net\core\dev.c:3760)
__dev_queue_xmit (\root\codes\kernel-dev\linux\net\core\dev.c:4310)
dev_queue_xmit (\root\codes\kernel-dev\linux\include\linux\netdevice.h:3082)
neigh_hh_output (\root\codes\kernel-dev\linux\include\net\neighbour.h:529)
neigh_output (\root\codes\kernel-dev\linux\include\net\neighbour.h:543)
ip_finish_output2 (\root\codes\kernel-dev\linux\net\ipv4\ip_output.c:238)
__ip_finish_output (\root\codes\kernel-dev\linux\net\ipv4\ip_output.c:0)
NF_HOOK_COND (\root\codes\kernel-dev\linux\include\linux\netfilter.h:293)
ip_output (\root\codes\kernel-dev\linux\net\ipv4\ip_output.c:439)
dst_output (\root\codes\kernel-dev\linux\include\net\dst.h:458)
ip_local_out (\root\codes\kernel-dev\linux\net\ipv4\ip_output.c:128)
__ip_queue_xmit (\root\codes\kernel-dev\linux\net\ipv4\ip_output.c:543)
ip_queue_xmit (\root\codes\kernel-dev\linux\net\ipv4\ip_output.c:557)
__tcp_transmit_skb (\root\codes\kernel-dev\linux\net\ipv4\tcp_output.c:1415)
__tcp_send_ack (\root\codes\kernel-dev\linux\net\ipv4\tcp_output.c:4082)
tcp_send_ack (\root\codes\kernel-dev\linux\net\ipv4\tcp_output.c:4088)
tcp_rcv_synsent_state_process (\root\codes\kernel-dev\linux\net\ipv4\tcp_input.c:6363)
tcp_rcv_state_process (\root\codes\kernel-dev\linux\net\ipv4\tcp_input.c:6539)
tcp_v4_do_rcv (\root\codes\kernel-dev\linux\net\ipv4\tcp_ipv4.c:1751)
tcp_v4_rcv (\root\codes\kernel-dev\linux\net\ipv4\tcp_ipv4.c:2150)
ip_protocol_deliver_rcu (\root\codes\kernel-dev\linux\net\ipv4\ip_input.c:205)
ip_local_deliver_finish (\root\codes\kernel-dev\linux\net\ipv4\ip_input.c:233)
NF_HOOK (\root\codes\kernel-dev\linux\include\linux\netfilter.h:304)
ip_local_deliver (\root\codes\kernel-dev\linux\net\ipv4\ip_input.c:254)
dst_input (\root\codes\kernel-dev\linux\include\net\dst.h:468)
ip_sublist_rcv_finish (\root\codes\kernel-dev\linux\net\ipv4\ip_input.c:580)
ip_list_rcv_finish (\root\codes\kernel-dev\linux\net\ipv4\ip_input.c:631)
ip_sublist_rcv (\root\codes\kernel-dev\linux\net\ipv4\ip_input.c:639)
ip_list_rcv (\root\codes\kernel-dev\linux\net\ipv4\ip_input.c:674)
__netif_receive_skb_list_ptype (\root\codes\kernel-dev\linux\net\core\dev.c:5570)
__netif_receive_skb_list_core (\root\codes\kernel-dev\linux\net\core\dev.c:5618)
__netif_receive_skb_list (\root\codes\kernel-dev\linux\net\core\dev.c:5670)
netif_receive_skb_list_internal (\root\codes\kernel-dev\linux\net\core\dev.c:5761)
gro_normal_list (\root\codes\kernel-dev\linux\include\net\gro.h:439)
napi_complete_done (\root\codes\kernel-dev\linux\net\core\dev.c:6101)
e1000_clean (\root\codes\kernel-dev\linux\drivers\net\ethernet\intel\e1000\e1000_main.c:3811)
__napi_poll (\root\codes\kernel-dev\linux\net\core\dev.c:6531)
napi_poll (\root\codes\kernel-dev\linux\net\core\dev.c:6598)
net_rx_action (\root\codes\kernel-dev\linux\net\core\dev.c:6731)
__do_softirq (\root\codes\kernel-dev\linux\kernel\softirq.c:553)
invoke_softirq (\root\codes\kernel-dev\linux\kernel\softirq.c:427)
__irq_exit_rcu (\root\codes\kernel-dev\linux\kernel\softirq.c:632)
irq_exit_rcu (\root\codes\kernel-dev\linux\kernel\softirq.c:644)
sysvec_apic_timer_interrupt (\root\codes\kernel-dev\linux\arch\x86\kernel\apic\apic.c:1074)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
static inline struct sock *__inet_lookup(struct net *net,
struct inet_hashinfo *hashinfo,
struct sk_buff *skb, int doff,
const __be32 saddr, const __be16 sport,
const __be32 daddr, const __be16 dport,
const int dif, const int sdif,
bool *refcounted)
{
u16 hnum = ntohs(dport);
struct sock *sk;

sk = __inet_lookup_established(net, hashinfo, saddr, sport,
daddr, hnum, dif, sdif);
*refcounted = true;
if (sk)
return sk;
*refcounted = false;
return __inet_lookup_listener(net, hashinfo, skb, doff, saddr,
sport, daddr, hnum, dif, sdif);
}

到TCP层后,skb需要转换成 struct sock,从 kernel 协议栈查找skb -> struct sk 映射

阅读全文 »

目标:

分析 kernel 驱动收到后skb

1. 如何唤醒epoll callback?
2. accpet syscall 如何从listener socket spawn 子 socket?

一个极简epoll server程序(无法编译,只说明流程)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 创建listener socket
int listener_fd = socket();
bind(listener_fd);
listen(listener_fd);
set_socket_non_blocking(listener_fd);

// 创建socket
ep = epoll_create1(0);
struct epoll_event event;
event.data.fd = listener_fd;
event.events = EPOLLIN | EPOLLET;
// 将listener socket注册进epoll
s = epoll_ctl(efd, EPOLL_CTL_ADD, sfd, &event);
for ( ;; ) {
// eventloop
int n = epoll_wait(ep, &events, 1024, -1);
for (itn i = 0; i < n ; i ++) {
if(events[i].data.fd == listener_fd) {
// new incoming connection
int child = accept(listener_fd, &addr, &addr_len);
// 将子连接socket加入epoll eventloop
make_socket_non_blocking(infd);
struct epoll_event;
event.data.fd = infd;
event.events = EPOLLIN | EPOLLET;
s = epoll_ctl(ep, EPOLL_CTL_ADD, child, &event);
}
}
}

epoll 注册 wake callback

阅读全文 »

以联发科 mt7921 无线网卡驱动为例

kernel mt7921/ 下有pci,usb接口的驱动,usb接口驱动入口是usb.c。手里有mt7921芯片的USB无线网卡,对应的驱动为mt7921u

pci驱动为 mt7921e
USB接口 MT7921 外观

PCI接口的MT7921网卡外观

阅读全文 »

WI-FI 如何传输数据

无线通讯通过电磁波完成,发送端通过电流转换成电磁场,电磁场产生无线电波在空间中传递。利用这现象,将信息调制到无线电波上发送。计算机领域中,信息就是 0/1,通过电磁波的带宽表示(也可以用电磁波其他的概念组合表示,不一定是是带宽)

接收端利用电磁感应原理,通过解调还原成最初的数据,所以 WI-FI 设备都带天线,天线

数据在传输中,发送器会在天线上施加电流,施加的时变电压或时变电流而产生辐射的电磁场,使得电流的能量转变成无线电波。在接收时,天线会由于电场的感应,而在天线内部产生时变电流,并在其终端产生时变电压,产生电讯号经过处理之后,可以在接收器中观察或收听。天线被广泛应用于广播、点对点无线电通讯、雷达和太空探索等通讯系统。天线是无线电通讯系统中的必需组件。

维基百科对无线电通讯有个大体介绍

阅读全文 »

驱动层

驱动向内核注册 softirq,里面包含回调函数。驱动收到数据触发中断,kernel读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
__netif_receive_skb_list_ptype(struct net_device * orig_dev, struct packet_type * pt_prev, struct list_head * head) (/data00/codes/linux/net/core/dev.c:5533)
__netif_receive_skb_list_core(struct list_head * head, bool pfmemalloc) (/data00/codes/linux/net/core/dev.c:5582)
__netif_receive_skb_list(struct list_head * head) (/data00/codes/linux/net/core/dev.c:5634)
netif_receive_skb_list_internal(struct list_head * head) (/data00/codes/linux/net/core/dev.c:5725)
gro_normal_list(struct napi_struct * napi) (/data00/codes/linux/include/net/gro.h:433)
gro_normal_list(struct napi_struct * napi) (/data00/codes/linux/include/net/gro.h:429)
napi_complete_done(struct napi_struct * n, int work_done) (/data00/codes/linux/net/core/dev.c:6065)
e1000_clean(struct napi_struct * napi, int budget) (/data00/codes/linux/drivers/net/ethernet/intel/e1000/e1000_main.c:3811)
__napi_poll(struct napi_struct * n, bool * repoll) (/data00/codes/linux/net/core/dev.c:6496)
napi_poll(struct list_head * repoll, struct napi_struct * n) (/data00/codes/linux/net/core/dev.c:6563)
net_rx_action(struct softirq_action * h) (/data00/codes/linux/net/core/dev.c:6696)
__do_softirq() (/data00/codes/linux/kernel/softirq.c:571)
do_softirq() (/data00/codes/linux/kernel/softirq.c:472)
do_softirq() (/data00/codes/linux/kernel/softirq.c:459)

NAPI

基于已有thread_struct封装的新的任务调度库

阅读全文 »

工作中涉及Nginx module开发,分析Nginx/tengine代码

nginx modules初始化

每个 module 必须有 ngx_module_t,且在module不同生命周期都支持 hook 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
struct ngx_module_s {
ngx_uint_t ctx_index;
ngx_uint_t index;

char *name;

ngx_uint_t spare0;
ngx_uint_t spare1;

ngx_uint_t version;
const char *signature;

void *ctx;
ngx_command_t *commands;
ngx_uint_t type;

ngx_int_t (*init_master)(ngx_log_t *log);

ngx_int_t (*init_module)(ngx_cycle_t *cycle);

ngx_int_t (*init_process)(ngx_cycle_t *cycle);
ngx_int_t (*init_thread)(ngx_cycle_t *cycle);
void (*exit_thread)(ngx_cycle_t *cycle);
void (*exit_process)(ngx_cycle_t *cycle);

void (*exit_master)(ngx_cycle_t *cycle);

uintptr_t spare_hook0;
uintptr_t spare_hook1;
uintptr_t spare_hook2;
uintptr_t spare_hook3;
uintptr_t spare_hook4;
uintptr_t spare_hook5;
uintptr_t spare_hook6;
uintptr_t spare_hook7;
};

由于 ngx_module_t 为基础类型,对于http和stream,通过 ngx_module_t#ctx进行了扩展,用于放置 http/stream module相关的 hook 函数

阅读全文 »

shadowsocks 协议分析

基础知识

nonce 和 salt 区别

salt 只用一次,用于生成 cipher,和 salt 类似的概念叫initial vector(初始化向量),可认为 salt 和 iv 是等价的概念。

nonce 每次 encrypt,decrypt都需要,而且 decrypt 时使用的nonce必须和那次encrypt的nonce一致。由于加解密的nonce必须一一对应,所以nonce往往采用双方提前约定的生成规则,一般都是每次使用完自加1,为下次使用做准备

阅读全文 »