一般流量分析系统可以记录主机间的访问关系,比如态势感知系统。通过分析流量中的源地址和目的地址可以搞清楚主机之间是否有互访关系。
对于没有互访关系的主机,一般可以通过防火墙黑名单的形式禁掉,这样可以最大程度地保护主机的安全。内网主机间因一台主机失陷而殃及池鱼的情况经常发生,所以梳理主机间的访问关系是非常必要的。
如果不想使用态势感知这种非常重的系统,可以通过编写脚本记录数据连接中的目的地址的方式来梳理主机会与哪些目的地址发生关系。
采用轮询的方式,每秒钟遍历一次系统网络连接,将目的IP记录在集合中。为防止脚本退出,可以每轮询30次写一次日志,将集合中的数据序列化后存盘。下次脚本重新运行时通过读档的形式,将数据反序列化,重新加载到集合中。
最终与主机有交互的IP都存在 json 数据文件中,通过文本处理可以对 IP 进行排序或其它后续处理:
网络连接信息通过 python psutil 模块获取,脚本如下:
#!python3
# FileName: net_monitor.py
import
psutil
import
os
import
json
import
atexit
import
time
import
ipaddress
import
sys
from
pprint
import
pprint
def
is_ipv6
(ip_str)
:
try
:
ipaddress.IPv6Address(ip_str)
return
True
except
ipaddress.AddressValueError:
return
False
def
cleanup
()
:
serialize_data(json_file, ipset)
print(
'Saving ...'
)
def
serialize_data
(file_name, my_set)
:
json_data = json.dumps(list(my_set))
# 将 JSON 数据写入文件
with
open(file_name,
'w'
)
as
json_file:
json_file.write(json_data)
def
unserialize_data
(file_name)
:
with
open(file_name,
'r'
)
as
json_file:
loaded_data = json.load(json_file)
return
set(loaded_data)
# 默认数据文件,也可以命令行指定
json_file =
r'd:ipset.json'
# ip 集合
ipset = set()
# 休眠时间,单位:秒
sleep_sec =
1
if
__name__ ==
'__main__'
:
# 命令行指定新的数据文件
if
len(sys.argv) ==
2
:
json_file = sys.argv[
1
]
# 注册清理函数
atexit.register(cleanup)
if
os.path.isfile(json_file):
ipset = unserialize_data(json_file)
count =
0
while
True
:
# 获取当前网络连接信息
network_connections = psutil.net_connections()
for
conn
in
network_connections:
if
conn.laddr
and
conn.raddr:
ip = conn.raddr.ip
# 处理 ipv6
if
is_ipv6(ip):
continue
if
ip
not
in
ipset:
ipset.add(ip)
time.sleep(sleep_sec)
count +=
1
if
count%
30
==
0
:
serialize_data(json_file, ipset)
count =
0
使用时可以在命令行指定 JSON 数据文件位置,也可以不加参数,使用代码中的默认位置。
pyhton3 net_monitor ipset.json
在处理 IP 时,可能会用到的 IP 排序函数:
import
ipaddress
def
sort_ips
(ip_list)
:
# 使用ipaddress.IPv4Address创建IPv4地址对象并排序
sorted_ips = sorted(ipaddress.IPv4Address(ip)
for
ip
in
ip_list)
return
sorted_ips
# 示例列表
ip_list = [
'192.168.1.2'
,
'10.0.0.1'
,
'172.16.0.1'
,
'192.168.0.1'
]
# 对IP地址进行排序
sorted_ips = sort_ips(ip_list)
# 打印排序后的IP地址
for
ip
in
sorted_ips:
print(ip)
在后续处理中,我们可能还要对公网IP和私网IP分开处理,私网IP的判断函数为:
import
ipaddress
def
is_private_ip
(ip_str)
:
try
:
ip = ipaddress.ip_address(ip_str)
return
ip.is_private
except
ValueError:
# 无效的IP地址
return
False
# 示例
ip1 =
'192.168.1.1'
ip2 =
'203.0.113.1'
# 判断是否为私有网络IP地址
print(
f"
{ip1}
is private IP:
{is_private_ip(ip1)}
"
)
print(
f"
{ip2}
is private IP:
{is_private_ip(ip2)}
"
)
需要注意的是,我们常见的私网地址段为:
10.0
.0
.0
-10.255
.255
.255
CIDR
格式:
10.0
.0
.0
/
8
172.16
.0
.0
-172.31
.255
.255
CIDR
格式:
172.16
.0
.0
/
12
192.168
.0
.0
-192.168
.255
.255
CIDR
格式:
192.168
.0
.0
/
16
除了这些我们常见的私网地址,还有一些不常见的,也叫保留地址。与互联网公网地址区分开,这些地址也叫私网地址,它们分别是:
0.0
.
0.0
/
8
-
Current
network (only valid
as
source address)
RFC
1700
100.64
.
0.0
~
100.127
.
255.255
(
100.64
.
0.0
/
10
prefix
) carrier-grade
NAT
communication between service provider and subscribers
127.0
.
0.0
is
reserved
for
loopback and
IPC
on the localhost.
127.0
.
0.1
~
127.255
.
255.254
(
127.0
.
0.0
/
8
) - loopback
IP
addresses (refers to
self
)
RFC
5735
192.0
.
0.0
/
24
- reserved (
IANA
)
RFC
5735
192.88
.
99.0
/
24
-
IPv6
to
IPv4
relay.
RFC
3068
198.18
.
0.0
/
15
- network benchmark tests.
RFC
2544
198.51
.
100.0
/
24
-
TEST
-
NET
-
2
.
RFC
5737
203.0
.
113.0
/
24
-
TEST
-
NET
-
3
.
RFC
5737
224.0
.
0.0
~
239.255
.
255.255
(
224.0
.
0.0
/
4
) reserved
for
multicast addresses.
RFC
3171
240.0
.
0.0
/
4
- reserved (former
Class
E
network)
RFC
1700
255.255
.
255.255
is
the limited broadcast address (limited to all other nodes on the
LAN
)
RFC
919
255
in
any part of the
IP
is
reserved
for
broadcast addressing
0.0
.
0.0
in
routing context means the
default
route (to
"the rest of"
the internet)
RFC
1700
0.0
.
0.0
in
the context of firewalls means
"all addresses of the local machine"
RFC
1700
参考
https:
//www.speedguide.net/ip/203.0.113.5
原文始发于微信公众号(生有可恋):监控主机间的访问关系
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论