源項(xiàng)目地址:https://github.com/xmapst/rinetdweb
因?yàn)楣窘?jīng)常需要把內(nèi)網(wǎng)服務(wù)映射出去携悯,領(lǐng)導(dǎo)為了便于管理族檬,故提出實(shí)施web化管理爬范。
本著充分利用網(wǎng)絡(luò)資源原則趾徽,采用了上面的項(xiàng)目地址。
由于具體腳本寫的缺乏細(xì)節(jié)窟感,故根據(jù)自己需求削茁,進(jìn)行了修改略贮。
有些配置原來寫死了,為考慮通用性茫陆,盡量采用變量和主動(dòng)獲取方式金麸。
提示uwsgi采用pip安裝,rpm包的兼容版本不知道是哪個(gè)簿盅,自動(dòng)安裝的沒法用
依賴:pip install uwsgi
2021.03.10由于之前頁面不支持增加說明信息挥下,有些配置時(shí)間長了會(huì)忘記做什么用的,因此要增加說明信息并顯示
***** 表示此次修改的部分
前端頁面比較簡單棚瘟,增加兩行代碼而已
補(bǔ)充了一些注釋现斋,現(xiàn)在應(yīng)該很容易明白了。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
# @Author : lijunye
# @File : webserver.py
# @Time : 2019/1/10
# @Uptime :
# @Version : 0.1
# @Features :
# @Desc : rinted端口轉(zhuǎn)發(fā) WEB界面操作
"""
import web
import os
import re
import time
import commands
import subprocess
render = web.template.render('templates/')
rinstate, rinetd_bin = commands.getstatusoutput('which rinetd')
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
CONF = "/root/data/rinetdweb/rinetd.conf" # 根據(jù)實(shí)際修改
PID = """ps -elf |grep rinetd|grep -v grep |awk '{print $4}'""" # 獲取rinetd的pid
# 判斷本機(jī)是否安裝rinetd
if rinstate != 0:
print("rinetd is not find")
os._exit()
# URL路由
urls = (
'/', 'Index',
'/add', 'Add',
'/del', 'Del',
'/op(.*)', 'Operate'
)
app = web.application(urls, globals())
# 獲取有效配置
def getConf():
i = 0
result = {}
with open( CONF, 'r') as fobj:
lines = fobj.readlines()
for line in lines:
line = line.strip('\n')
if line.startswith('0.0.0'): # 默認(rèn)源ip 0.0.0.0解取,建議采用默認(rèn)
# line = re.sub('#.*', '', line) # 為了便于管理步责,有些配置后面增加了注釋
line = re.sub('#', '', line) #*****獲取注釋內(nèi)容,去掉注釋符號(hào)
result[i] = line
i += 1
print line
# k = ['SocIP', 'SocPort', 'DesIP', 'DesPort'] # 向頁面?zhèn)鬟f配置的字段
k = ['SocIP', 'SocPort', 'DesIP', 'DesPort', 'Comment'] # 添加描述字段
for line in result.keys(): # 獲取每行配置的鍵值
v = str(result[line]).split() # 切割每行有效配置的
# result[line] = dict(zip(k, v)) # 把配置文件的值賦予字段意義禀苦,變成字典格式重新賦值回去
C = "" #**** 用于接受描述字段內(nèi)容蔓肯,因?yàn)槊枋隼锟赡苡锌崭瘢瑫?huì)生成不定長列表
if v[4:]: #***** 從第5個(gè)字段開始是說明內(nèi)容
for i in v[4:]:
C = C + i + " "
result[line] = { k[0]:v[0], k[1]:v[1], k[2]:v[2], k[3]:v[3], k[4]:C } # ****返回結(jié)果字典
return result
# 獲取rinetd運(yùn)行狀態(tài)
def rinetd_state():
pid = commands.getoutput( PID )
if pid == "":
return "Rinetd 已停止"
else:
return "Rinetd 正在運(yùn)行"
# 定義首頁類
class Index():
def GET(self):
result = getConf()
port_state = commands.getoutput('netstat -lnt').split("\n")
status = rinetd_state()
return render.index(result, status, port_state, msg=None)
# 定義增加配置方法類
class Add():
def POST(self):
form = web.input()
result = getConf()
status = rinetd_state()
port_state = commands.getoutput('netstat -lnt').split("\n")
p = []
for i,n in enumerate(port_state):
if i > 1:
s = ' '.join(n.split())
p.append(s.split()[3].split(":")[-1])
if form['SocIP'] != "" and form['SocPort'] != "" and form['DesIP'] != "" and form['DesPort'] != "":
for line in result.values():
if line['SocPort'] == form['SocPort'] or form['SocPort'] in p:
msg = "端口已存在"
return render.index(result, status, port_state, msg)
# new_result = "%s %s %s %s" % (form['SocIP'], form['SocPort'], form['DesIP'], form['DesPort'])
new_result = "%s %s %s %s #%s" % (form['SocIP'], form['SocPort'], form['DesIP'], form['DesPort'], form['Comment']) # ****獲取新增加配置
with open( CONF, mode='a') as data:
data.write(new_result.encode("utf-8") + '\n') # ****由于傳入內(nèi)容有非ASCII字符振乏,因此需要編碼
# data.write(new_result + '\n')
msg = "添加成功"
return render.index(result, status, port_state, msg)
else:
msg = "不允許為空"
return render.index(result, status, port_state, msg)
# 定義刪除配置方法類
class Del():
def POST(self):
form = web.input()
result = getConf()
status = rinetd_state()
port_state = commands.getoutput('netstat -lnt').split("\n")
lists = []
for line in result.values():
lists.append(line['SocPort'])
if form['SocIP'] != "" and form['SocPort'] != "" and form['DesIP'] != "" and form['DesPort'] != "":
with open( CONF, 'r') as fobj:
lines = fobj.readlines()
for line in lines:
line = line.strip()
if line.startswith('0.0.0'):
line = re.sub('#.*', '', line)
else:
continue
new_result = line.split(" ")[1]
if form['SocPort'] in lists and form['SocPort'] == new_result:
count = 0
while count < len(lines): # 動(dòng)態(tài)計(jì)算蔗包,防止最后索引超出范圍
# 此處的len函數(shù)是因?yàn)榕渲梦募杏械淖⑨屩挥羞B續(xù)的幾個(gè)字,甚至只有一個(gè)注釋符號(hào)慧邮,不判斷直接比較调限,后面的[1]會(huì)出現(xiàn)索引超出范圍
# 如果有特殊需求,可以 增加SocIP判斷
if len(lines[count]) > 2 and new_result == lines[count].split(" ")[1]:
lines.pop(count) # 如果排除修改出現(xiàn)重復(fù)錯(cuò)誤误澳,可以此處退出循環(huán)
else:
count += 1
with open( CONF, 'w') as wobj: # 回寫新配置文件
wobj.writelines(lines)
print line
msg = "刪除成功"
return render.index(result, status, port_state, msg)
else:
msg = "記錄不存在"
return render.index(result, status, port_state, msg)
class Operate():
def POST(self,operate=None):
form = web.input()
result = getConf()
if form['pm'] == 'start':
pid = commands.getoutput( PID )
if pid != "":
raise web.seeother('/')
stats = subprocess.Popen( rinetd_bin + ' -c ' + CONF + ' &' , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
time.sleep(0.3)
raise web.seeother('/')
elif form['pm'] == 'stop':
pid = commands.getoutput( PID )
if pid == "":
raise web.seeother('/')
commands.getstatusoutput('killall rinetd')
raise web.seeother('/')
elif form['pm'] == 'reload':
pid = commands.getoutput( PID )
if pid == "":
raise web.seeother('/')
# 此處使用kill -1 重新加載耻矮,避免直接重啟進(jìn)程,而斷掉其他正在使用的鏈接
commands.getstatusoutput("kill -1 `ps -elf |grep rinetd|grep -v grep |awk '{print $4}'`")
# stats = subprocess.Popen( rinetd_bin + ' -c ' + CONF + ' &' , shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, close_fds=True)
time.sleep(0.3)
raise web.seeother('/')
application = app.wsgifunc()
最終效果如圖