混拨节点适配
This commit is contained in:
68
README.md
68
README.md
@@ -1,3 +1,71 @@
|
|||||||
|
## 部署流程
|
||||||
|
|
||||||
|
**参数**
|
||||||
|
|
||||||
|
- 默认网关
|
||||||
|
- 公网 CIDR
|
||||||
|
- 内网 CIDR
|
||||||
|
- RADIUS 配置
|
||||||
|
- NAT 网关
|
||||||
|
- 节点 IP 池
|
||||||
|
- 节点地区编号
|
||||||
|
- 城市数量
|
||||||
|
- 窗口数量
|
||||||
|
- 连接报告地址
|
||||||
|
- 日志报告地址
|
||||||
|
|
||||||
|
**配置网络**
|
||||||
|
|
||||||
|
刷新 mac 地址(手动)
|
||||||
|
|
||||||
|
默认网关(手动 [默认网关])
|
||||||
|
|
||||||
|
wan 口 ip(手动 [公网 CIDR])
|
||||||
|
|
||||||
|
lan 口 ip([内网 CIDR])
|
||||||
|
|
||||||
|
**配置 vpn**
|
||||||
|
|
||||||
|
地址池(172.17.0.0/16)
|
||||||
|
|
||||||
|
ppp profile(本地地址,地址池)
|
||||||
|
|
||||||
|
pptp & l2tp & sstp 服务端(profile)
|
||||||
|
|
||||||
|
ppp secrets & radius([RADIUS 配置])
|
||||||
|
|
||||||
|
路由表,默认路由,路由策略(default => [NAT 网关],172.17.0.0/16 => vpn)
|
||||||
|
|
||||||
|
**配置 nat**
|
||||||
|
|
||||||
|
ospf 路由表,黑洞路由([节点 IP 池])
|
||||||
|
|
||||||
|
实例,区域,模板;在 lan 上的 area0 区域重分发黑洞路由表上的静态路由区域
|
||||||
|
|
||||||
|
**配置脚本**
|
||||||
|
|
||||||
|
上线脚本:
|
||||||
|
- 删除旧 nat 规则
|
||||||
|
- 根据[节点地区编号],[城市数量],[窗口数量]生成 ipv4 地址生成 snat 规则(172.16.x.x => 10.i.j.k)
|
||||||
|
- 上报开始占用
|
||||||
|
|
||||||
|
下线脚本:
|
||||||
|
- 删除旧 nat 规则
|
||||||
|
- 上报解除占用
|
||||||
|
|
||||||
|
清理超时连接(9 小时):
|
||||||
|
- 查找并删除在线超过 24 小时的连接
|
||||||
|
|
||||||
|
报告用户在线数量(5 分钟):
|
||||||
|
- 查找并上报用户在线数量
|
||||||
|
|
||||||
|
配置脚本调度
|
||||||
|
挂载上下线脚本到 ppp profile
|
||||||
|
|
||||||
|
**配置日志**
|
||||||
|
|
||||||
|
上报到远程地址
|
||||||
|
|
||||||
## 单地区
|
## 单地区
|
||||||
|
|
||||||
### 添加 ros 后应该改什么
|
### 添加 ros 后应该改什么
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
index,name,code,gateway,public,mask,private,domain,cert
|
index,name,code,gateway,public,mask,private,domain,cert
|
||||||
|
0,混拨1,hh1,43.226.58.1,43.226.58.9,24,192.168.98.1,hh,server.9.crt
|
||||||
1,宣城,ahxc215,43.226.58.1,43.226.58.10,24,192.168.99.1,ahxc,server.crt
|
1,宣城,ahxc215,43.226.58.1,43.226.58.10,24,192.168.99.1,ahxc,server.crt
|
||||||
2,宿州,ahsz216,43.226.58.1,43.226.58.11,24,192.168.99.2,ahsz,server.crt
|
2,宿州,ahsz216,43.226.58.1,43.226.58.11,24,192.168.99.2,ahsz,server.crt
|
||||||
3,阜阳,ahfy225,43.226.58.1,43.226.58.12,24,192.168.99.3,ahfy,server.crt
|
3,阜阳,ahfy225,43.226.58.1,43.226.58.12,24,192.168.99.3,ahfy,server.crt
|
||||||
|
21
config.csv
21
config.csv
@@ -1,21 +1,2 @@
|
|||||||
index,name,code,gateway,public,mask,private,domain,cert
|
index,name,code,gateway,public,mask,private,domain,cert
|
||||||
51,宁波,zjnb138,43.226.58.1,43.226.58.60,24,192.168.99.51,zjnb,server.60.crt
|
0,混拨1,hh1,43.226.58.1,43.226.58.9,24,192.168.98.1,hh,server.9.crt
|
||||||
52,杭州,zjhz143,43.226.58.1,43.226.58.61,24,192.168.99.52,zjhz,server.61.crt
|
|
||||||
53,绍兴,zjsx136,43.226.58.1,43.226.58.62,24,192.168.99.53,zjsx,server.62.crt
|
|
||||||
54,丽水,zjls139,43.226.58.1,43.226.58.63,24,192.168.99.54,zjls,server.63.crt
|
|
||||||
55,温州,zjwz134,43.226.58.1,43.226.58.64,24,192.168.99.55,zjwz,server.64.crt
|
|
||||||
56,湖州,zjhz142,43.226.58.1,43.226.58.65,24,192.168.99.56,zjhuz,server.65.crt
|
|
||||||
57,舟山,zjzs133,43.226.58.1,43.226.58.66,24,192.168.99.57,zjzs,server.66.crt
|
|
||||||
58,衢州,zjqz137,43.226.58.1,43.226.58.67,24,192.168.99.58,zjqz,server.67.crt
|
|
||||||
59,金华,zjjh140,43.226.58.1,43.226.58.68,24,192.168.99.59,zjjh,server.68.crt
|
|
||||||
60,海口,hnhk172,43.226.58.1,43.226.58.69,24,192.168.99.60,hnhk,server.69.crt
|
|
||||||
61,文昌,hnwc170,43.226.58.1,43.226.58.70,24,192.168.99.61,hnwc,server.70.crt
|
|
||||||
62,三亚,hnsy171,43.226.58.1,43.226.58.71,24,192.168.99.62,hnsya,server.71.crt
|
|
||||||
63,上海,sh130,43.226.58.1,43.226.58.72,24,192.168.99.63,sh,server.72.crt
|
|
||||||
64,昆明,ynkm144,43.226.58.1,43.226.58.73,24,192.168.99.64,ynkm,server.73.crt
|
|
||||||
65,呼和浩特,nmghhht192,43.226.58.1,43.226.58.74,24,192.168.99.65,nmghhht,server.74.crt
|
|
||||||
66,赤峰,nmgcf194,43.226.58.1,43.226.58.75,24,192.168.99.66,nmgcf,server.75.crt
|
|
||||||
67,鄂尔多斯,nmgeeds193,43.226.58.1,43.226.58.76,24,192.168.99.67,nmgeeds,server.76.crt
|
|
||||||
68,通辽,nmgtl190,43.226.58.1,43.226.58.77,24,192.168.99.68,nmgtl,server.77.crt
|
|
||||||
69,包头,nmgbt195,43.226.58.1,43.226.58.78,24,192.168.99.69,nmgbt,server.78.crt
|
|
||||||
70,呼伦贝尔,nmghlbe191,43.226.58.1,43.226.58.79,24,192.168.99.70,nmghlbe,server.79.crt
|
|
||||||
|
336
main.py
336
main.py
@@ -1,9 +1,10 @@
|
|||||||
import re
|
|
||||||
from librouteros import connect,Api
|
from librouteros import connect,Api
|
||||||
import csv
|
import csv
|
||||||
import ssl
|
import ssl
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
|
from steps import *
|
||||||
|
|
||||||
'''
|
'''
|
||||||
自动配置 ros 脚本,需要安装 librouteros 库:
|
自动配置 ros 脚本,需要安装 librouteros 库:
|
||||||
|
|
||||||
@@ -27,6 +28,12 @@ pip install librouteros
|
|||||||
threads = []
|
threads = []
|
||||||
failed = []
|
failed = []
|
||||||
|
|
||||||
|
# 配置执行步骤
|
||||||
|
steps = [
|
||||||
|
configLogs
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# 加载配置文件
|
# 加载配置文件
|
||||||
config_data = []
|
config_data = []
|
||||||
@@ -68,337 +75,18 @@ def start(config):
|
|||||||
ssl_wrapper=ctx.wrap_socket,
|
ssl_wrapper=ctx.wrap_socket,
|
||||||
)
|
)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
failed.append((config, err))
|
failed.append((config, f'连接失败: {err}'))
|
||||||
return
|
return
|
||||||
|
|
||||||
# 配置 ros
|
# 配置 ros
|
||||||
try:
|
try:
|
||||||
addDrop(conn, config)
|
for step in steps:
|
||||||
|
step(conn, config)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
failed.append((config, err))
|
failed.append((config, f'配置失败: {err}'))
|
||||||
|
|
||||||
# 关闭连接
|
# 关闭连接
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
|
||||||
def configDefault(conn:Api,config):
|
|
||||||
configNet(conn, config)
|
|
||||||
configOuts(conn, config)
|
|
||||||
configScripts(conn, config)
|
|
||||||
|
|
||||||
|
|
||||||
def configNet(conn:Api,config):
|
|
||||||
'''
|
|
||||||
配置网络
|
|
||||||
'''
|
|
||||||
|
|
||||||
# 配置路由
|
|
||||||
routes = conn.path('ip', 'route')
|
|
||||||
for route in routes:
|
|
||||||
if route['routing-table'] == '1':
|
|
||||||
try:
|
|
||||||
routes.update(**{
|
|
||||||
'.id': route['.id'],
|
|
||||||
'gateway': config['gateway']
|
|
||||||
})
|
|
||||||
except Exception as e:
|
|
||||||
print('更新默认路由失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 配置地址
|
|
||||||
addrs = conn.path('ip', 'address')
|
|
||||||
for addr in addrs:
|
|
||||||
if addr['interface'] == 'lan':
|
|
||||||
try:
|
|
||||||
addrs.update(**{
|
|
||||||
'.id': addr['.id'],
|
|
||||||
'address': config['private']
|
|
||||||
})
|
|
||||||
except Exception as e:
|
|
||||||
print('更新 WAN 地址失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 刷新 mac 地址
|
|
||||||
eths = conn.path('interface', 'ethernet')
|
|
||||||
for eth in eths:
|
|
||||||
if eth['name'] == 'lan':
|
|
||||||
tuple(eths('reset-mac-address', **{
|
|
||||||
'.id': eth['.id']
|
|
||||||
}))
|
|
||||||
|
|
||||||
def configOuts(conn:Api,config):
|
|
||||||
'''
|
|
||||||
配置 vpn 出口负载均衡
|
|
||||||
'''
|
|
||||||
count = 20
|
|
||||||
|
|
||||||
# 配置 ppp
|
|
||||||
ppps = conn.path('interface', 'l2tp-client')
|
|
||||||
|
|
||||||
# 删除旧的 ppp
|
|
||||||
for ppp in ppps:
|
|
||||||
if ppp['name'].startswith('l2tp-out'):
|
|
||||||
try:
|
|
||||||
ppps.remove(ppp['.id'])
|
|
||||||
except Exception as e:
|
|
||||||
print('删除 PPP 失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 添加新的 ppp
|
|
||||||
for i in range(1, count+1):
|
|
||||||
ppps.add(**{
|
|
||||||
'name':'l2tp-out{}'.format(i),
|
|
||||||
'connect-to':'192.168.25{}.25{}'.format((i-1)%3+1, (i-1)%3+1),
|
|
||||||
'user':'jdzz{}dt{}'.format(i, config['index']),
|
|
||||||
'password':'123231',
|
|
||||||
'disabled':'no',
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
# 配置路由
|
|
||||||
routes = conn.path('ip', 'route')
|
|
||||||
|
|
||||||
# 删除旧的路由表
|
|
||||||
for route in routes:
|
|
||||||
if str(route['routing-table']).startswith('r'):
|
|
||||||
try:
|
|
||||||
routes.remove(route['.id'])
|
|
||||||
except Exception as e:
|
|
||||||
print('删除路由表失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
# 添加新的路由表
|
|
||||||
for i in range(1,count+1):
|
|
||||||
routeName = 'r{}'.format(i)
|
|
||||||
routeOut = 'l2tp-out{}'.format(i)
|
|
||||||
try:
|
|
||||||
routes.add(**{
|
|
||||||
'dst-address': '0.0.0.0/0',
|
|
||||||
'gateway': routeOut,
|
|
||||||
'routing-table': routeName,
|
|
||||||
})
|
|
||||||
except Exception as e:
|
|
||||||
print('添加路由表失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
def configScripts(conn:Api,config):
|
|
||||||
'''
|
|
||||||
配置脚本
|
|
||||||
'''
|
|
||||||
|
|
||||||
scripts = conn.path('system', 'script')
|
|
||||||
for script in scripts:
|
|
||||||
if script['name'] == 'up':
|
|
||||||
with open('scripts/up.rsc', 'rb') as file:
|
|
||||||
upScript = str(file.read(), encoding='utf-8')
|
|
||||||
scripts.update(**{
|
|
||||||
'.id': script['.id'],
|
|
||||||
'source': upScript
|
|
||||||
})
|
|
||||||
elif script['name'] == 'down':
|
|
||||||
with open('scripts/down.rsc', 'rb') as file:
|
|
||||||
downScript = str(file.read(), encoding='utf-8')
|
|
||||||
scripts.update(**{
|
|
||||||
'.id': script['.id'],
|
|
||||||
'source': downScript
|
|
||||||
})
|
|
||||||
elif script['name'] == 'onlinestatus':
|
|
||||||
with open('scripts/onlinestatus.rsc', 'rb') as file:
|
|
||||||
onlineStatusScript = str(file.read(), encoding='utf-8')
|
|
||||||
scripts.update(**{
|
|
||||||
'.id': script['.id'],
|
|
||||||
'source': onlineStatusScript.replace('<IP>', config['public'])
|
|
||||||
})
|
|
||||||
elif script['name'] == 'pppoestatus':
|
|
||||||
with open('scripts/pppoestatus.rsc', 'rb') as file:
|
|
||||||
pppoeStatusScript = str(file.read(), encoding='utf-8')
|
|
||||||
scripts.update(**{
|
|
||||||
'.id': script['.id'],
|
|
||||||
'source': pppoeStatusScript.replace('<IP>', config['public'])
|
|
||||||
})
|
|
||||||
|
|
||||||
def configLogs(conn:Api,config):
|
|
||||||
'''
|
|
||||||
配置日志处理
|
|
||||||
'''
|
|
||||||
|
|
||||||
# 添加日志过滤器
|
|
||||||
filters = conn.path('ip', 'firewall', 'filter')
|
|
||||||
for filter in filters:
|
|
||||||
if filter['comment'] == 'natlog':
|
|
||||||
try:
|
|
||||||
filters.remove(filter['.id'])
|
|
||||||
except Exception as e:
|
|
||||||
print('删除过滤器失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
filters.add(**{
|
|
||||||
'chain': 'forward',
|
|
||||||
'action': 'log',
|
|
||||||
'comment': 'natlog',
|
|
||||||
'dst-address': '10.0.0.0/8',
|
|
||||||
'protocol': 'tcp',
|
|
||||||
'connection-nat-state': 'srcnat',
|
|
||||||
'tcp-flags': 'syn',
|
|
||||||
})
|
|
||||||
|
|
||||||
filters.add(**{
|
|
||||||
'chain': 'forward',
|
|
||||||
'action': 'log',
|
|
||||||
'comment': 'natlog',
|
|
||||||
'src-address': '10.0.0.0/8',
|
|
||||||
'protocol': 'udp',
|
|
||||||
'dst-port': '!53',
|
|
||||||
'connection-nat-state': '!srcnat',
|
|
||||||
})
|
|
||||||
|
|
||||||
# 添加日志动作
|
|
||||||
actions = conn.path('system', 'logging', 'action')
|
|
||||||
|
|
||||||
for action in actions:
|
|
||||||
if action['name'] in ['logremote', 'logremoteidc']:
|
|
||||||
try:
|
|
||||||
actions.remove(action['.id'])
|
|
||||||
except Exception as e:
|
|
||||||
print('删除日志动作失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
actions.add(**{
|
|
||||||
'name': 'logremote',
|
|
||||||
'target': 'remote',
|
|
||||||
'src-address': '0.0.0.0',
|
|
||||||
'remote': '106.119.167.38',
|
|
||||||
'remote-port': '5775',
|
|
||||||
})
|
|
||||||
|
|
||||||
actions.add(**{
|
|
||||||
'name': 'logremoteidc',
|
|
||||||
'target': 'remote',
|
|
||||||
'src-address': '0.0.0.0',
|
|
||||||
'remote': '192.168.100.255',
|
|
||||||
'remote-port': '5775',
|
|
||||||
})
|
|
||||||
|
|
||||||
# 配置日志动作
|
|
||||||
logs = conn.path('system', 'logging')
|
|
||||||
|
|
||||||
for log in logs:
|
|
||||||
if 'firewall' in log['topics'] and 'info' in log['topics']:
|
|
||||||
try:
|
|
||||||
logs.remove(log['.id'])
|
|
||||||
except Exception as e:
|
|
||||||
print('删除日志配置失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
logs.add(**{
|
|
||||||
'topics': 'firewall,info',
|
|
||||||
'prefix': config['code'],
|
|
||||||
'action': 'logremote',
|
|
||||||
})
|
|
||||||
|
|
||||||
logs.add(**{
|
|
||||||
'topics': 'firewall,info',
|
|
||||||
'prefix': config['code'],
|
|
||||||
'action': 'logremoteidc',
|
|
||||||
})
|
|
||||||
|
|
||||||
def addDrop(conn:Api, config):
|
|
||||||
'''
|
|
||||||
添加丢弃规则
|
|
||||||
'''
|
|
||||||
|
|
||||||
domains = [
|
|
||||||
'kasut.org',
|
|
||||||
'chigua41.xyz',
|
|
||||||
'chigua35.info',
|
|
||||||
'chigua32.life',
|
|
||||||
'iufsvayufgiwlj6ok.com',
|
|
||||||
'kaixr.top',
|
|
||||||
'qiopqc.cn',
|
|
||||||
'lsdhgsduyccnja18.com',
|
|
||||||
'tongyan01.club',
|
|
||||||
'nenmei37.club',
|
|
||||||
'69lesbi.com',
|
|
||||||
'ero-labs.cool',
|
|
||||||
'soxue100.com',
|
|
||||||
'24news.world',
|
|
||||||
'aaa215.click',
|
|
||||||
'qqqqqdfggjkgfgfhe.cc',
|
|
||||||
'lovefootjob.com',
|
|
||||||
'hadesex.com',
|
|
||||||
]
|
|
||||||
|
|
||||||
ips = [
|
|
||||||
'23.231.144.26',
|
|
||||||
'23.231.183.17',
|
|
||||||
'23.231.182.57',
|
|
||||||
'23.231.182.56',
|
|
||||||
'154.92.94.91',
|
|
||||||
'154.92.94.163',
|
|
||||||
'192.250.241.167',
|
|
||||||
'192.250.192.242',
|
|
||||||
]
|
|
||||||
|
|
||||||
# 非法网站列表
|
|
||||||
layer7 = conn.path('ip', 'firewall', 'layer7-protocol')
|
|
||||||
|
|
||||||
for item in layer7:
|
|
||||||
if item['name'] == 'illegal':
|
|
||||||
try:
|
|
||||||
layer7.remove(item['.id'])
|
|
||||||
except Exception as e:
|
|
||||||
print('删除 Layer7 规则失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
layer7.add(**{
|
|
||||||
'name': 'illegal',
|
|
||||||
'regexp': f'({"|".join([re.escape(domain) for domain in domains])})[/:]?.*',
|
|
||||||
})
|
|
||||||
|
|
||||||
# 非法 IP 列表
|
|
||||||
addressLists = conn.path('ip', 'firewall', 'address-list')
|
|
||||||
for item in addressLists:
|
|
||||||
if item['list'] == 'illegal':
|
|
||||||
try:
|
|
||||||
ips.remove(item['address'])
|
|
||||||
except Exception as e:
|
|
||||||
continue
|
|
||||||
|
|
||||||
for ip in ips:
|
|
||||||
addressLists.add(**{
|
|
||||||
'list': 'illegal',
|
|
||||||
'address': ip,
|
|
||||||
})
|
|
||||||
|
|
||||||
# 添加丢弃规则
|
|
||||||
filters = conn.path('ip', 'firewall', 'filter')
|
|
||||||
|
|
||||||
for item in filters:
|
|
||||||
if item['comment'] == 'drop illegal websites':
|
|
||||||
try:
|
|
||||||
filters.remove(item['.id'])
|
|
||||||
except Exception as e:
|
|
||||||
print('删除过滤器失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
elif item['comment'] == 'drop illegal ips':
|
|
||||||
try:
|
|
||||||
filters.remove(item['.id'])
|
|
||||||
except Exception as e:
|
|
||||||
print('删除过滤器失败: {}'.format(e))
|
|
||||||
continue
|
|
||||||
|
|
||||||
filters.add(**{
|
|
||||||
'chain': 'forward',
|
|
||||||
'action': 'drop',
|
|
||||||
'layer7-protocol': 'illegal',
|
|
||||||
'comment': 'drop illegal websites',
|
|
||||||
})
|
|
||||||
|
|
||||||
filters.add(**{
|
|
||||||
'chain': 'forward',
|
|
||||||
'action': 'drop',
|
|
||||||
'src-address-list': 'illegal',
|
|
||||||
'comment': 'drop illegal ips',
|
|
||||||
})
|
|
||||||
|
|
||||||
main()
|
main()
|
||||||
16
scripts/down_ppp.rsc
Normal file
16
scripts/down_ppp.rsc
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
:log debug "用户 $"remote-address" 下线"
|
||||||
|
|
||||||
|
# 删除旧的分配规则
|
||||||
|
:local "snat-address" [/ip/firewall/nat/get [find src-address $"remote-address"] to-addresses]
|
||||||
|
/ip/firewall/nat/remove [find where src-address $"remote-address"]
|
||||||
|
|
||||||
|
:log debug "删除旧的 nat 规则"
|
||||||
|
|
||||||
|
# 上报调度服务
|
||||||
|
:local edge ($"snat-address"&0.0.0.255<<8)
|
||||||
|
:local city (($"snat-address"&0.0.255.0>>8)+1)
|
||||||
|
:local localip (172.16.0.0|$edge|$city)
|
||||||
|
|
||||||
|
:log debug "上报到调度服务 http://192.168.250.250:18702/server/ros/down/ip/$localip"
|
||||||
|
/tool fetch url="http://192.168.250.250:18702/server/ros/down/ip/$localip" mode=http
|
||||||
|
/file remove "$localip"
|
||||||
26
scripts/up_ppp.rsc
Normal file
26
scripts/up_ppp.rsc
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
:log debug "用户 $"remote-address" 上线"
|
||||||
|
|
||||||
|
# 删除旧的分配规则
|
||||||
|
/ip/firewall/nat/remove [find where src-address $"remote-address"]
|
||||||
|
|
||||||
|
:log debug "删除旧的 nat 规则"
|
||||||
|
|
||||||
|
# 分配出口 IP
|
||||||
|
:local RosIndex [/system/script/environment/get RosIndex value]
|
||||||
|
:local CityCount [/system/script/environment/get CityCount value]
|
||||||
|
:local EdgeCount [/system/script/environment/get EdgeCount value]
|
||||||
|
|
||||||
|
:local edge [:rndnum from=1 to=$EdgeCount]
|
||||||
|
:local city [:rndnum from=2 to=$CityCount]
|
||||||
|
:local "snat-address" "10.$RosIndex.$city.$edge"
|
||||||
|
|
||||||
|
/ip/firewall/nat/add chain=srcnat src-address=$"remote-address" action=src-nat to-addresses=$"snat-address" comment="snat $"remote-address" => $"snat-address""
|
||||||
|
|
||||||
|
:log debug "添加新的 nat 规则 snat $"remote-address" => $"snat-address""
|
||||||
|
|
||||||
|
# 上报调度服务
|
||||||
|
:local cityP ($city + 1)
|
||||||
|
:local localip "172.16.$edge.$cityP"
|
||||||
|
:log debug "上报到调度服务 http://192.168.250.250:18702/server/ros/up/ip/$localip"
|
||||||
|
/tool/fetch url="http://192.168.250.250:18702/server/ros/up/ip/$localip" mode=http
|
||||||
|
/file remove "$localip"
|
||||||
322
steps.py
Normal file
322
steps.py
Normal file
@@ -0,0 +1,322 @@
|
|||||||
|
import re
|
||||||
|
from librouteros import connect,Api
|
||||||
|
|
||||||
|
def configDefault(conn:Api,config):
|
||||||
|
configNet(conn, config)
|
||||||
|
configOuts(conn, config)
|
||||||
|
configScripts(conn, config)
|
||||||
|
|
||||||
|
|
||||||
|
def configNet(conn:Api,config):
|
||||||
|
'''
|
||||||
|
配置网络
|
||||||
|
'''
|
||||||
|
|
||||||
|
# 配置路由
|
||||||
|
routes = conn.path('ip', 'route')
|
||||||
|
for route in routes:
|
||||||
|
if route['routing-table'] == '1':
|
||||||
|
try:
|
||||||
|
routes.update(**{
|
||||||
|
'.id': route['.id'],
|
||||||
|
'gateway': config['gateway']
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
print('更新默认路由失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 配置地址
|
||||||
|
addrs = conn.path('ip', 'address')
|
||||||
|
for addr in addrs:
|
||||||
|
if addr['interface'] == 'lan':
|
||||||
|
try:
|
||||||
|
addrs.update(**{
|
||||||
|
'.id': addr['.id'],
|
||||||
|
'address': config['private']
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
print('更新 WAN 地址失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 刷新 mac 地址
|
||||||
|
eths = conn.path('interface', 'ethernet')
|
||||||
|
for eth in eths:
|
||||||
|
if eth['name'] == 'lan':
|
||||||
|
tuple(eths('reset-mac-address', **{
|
||||||
|
'.id': eth['.id']
|
||||||
|
}))
|
||||||
|
|
||||||
|
def configOuts(conn:Api,config):
|
||||||
|
'''
|
||||||
|
配置 vpn 出口负载均衡
|
||||||
|
'''
|
||||||
|
count = 20
|
||||||
|
|
||||||
|
# 配置 ppp
|
||||||
|
ppps = conn.path('interface', 'l2tp-client')
|
||||||
|
|
||||||
|
# 删除旧的 ppp
|
||||||
|
for ppp in ppps:
|
||||||
|
if ppp['name'].startswith('l2tp-out'):
|
||||||
|
try:
|
||||||
|
ppps.remove(ppp['.id'])
|
||||||
|
except Exception as e:
|
||||||
|
print('删除 PPP 失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 添加新的 ppp
|
||||||
|
for i in range(1, count+1):
|
||||||
|
ppps.add(**{
|
||||||
|
'name':'l2tp-out{}'.format(i),
|
||||||
|
'connect-to':'192.168.25{}.25{}'.format((i-1)%3+1, (i-1)%3+1),
|
||||||
|
'user':'jdzz{}dt{}'.format(i, config['index']),
|
||||||
|
'password':'123231',
|
||||||
|
'disabled':'no',
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# 配置路由
|
||||||
|
routes = conn.path('ip', 'route')
|
||||||
|
|
||||||
|
# 删除旧的路由表
|
||||||
|
for route in routes:
|
||||||
|
if str(route['routing-table']).startswith('r'):
|
||||||
|
try:
|
||||||
|
routes.remove(route['.id'])
|
||||||
|
except Exception as e:
|
||||||
|
print('删除路由表失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 添加新的路由表
|
||||||
|
for i in range(1,count+1):
|
||||||
|
routeName = 'r{}'.format(i)
|
||||||
|
routeOut = 'l2tp-out{}'.format(i)
|
||||||
|
try:
|
||||||
|
routes.add(**{
|
||||||
|
'dst-address': '0.0.0.0/0',
|
||||||
|
'gateway': routeOut,
|
||||||
|
'routing-table': routeName,
|
||||||
|
})
|
||||||
|
except Exception as e:
|
||||||
|
print('添加路由表失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
def configScripts(conn:Api,config):
|
||||||
|
'''
|
||||||
|
配置脚本
|
||||||
|
'''
|
||||||
|
|
||||||
|
scripts = conn.path('system', 'script')
|
||||||
|
for script in scripts:
|
||||||
|
if script['name'] == 'up':
|
||||||
|
with open('scripts/up.rsc', 'rb') as file:
|
||||||
|
upScript = str(file.read(), encoding='utf-8')
|
||||||
|
scripts.update(**{
|
||||||
|
'.id': script['.id'],
|
||||||
|
'source': upScript
|
||||||
|
})
|
||||||
|
elif script['name'] == 'down':
|
||||||
|
with open('scripts/down.rsc', 'rb') as file:
|
||||||
|
downScript = str(file.read(), encoding='utf-8')
|
||||||
|
scripts.update(**{
|
||||||
|
'.id': script['.id'],
|
||||||
|
'source': downScript
|
||||||
|
})
|
||||||
|
elif script['name'] == 'onlinestatus':
|
||||||
|
with open('scripts/onlinestatus.rsc', 'rb') as file:
|
||||||
|
onlineStatusScript = str(file.read(), encoding='utf-8')
|
||||||
|
scripts.update(**{
|
||||||
|
'.id': script['.id'],
|
||||||
|
'source': onlineStatusScript.replace('<IP>', config['public'])
|
||||||
|
})
|
||||||
|
elif script['name'] == 'pppoestatus':
|
||||||
|
with open('scripts/pppoestatus.rsc', 'rb') as file:
|
||||||
|
pppoeStatusScript = str(file.read(), encoding='utf-8')
|
||||||
|
scripts.update(**{
|
||||||
|
'.id': script['.id'],
|
||||||
|
'source': pppoeStatusScript.replace('<IP>', config['public'])
|
||||||
|
})
|
||||||
|
|
||||||
|
def configLogs(conn:Api,config):
|
||||||
|
'''
|
||||||
|
配置日志处理
|
||||||
|
'''
|
||||||
|
|
||||||
|
# 添加日志过滤器
|
||||||
|
filters = conn.path('ip', 'firewall', 'filter')
|
||||||
|
for filter in filters:
|
||||||
|
if filter['comment'] == 'natlog':
|
||||||
|
try:
|
||||||
|
filters.remove(filter['.id'])
|
||||||
|
except Exception as e:
|
||||||
|
print('删除过滤器失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
filters.add(**{
|
||||||
|
'chain': 'forward',
|
||||||
|
'action': 'log',
|
||||||
|
'comment': 'natlog',
|
||||||
|
'dst-address': '10.0.0.0/8',
|
||||||
|
'protocol': 'tcp',
|
||||||
|
'connection-nat-state': 'srcnat',
|
||||||
|
'tcp-flags': 'syn',
|
||||||
|
})
|
||||||
|
|
||||||
|
filters.add(**{
|
||||||
|
'chain': 'forward',
|
||||||
|
'action': 'log',
|
||||||
|
'comment': 'natlog',
|
||||||
|
'src-address': '10.0.0.0/8',
|
||||||
|
'protocol': 'udp',
|
||||||
|
'dst-port': '!53',
|
||||||
|
'connection-nat-state': '!srcnat',
|
||||||
|
})
|
||||||
|
|
||||||
|
# 添加日志动作
|
||||||
|
actions = conn.path('system', 'logging', 'action')
|
||||||
|
|
||||||
|
for action in actions:
|
||||||
|
if action['name'] in ['logremote', 'logremoteidc']:
|
||||||
|
try:
|
||||||
|
actions.remove(action['.id'])
|
||||||
|
except Exception as e:
|
||||||
|
print('删除日志动作失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
actions.add(**{
|
||||||
|
'name': 'logremote',
|
||||||
|
'target': 'remote',
|
||||||
|
'src-address': '0.0.0.0',
|
||||||
|
'remote': '106.119.167.38',
|
||||||
|
'remote-port': '5775',
|
||||||
|
})
|
||||||
|
|
||||||
|
actions.add(**{
|
||||||
|
'name': 'logremoteidc',
|
||||||
|
'target': 'remote',
|
||||||
|
'src-address': '0.0.0.0',
|
||||||
|
'remote': '192.168.100.255',
|
||||||
|
'remote-port': '5775',
|
||||||
|
})
|
||||||
|
|
||||||
|
# 配置日志动作
|
||||||
|
logs = conn.path('system', 'logging')
|
||||||
|
|
||||||
|
for log in logs:
|
||||||
|
if 'firewall' in log['topics'] and 'info' in log['topics']:
|
||||||
|
try:
|
||||||
|
logs.remove(log['.id'])
|
||||||
|
except Exception as e:
|
||||||
|
print('删除日志配置失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
logs.add(**{
|
||||||
|
'topics': 'firewall,info',
|
||||||
|
'prefix': config['code'],
|
||||||
|
'action': 'logremote',
|
||||||
|
})
|
||||||
|
|
||||||
|
logs.add(**{
|
||||||
|
'topics': 'firewall,info',
|
||||||
|
'prefix': config['code'],
|
||||||
|
'action': 'logremoteidc',
|
||||||
|
})
|
||||||
|
|
||||||
|
def addDrop(conn:Api, config):
|
||||||
|
'''
|
||||||
|
添加丢弃规则
|
||||||
|
'''
|
||||||
|
|
||||||
|
domains = [
|
||||||
|
'kasut.org',
|
||||||
|
'chigua41.xyz',
|
||||||
|
'chigua35.info',
|
||||||
|
'chigua32.life',
|
||||||
|
'iufsvayufgiwlj6ok.com',
|
||||||
|
'kaixr.top',
|
||||||
|
'qiopqc.cn',
|
||||||
|
'lsdhgsduyccnja18.com',
|
||||||
|
'tongyan01.club',
|
||||||
|
'nenmei37.club',
|
||||||
|
'69lesbi.com',
|
||||||
|
'ero-labs.cool',
|
||||||
|
'soxue100.com',
|
||||||
|
'24news.world',
|
||||||
|
'aaa215.click',
|
||||||
|
'qqqqqdfggjkgfgfhe.cc',
|
||||||
|
'lovefootjob.com',
|
||||||
|
'hadesex.com',
|
||||||
|
]
|
||||||
|
|
||||||
|
ips = [
|
||||||
|
'23.231.144.26',
|
||||||
|
'23.231.183.17',
|
||||||
|
'23.231.182.57',
|
||||||
|
'23.231.182.56',
|
||||||
|
'154.92.94.91',
|
||||||
|
'154.92.94.163',
|
||||||
|
'192.250.241.167',
|
||||||
|
'192.250.192.242',
|
||||||
|
]
|
||||||
|
|
||||||
|
# 非法网站列表
|
||||||
|
layer7 = conn.path('ip', 'firewall', 'layer7-protocol')
|
||||||
|
|
||||||
|
for item in layer7:
|
||||||
|
if item['name'] == 'illegal':
|
||||||
|
try:
|
||||||
|
layer7.remove(item['.id'])
|
||||||
|
except Exception as e:
|
||||||
|
print('删除 Layer7 规则失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
layer7.add(**{
|
||||||
|
'name': 'illegal',
|
||||||
|
'regexp': f'({"|".join([re.escape(domain) for domain in domains])})[/:]?.*',
|
||||||
|
})
|
||||||
|
|
||||||
|
# 非法 IP 列表
|
||||||
|
addressLists = conn.path('ip', 'firewall', 'address-list')
|
||||||
|
for item in addressLists:
|
||||||
|
if item['list'] == 'illegal':
|
||||||
|
try:
|
||||||
|
ips.remove(item['address'])
|
||||||
|
except Exception as e:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for ip in ips:
|
||||||
|
addressLists.add(**{
|
||||||
|
'list': 'illegal',
|
||||||
|
'address': ip,
|
||||||
|
})
|
||||||
|
|
||||||
|
# 添加丢弃规则
|
||||||
|
filters = conn.path('ip', 'firewall', 'filter')
|
||||||
|
|
||||||
|
for item in filters:
|
||||||
|
if item['comment'] == 'drop illegal websites':
|
||||||
|
try:
|
||||||
|
filters.remove(item['.id'])
|
||||||
|
except Exception as e:
|
||||||
|
print('删除过滤器失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
elif item['comment'] == 'drop illegal ips':
|
||||||
|
try:
|
||||||
|
filters.remove(item['.id'])
|
||||||
|
except Exception as e:
|
||||||
|
print('删除过滤器失败: {}'.format(e))
|
||||||
|
continue
|
||||||
|
|
||||||
|
filters.add(**{
|
||||||
|
'chain': 'forward',
|
||||||
|
'action': 'drop',
|
||||||
|
'layer7-protocol': 'illegal',
|
||||||
|
'comment': 'drop illegal websites',
|
||||||
|
})
|
||||||
|
|
||||||
|
filters.add(**{
|
||||||
|
'chain': 'forward',
|
||||||
|
'action': 'drop',
|
||||||
|
'src-address-list': 'illegal',
|
||||||
|
'comment': 'drop illegal ips',
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user