Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add SRC-MAC rule #1406

Open
wants to merge 3 commits into
base: Alpha
Choose a base branch
from
Open

feat: add SRC-MAC rule #1406

wants to merge 3 commits into from

Conversation

mlkt
Copy link

@mlkt mlkt commented Jul 24, 2024

Add SRC-MAC matching rule.

It can match the MAC address of the device from which the request originates to carry out the diversion, and set different rules for different devices in the router.
The MAC address separator can be either : or -

IPv4 and IPv6 are supported.

rules:
  - SRC-MAC,e4:fd:34:49:c5:78,DIRECT
  - SRC-MAC,e4:ea:bb:e3:5e:90,PROXY
  - SRC-MAC,66-aa-3d-4f-e7-ef,PROXY

增加 SRC-MAC 匹配规则。
可以匹配请求来源设备MAC地址来进行分流,比如若用在路由器中可对不同设备设置不同的规则。
MAC地址分隔符用 :- 均可。

支持 Linux & Windows,支持IPv4 & IPv6。

@wwqgtxx
Copy link
Collaborator

wwqgtxx commented Jul 24, 2024

@mlkt 不会合并这种采用cmd输出解析的实现方式,linux和win上均有原生api可以实现获取的方式

@mlkt
Copy link
Author

mlkt commented Jul 25, 2024

之前用C写过通过请求连接的fd获取mac的

u_int64_t getpeermac(int sockfd, const char* dev_name) {
	u_int64_t mac = 0;
	struct arpreq arpreq;
	struct sockaddr_in dstadd_in;
	bzero(&arpreq, sizeof(arpreq)), bzero(&dstadd_in, sizeof(dstadd_in));
	socklen_t len = sizeof(struct sockaddr_in);
	if (getpeername(sockfd, (struct sockaddr*) &dstadd_in, &len) == 0) {
		memcpy(&arpreq.arp_pa, &dstadd_in, len);
		strcpy(arpreq.arp_dev, dev_name);
		arpreq.arp_pa.sa_family = AF_INET;
		arpreq.arp_ha.sa_family = AF_UNSPEC;
		if (ioctl(sockfd, SIOCGARP, &arpreq) == 0) {
			memcpy(&mac, arpreq.arp_ha.sa_data, ETH_ALEN);
		}
	}
	return mac;
}

但是go无法直接获取请求的socket,只能根据IP去查ARP表,我查了下windows要用 getIpNetTable2这个函数,但调起来很麻烦,用chatgpt生成了一百多行。

linux没找到可以直接用的接口,然后我去查了ip命令它自己怎么实现的,好像必须得用 socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE) 内核通信,而且似乎必须得root权限。找到个go的封装库 vishvananda/netlink 可以直接调,但其实就和直接调 ip 命令也差不多,还是得处理缓存,只是不依赖外部进程。

现在这样直接调命令的方式其实是最简单的了...

@wwqgtxx
Copy link
Collaborator

wwqgtxx commented Jul 25, 2024

实际上你需要的getIpNetTable2封装在 https://github.com/situation-sh/situation/tree/main/modules/arp 有别人完整实现过了,改动一下移植过来就行
至于netlink,vishvananda/netlink本来就在依赖项中,只不过用的是fork后的sagernet/netlink,而且还能配合netlink.NeighSubscribe做自动更新,不需要手动轮训

@mlkt
Copy link
Author

mlkt commented Jul 25, 2024

6,原来还有这种东西,那我再研究一下

@wwqgtxx wwqgtxx force-pushed the Alpha branch 4 times, most recently from c5a4a91 to c830b8a Compare July 28, 2024 03:00
@douglarek
Copy link

douglarek commented Aug 2, 2024

我查了下windows要用 getIpNetTable2这个函数,但调起来很麻烦,用chatgpt生成了一百多行。

src-mac 没必要支持 linux/mac 之外的 os,它的意义应该仅限于路由系统。

@mlkt
Copy link
Author

mlkt commented Aug 3, 2024

@douglarek
src-mac 没必要支持 linux/mac 之外的 os,它的意义应该仅限于路由系统。

运行在Windows上时,如果通过socks等入站连接,这个规则也是有意义的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants