Skip to content

Instantly share code, notes, and snippets.

@keegoo
Last active August 27, 2022 16:10
Show Gist options
  • Save keegoo/25ad3e01e416bb597725c0b4c9dfef68 to your computer and use it in GitHub Desktop.
Save keegoo/25ad3e01e416bb597725c0b4c9dfef68 to your computer and use it in GitHub Desktop.
记录如何写一个http proxy in Rust的学习笔记

Briefing

在Mac和Linux下感觉没有好用的http capture的工具。

其实需求很简单:可以monitor某个ip,监控其中发生的http的traffice,并实时的在Web UI中显示出来。

用过Windows平台的Fiddler,感觉非常易用。

想用Rust来写,不过之前对于Rust和网络编程都没有什么经验。

用此gist来一步一步的记录整个学习过程。

2022年6月20号,新加坡。

@keegoo
Copy link
Author

keegoo commented Jun 30, 2022

才知道:

  • ifconfig早晚有一天要被ip替换掉
  • netstat已经被ss替换掉了

还是要对socket底层的东西有所了解,不然每次碰到address family,protocol,socket都不知道具体是什么关系。摘自The Open Group Base Specifications Issue 6.

(可能翻译的不准确)

所有的网络协议(protocol)都会关联到一个具体的address family。每个address family都会提供一些基础的services来支持协议(protocol)在特定网络设备中的具体实现。这些services包括packet fragmentation and reassembly, routing, addressing, and basic transport. 所以一个address family会包含多个protocols,每个protocol会对应到一个socket type。。。

...所有的network address都有一个通用的格式,叫sockaddr,被定义在sys/socket.h的文件中。然而每个address family都会在此基础上引入各自不同的结构。。。The field sa_family in the sockaddr structure contains the address family identifier, specifying the format of the sa_data area.

例如下面的例子,来自socket.h:

struct sockaddr {
	sa_family_t	sa_family;	/* address family, AF_xxx	*/
	char		sa_data[14];	/* 14 bytes of protocol address	*/
};

Socket有四种类型:SOCK_STREAM, SOCK_SEQPACKET, SOCK_DGRAM, and SOCK_RAW。

其中SOCK_STREAMSOCK_SEQPACKEt功能相似,提供reliable, sequenced, full-duplex octet streams between the socket and a peer to which the socket is connected. 这里应该就是指TCP那种面向连接的。SOCK_DGRAMSOCK_RAW比较相似,supports connectionless data transfer which is not necessarily acknowledged or reliable. 这里应该是指UDP那种没有链接的。

关于socket()函数。

int socket(int domain, int type, int protocol);

// domain
//     Specifies the address family used in the communications domain.
//     e.g.
//         AF_INET - Internet IP Protocol.
//         AF_INET6 - IP version 6.
//         AF_UNIX - Unix domain sockets.
//         大概还有100多个AF。。。
// type
//     Specifies the type of socket to be created.
// protocol
//     Specifies a particular protocol to be used with the socket.
//     e.g.
//         TCP
//         UDP
//         IIP
//         Internet Control Message Protocol (ICMP)

@keegoo
Copy link
Author

keegoo commented Aug 24, 2022

程序是从run_scapy开始的。

$ sudo ./run_scapy -H
# Welcome to Scapy (2.4.4.dev221)

run_scapy -> SCAPY/__init__.py -> SCAPY/main.py,可以看到所有传给run_scapy的arguments最终都是在main.py中的interact()函数处理的。 所以从interact()看起。

@keegoo
Copy link
Author

keegoo commented Aug 24, 2022

interact()做了一下几件事:

  • parse and check arguments with getopt.
  • init_session()。将libs/all.py中的所有modules都读取到SESSION中。同时加入config的信息,SESSION = {"conf": conf}。其中SESSION是一个dictionary。
  • 千方百计的要在终端上打出一个logo,logo的大小会根据终端的column来决定。
  • 打开一个可以交互的console。使用code.interact(banner=banner_text, local=SESSION),因为SESSION中存了scapy中所有的modules,所以可以直接在这个console中使用这些模块了。

@keegoo
Copy link
Author

keegoo commented Aug 27, 2022

上面提到./run_scapy会启动一个可交互的console,下面是一个如何在console中操作数据包的例子:

send(IP(dst="1.2.3.4")/TCP(dport=502, options=[("MSS", 0)]))

其中

  • IP和TCP都是class,定义在scapy/layers/inet.py中。
  • send应该是定义在scapy/sendrecv.py中。

(to be continue ...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment