#!/bin/python3
import os
# from portServer import * # 可以将下面 samba 等定义的端口函数,存放在 portServer.py 里,然后这里导入所有函数
# 定义全局变量的初始值
type = ""
rank_type = ""
ip = ""
ip_segment = ""
port_list = []
source_port = []
dest_port = []
portmin = 0
portmax = 0
vpn_flag = 0
vpn_ip = "10.1.1.3"
# 定义服务函数
def samba():
global type, rank_type, ip, port_list # 如果需要修改全局变量,都需要加 global 全局声明
type = "samba"
rank_type = "list"
ip = "192.168.122.1"
port_list = [139, 445]
def mysql():
global type, rank_type, ip, port_list
type = "mysql"
rank_type = "list"
ip = "192.168.122.80"
port_list = [3306]
def mqtt():
global type, rank_type, ip, port_list
type = "mqtt"
rank_type = "list"
ip = "192.168.122.80"
port_list = [1883, 8883, 8083, 8084, 18083, 4370, 5370]
def mail():
global type, rank_type, ip, port_list
type = "mail"
rank_type = "list"
ip = "192.168.122.81"
port_list = [143, 993, 110, 995, 465, 587]
def webPublic():
global type, rank_type, ip, portmin, portmax
type = "web"
rank_type = "range"
ip = "192.168.122.80"
portmin = 62010
portmax = 62018
def webInside():
global type, rank_type, ip, port_list
type = "insideweb"
rank_type = "list"
ip = "192.168.122.80"
port_list = [3000, 3000, 3000, 3000]
def ssh():
global type, rank_type, ip_segment, ip, source_port, dest_port
type = "ssh"
rank_type = "SouceDest"
ip_segment = "192.168.122"
ip = [22, 22, 22, 22, 22, 22]
source_port = [22, 22, 22, 22, 22, 22]
dest_port = [22, 22, 22, 22, 22, 22]
def mstsc():
global type, rank_type, ip_segment, ip, source_port, dest_port
type = "mstsc"
rank_type = "SouceDest"
ip_segment = "192.168.122"
ip = [200, 200]
source_port = [3389, 3389]
dest_port = [3389, 3389]
# 创建目标文件夹并附加权限,如果 tcp.conf 不存在则创建它
def create_directory(tcp_file_dir, mode=0o777): # 定义函数,有两个参数: 1. 文件路径,2. 定义的权限: 0o 代表8进制
os.makedirs(tcp_file_dir, exist_ok=True) # 1. mkdir: make制作,dirs目录。 2. 目录存在不抛出异常
tcp_conf_path = os.path.join(tcp_file_dir, 'tcp.conf') # 拼接目录 tcp.conf 的完整路径
if not os.path.exists(tcp_conf_path): # 判断目录 不 存在
with open(tcp_conf_path, 'w') as file: # 1.上下文管理器,作用:在 with 板块里面的代码执行完,自动关闭文件操作流,和其他需要手动操作关闭的动作
# 2.打开文件,模式w写,覆盖 和 不存在就新建文件; 3. as file: 这个一个动作定义为一个 别名 file 写文件的对象函数; 并继承 open() 函数的内置方法如读写操作
file.write("stream {\n") # 1.file 函数动作传入参数,自动写入字符
# 主函数
def main():
global tcp_file_dir, vpn_ip, vpn_flag
tcp_file_dir = '/datadisk/eisc/wwwconf/tcp/'
# 用户输入和逻辑判断
vpn_input = input("当前电脑是放置在家庭吗?(y/n): ").strip().lower() #变量vpn_input=input内置函数输入的字符串,strip()删除空白字符; lower() 将大写转为小写字母
vpn_flag = 0 if vpn_input == 'y' else 1 # 先给你数值,你要满足的我条件: 输入为y 就不做任何操作。不满足我条件,将重新给你数值 为1; 当前是三元操作
port_list = ['samba', 'mysql', 'mqtt', 'mail', 'webPublic', 'webInside', 'ssh', 'mstsc']
print("选择的服务组有:")
for i, port_number in enumerate(port_list): # enumerate 遍历数组会返回两个参数,1.元素角标, 2.元素
print(f"{i}: {port_number}")
print("选择您要映射的端口组。使用空格分隔。例如: 0 1 2 3 (输入 '666' 选择所有服务)")
vpn_str_input = input("输入: ").strip() # 接收输入参数,删除空白字符
vpn_str_list = vpn_str_input.split() # split() 函数: 将字符串转为列表数组; 可以指定逗号分隔符案例: split(",")
if '666' in vpn_str_list: # 判断 all 元素是数组的成员 ; vpn_str_list 是选择的数字数组
vpn_select_port_list = port_list
else:
vpn_select_port_list = [port_list[int(port_number)] for port_number in vpn_str_list]
# 1. port_list[int(port_number)] 数组+角标获取元素; 而角标 port_number 是通过选择端口组的数组 在for 遍历得来
print(f"选择的端口组为: {vpn_select_port_list}") # f 格式化字符串,允许字符串包含表达式
# 创建目录并初始化 tcp.conf 文件
create_directory(tcp_file_dir)
# 根据选择的服务调用相应的函数
for service_name in vpn_select_port_list:
globals()[service_name]() # globals() 动态获取访问和操作函数 service_name 里面定义的全局变量
# python 所有函数板块使用缩进区分结束。
# 如 match rank_type: 位于 for 对齐将不会循环多次,不受for控制
# 根据不同的 rank_type 调用不同的创建函数
match rank_type:
case 'list':
print(f"端口类型 {service_name} 是列表类型,分类进入 createListPort 生成")
createListPort()
case 'range':
print(f"端口类型 {service_name} 是范围,分类进入 createRangePort 生成")
createRangePort()
case 'SouceDest':
print(f"端口类型 {service_name} 是源端口和目标绑定端口,分类进入 createSouceDestPort 生成")
createSouceDestPort()
case _:
print(f"未知的rank_type: {rank_type}")
# 添加额外的配置到 tcp.conf 文件
with open(os.path.join(tcp_file_dir, 'tcp.conf'), 'a') as file: # os.path.join 拼接文件完整路径,open打开文件 然后将这个动作方法 定义为file 对象函数,同时继承open() 函数的方法,如读写; 相当于 open() 函数被 file 函数继承所有方法
file.write("} # End of stream configuration\n") # 使用对象函数的方法 写文件
# 创建列表类型端口
def createListPort():
with open(os.path.join(tcp_file_dir, 'tcp.conf'), 'a') as file:
file.write(f"#------- {type} ---------#\n")
for port in port_list:
if vpn_flag == 1:
ip_address = vpn_ip
else:
ip_address = f"{ip_segment}.{ip}"
file.write(f"upstream {type}-{port} {
{ server {ip_address}:{port}; }} # {type}\n")
file.write(f"server {
{ listen {port}; proxy_pass {type}-{port}; }} # {type}\n\n")
# 创建范围类型端口
def createRangePort():
with open(os.path.join(tcp_file_dir, 'tcp.conf'), 'a') as file:
file.write(f"#------- {type} ---------#\n")
for port in range(portmin, portmax):
if vpn_flag == 1:
ip_address = vpn_ip
else:
ip_address = f"{ip_segment}.{ip}"
file.write(f"upstream {type}-{port} {
{ server {ip_address}:{port}; }} # {type}\n")
file.write(f"server {
{ listen {port}; proxy_pass {type}-{port}; }} # {type}\n\n")
# 创建源端口和目标端口映射类型
def createSouceDestPort():
with open(os.path.join(tcp_file_dir, 'tcp.conf'), 'a') as file:
file.write(f"#------- {type} ---------#\n")
for i, ip_suffix in enumerate(ip):
if vpn_flag == 1:
ip_address = vpn_ip
sport = dest_port[i]
dport = dest_port[i]
else:
ip_address = f"{ip_segment}.{ip_suffix}"
sport = source_port[i]
dport = dest_port[i]
file.write(f"upstream {type}-{dport} {
{ server {ip_address}:{sport}; }} # {type}\n")
file.write(f"server {
{ listen {dport}; proxy_pass {type}-{dport}; }} # {type}\n\n")
if __name__ == '__main__':
main()