iup-nft 0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- iup/__init__.py +5 -0
- iup/config.py +98 -0
- iup/main.py +170 -0
- iup_nft-0.1.dist-info/METADATA +10 -0
- iup_nft-0.1.dist-info/RECORD +8 -0
- iup_nft-0.1.dist-info/WHEEL +5 -0
- iup_nft-0.1.dist-info/entry_points.txt +3 -0
- iup_nft-0.1.dist-info/top_level.txt +1 -0
iup/__init__.py
ADDED
iup/config.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
import configparser
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
SECTION_COMMON = 'common'
|
|
8
|
+
SECTIONS = [SECTION_COMMON]
|
|
9
|
+
|
|
10
|
+
class Config:
|
|
11
|
+
|
|
12
|
+
def __init__(self, config_path=None):
|
|
13
|
+
self.host = '127.0.0.1'
|
|
14
|
+
self.port = 22
|
|
15
|
+
self.username = 'root'
|
|
16
|
+
self.password = '123456'
|
|
17
|
+
self.refresh = True
|
|
18
|
+
|
|
19
|
+
if config_path:
|
|
20
|
+
self.__update(config_path)
|
|
21
|
+
|
|
22
|
+
def update(self, host=None, port=None, username=None, password=None, refresh=None):
|
|
23
|
+
self.host = host
|
|
24
|
+
self.port = port
|
|
25
|
+
self.username = username
|
|
26
|
+
self.password = password
|
|
27
|
+
self.refresh = refresh
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def parser(self):
|
|
31
|
+
parser = configparser.ConfigParser()
|
|
32
|
+
variables = vars(self)
|
|
33
|
+
for section in SECTIONS:
|
|
34
|
+
parser[section] = {}
|
|
35
|
+
for k, v in variables.items():
|
|
36
|
+
if k.startswith('cm'):
|
|
37
|
+
pass
|
|
38
|
+
else:
|
|
39
|
+
parser[SECTION_COMMON].update({k: str(v)})
|
|
40
|
+
return parser
|
|
41
|
+
|
|
42
|
+
def save_to(self, path):
|
|
43
|
+
with open(path, 'w', encoding='utf-8') as f:
|
|
44
|
+
self.parser.write(f)
|
|
45
|
+
|
|
46
|
+
def __update(self, path):
|
|
47
|
+
variables = vars(self)
|
|
48
|
+
parser = configparser.ConfigParser()
|
|
49
|
+
parser.read(path, 'utf-8')
|
|
50
|
+
for section in parser.sections():
|
|
51
|
+
if section in SECTIONS:
|
|
52
|
+
pass
|
|
53
|
+
else:
|
|
54
|
+
# 不要parse 无关的section
|
|
55
|
+
break
|
|
56
|
+
for option in parser.options(section):
|
|
57
|
+
value = parser.get(section, option)
|
|
58
|
+
key = option
|
|
59
|
+
if not self.check_key_valid(key):
|
|
60
|
+
break
|
|
61
|
+
original_value = variables.get(key)
|
|
62
|
+
type_expr = None
|
|
63
|
+
if original_value:
|
|
64
|
+
type_of_original_value = type(original_value)
|
|
65
|
+
if type_of_original_value == str:
|
|
66
|
+
type_expr = 'str'
|
|
67
|
+
if type_expr:
|
|
68
|
+
expr = "self.{} = '{}'".format(key, value)
|
|
69
|
+
else:
|
|
70
|
+
expr = 'self.{} = {}'.format(key, value)
|
|
71
|
+
# print(expr)
|
|
72
|
+
exec(expr)
|
|
73
|
+
|
|
74
|
+
def check_key_valid(self, key):
|
|
75
|
+
variables = vars(self)
|
|
76
|
+
for k, _ in variables.items():
|
|
77
|
+
if k == key:
|
|
78
|
+
return True
|
|
79
|
+
return False
|
|
80
|
+
|
|
81
|
+
def __str__(self) -> str:
|
|
82
|
+
variables = vars(self)
|
|
83
|
+
info = ''
|
|
84
|
+
for k, v in variables.items():
|
|
85
|
+
temp_str = f"{k} = {v}\n"
|
|
86
|
+
type_of_v = type(v)
|
|
87
|
+
if type_of_v == str:
|
|
88
|
+
temp_str = f"{k} = '{v}'\n"
|
|
89
|
+
info += temp_str
|
|
90
|
+
return info[:-1]
|
|
91
|
+
|
|
92
|
+
if __name__ == '__main__':
|
|
93
|
+
path = None
|
|
94
|
+
if len(sys.argv) > 1:
|
|
95
|
+
path = sys.argv[1]
|
|
96
|
+
print('config path:', path)
|
|
97
|
+
test_config = Config(path)
|
|
98
|
+
print(test_config)
|
iup/main.py
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
import argparse
|
|
4
|
+
from os import path
|
|
5
|
+
import re
|
|
6
|
+
import paramiko
|
|
7
|
+
import iup
|
|
8
|
+
from iup.config import Config
|
|
9
|
+
import ipaddress
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
HOSTNAME_PATTERN = r'^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$'
|
|
13
|
+
CMD_TEMPLATE = 'iup {}'
|
|
14
|
+
CMD_DNSMASQ = '/etc/init.d/dnsmasq restart'
|
|
15
|
+
CMD_CHNDNS = '/etc/init.d/chinadns-ng restart'
|
|
16
|
+
MAGIC_STR = "update rule to"
|
|
17
|
+
MAGIC_STR2 = "update blk"
|
|
18
|
+
|
|
19
|
+
def is_domain_name(string: str):
|
|
20
|
+
if re.match(HOSTNAME_PATTERN, string):
|
|
21
|
+
return True
|
|
22
|
+
else:
|
|
23
|
+
return False
|
|
24
|
+
|
|
25
|
+
def is_ip_address(ip_str: str):
|
|
26
|
+
try:
|
|
27
|
+
ip = ipaddress.ip_address(ip_str)
|
|
28
|
+
return ip is not None
|
|
29
|
+
except ValueError:
|
|
30
|
+
return False
|
|
31
|
+
|
|
32
|
+
def parse_host_name(hostname_str: str):
|
|
33
|
+
if is_domain_name(hostname_str) or is_ip_address(hostname_str):
|
|
34
|
+
return hostname_str
|
|
35
|
+
return None
|
|
36
|
+
|
|
37
|
+
def parse_port(port: str):
|
|
38
|
+
if port.isdigit():
|
|
39
|
+
port_num = int(port)
|
|
40
|
+
if port_num > 1 and port_num < 65535:
|
|
41
|
+
return port
|
|
42
|
+
return None
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def parse_yes_or_no(msg: str):
|
|
46
|
+
msg = msg.upper()
|
|
47
|
+
if msg in ['Y', 'YES', 'T', 'TRUE']:
|
|
48
|
+
return True
|
|
49
|
+
if msg in ['N', 'NO', 'F', 'FALSE']:
|
|
50
|
+
return False
|
|
51
|
+
return None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def read_hostname_from_file(path: str):
|
|
55
|
+
hostnames = []
|
|
56
|
+
with open(path, 'r') as f:
|
|
57
|
+
for line in f:
|
|
58
|
+
host_name_str = line.strip()
|
|
59
|
+
if is_domain_name(host_name_str):
|
|
60
|
+
hostnames.append(host_name_str)
|
|
61
|
+
hostnames = list(dict.fromkeys(hostnames))
|
|
62
|
+
return hostnames
|
|
63
|
+
|
|
64
|
+
def load_and_overlay_config() -> Config:
|
|
65
|
+
parser = argparse.ArgumentParser(description='参数说明')
|
|
66
|
+
parser.add_argument("-nr", "--no_refresh", action='store_true', default=False, help="是否刷新")
|
|
67
|
+
parser.add_argument("sources", nargs='+', help='域名或者域名文件路径')
|
|
68
|
+
parser.add_argument(
|
|
69
|
+
"--version",
|
|
70
|
+
action="version",
|
|
71
|
+
version=f"%(prog)s version {iup.__version__} installed in {path.dirname(__file__)}",
|
|
72
|
+
)
|
|
73
|
+
args = parser.parse_args()
|
|
74
|
+
config_path = path.join(path.dirname(__file__), 'config.ini')
|
|
75
|
+
if not path.exists(config_path):
|
|
76
|
+
gen_config()
|
|
77
|
+
print('当前配置文件路径为:', config_path)
|
|
78
|
+
config = Config(config_path)
|
|
79
|
+
if args.no_refresh:
|
|
80
|
+
config.refresh = False
|
|
81
|
+
print('是否重启相关服务:', config.refresh)
|
|
82
|
+
return args.sources, config
|
|
83
|
+
|
|
84
|
+
def update_rule_by_ssh(hostnames: list, config: Config):
|
|
85
|
+
need_restart_dns = False
|
|
86
|
+
need_restart_cdns = False
|
|
87
|
+
ssh = paramiko.SSHClient()
|
|
88
|
+
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
89
|
+
ssh.connect(config.host, port=config.port, username=config.username, password=config.password)
|
|
90
|
+
for hostname in hostnames:
|
|
91
|
+
cmd = CMD_TEMPLATE.format(hostname)
|
|
92
|
+
_, stdout, stderr = ssh.exec_command(cmd)
|
|
93
|
+
msg = stdout.readlines()
|
|
94
|
+
err = stderr.readlines()
|
|
95
|
+
if MAGIC_STR in str(msg):
|
|
96
|
+
need_restart_dns = True
|
|
97
|
+
if MAGIC_STR2 in str(msg):
|
|
98
|
+
need_restart_cdns = True
|
|
99
|
+
print('msg', msg) if msg else print()
|
|
100
|
+
print('err', err) if err else print()
|
|
101
|
+
if config.refresh:
|
|
102
|
+
if need_restart_dns:
|
|
103
|
+
print('reboot dnsmasq')
|
|
104
|
+
_, stdout, stderr = ssh.exec_command(CMD_DNSMASQ)
|
|
105
|
+
msg = stdout.readlines()
|
|
106
|
+
err = stderr.readlines()
|
|
107
|
+
print('msg', msg) if msg else print()
|
|
108
|
+
print('err', err) if err else print()
|
|
109
|
+
if need_restart_cdns:
|
|
110
|
+
print('reboot chinadns')
|
|
111
|
+
_, stdout, stderr = ssh.exec_command(CMD_CHNDNS)
|
|
112
|
+
msg = stdout.readlines()
|
|
113
|
+
err = stderr.readlines()
|
|
114
|
+
print('msg', msg) if msg else print()
|
|
115
|
+
print('err', err) if err else print()
|
|
116
|
+
ssh.close()
|
|
117
|
+
|
|
118
|
+
def gen_hostnames_by_sources(sources):
|
|
119
|
+
hostnames = []
|
|
120
|
+
for source in sources:
|
|
121
|
+
if not path.exists(source):
|
|
122
|
+
if is_domain_name(source):
|
|
123
|
+
hostnames.append(source)
|
|
124
|
+
elif path.isfile(source):
|
|
125
|
+
hostnames += read_hostname_from_file(source)
|
|
126
|
+
return list(dict.fromkeys(hostnames))
|
|
127
|
+
|
|
128
|
+
def main():
|
|
129
|
+
sources, config = load_and_overlay_config()
|
|
130
|
+
print('sources:', sources)
|
|
131
|
+
hostnames = gen_hostnames_by_sources(sources)
|
|
132
|
+
if hostnames:
|
|
133
|
+
update_rule_by_ssh(hostnames, config)
|
|
134
|
+
else:
|
|
135
|
+
print('没有读取到有效域名,请检查!!!')
|
|
136
|
+
|
|
137
|
+
def read_info_from_input(prompt, parser=None):
|
|
138
|
+
while True:
|
|
139
|
+
info = input(prompt)
|
|
140
|
+
if parser:
|
|
141
|
+
info = parser(info)
|
|
142
|
+
if not info is None:
|
|
143
|
+
break
|
|
144
|
+
else:
|
|
145
|
+
print('输入有误,请重新输入!')
|
|
146
|
+
continue
|
|
147
|
+
break
|
|
148
|
+
return info
|
|
149
|
+
|
|
150
|
+
def gen_config():
|
|
151
|
+
print('配置向导,请按提示输入信息...')
|
|
152
|
+
host = read_info_from_input('请输入有效主机名:\n', parse_host_name)
|
|
153
|
+
port = int(read_info_from_input('请输入有效端口:\n', parse_port))
|
|
154
|
+
username = read_info_from_input('请输入openwrt用户名:\n')
|
|
155
|
+
password = read_info_from_input('请输入openwrt密码:\n')
|
|
156
|
+
refresh = read_info_from_input('是否重启相关服务(dnsmasq、chinadns),Y(es)/N(o)/T(rue)/F(alse):\n', parse_yes_or_no)
|
|
157
|
+
config = Config()
|
|
158
|
+
config.update(host, port, username, password, refresh)
|
|
159
|
+
config_path = path.join(path.dirname(__file__), 'config.ini')
|
|
160
|
+
config.save_to(config_path)
|
|
161
|
+
print('已生成配置文件写入到{}'.format(config_path))
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
if __name__ == '__main__':
|
|
165
|
+
gen_config()
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
iup/__init__.py,sha256=WXPOI9BwESIVzJ-XhG7bIFhsRg98u_v5gp16nY0bcbI,108
|
|
2
|
+
iup/config.py,sha256=Ecg9m83D_Cp_inYrltt--oPcupVvCw9oo8m5ukKyWLA,2862
|
|
3
|
+
iup/main.py,sha256=j7-6cFrI6_RFkWR-Y4_LChs3fBVb1JGKQ8aW_w_9kMk,5508
|
|
4
|
+
iup_nft-0.1.dist-info/METADATA,sha256=SiGliRq46XFLR0k3q-mV62-0tnU8QI-p9vke0ftFqVw,208
|
|
5
|
+
iup_nft-0.1.dist-info/WHEEL,sha256=Mdi9PDNwEZptOjTlUcAth7XJDFtKrHYaQMPulZeBCiQ,91
|
|
6
|
+
iup_nft-0.1.dist-info/entry_points.txt,sha256=ER1eUBmB6bXwudHBT51NoOtDSlnUgBi4T6J9_kA4pwc,68
|
|
7
|
+
iup_nft-0.1.dist-info/top_level.txt,sha256=abec3YOzJRti4IxzOLIn-uDOPTtYUE-Uv65cAv1v8JY,4
|
|
8
|
+
iup_nft-0.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
iup
|