rinetd端口轉(zhuǎn)發(fā)web化方案python二次開發(fā)(修改--增加備注)

源項(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()

最終效果如圖


image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末忆谓,一起剝皮案震驚了整個(gè)濱河市裆装,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌倡缠,老刑警劉巖哨免,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異昙沦,居然都是意外死亡琢唾,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門盾饮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來采桃,“玉大人,你說我怎么就攤上這事丐谋∩直蹋” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵号俐,是天一觀的道長泌豆。 經(jīng)常有香客問我,道長吏饿,這世上最難降的妖魔是什么踪危? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任蔬浙,我火速辦了婚禮,結(jié)果婚禮上贞远,老公的妹妹穿的比我還像新娘畴博。我一直安慰自己,他們只是感情好蓝仲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布俱病。 她就那樣靜靜地躺著,像睡著了一般袱结。 火紅的嫁衣襯著肌膚如雪亮隙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天垢夹,我揣著相機(jī)與錄音溢吻,去河邊找鬼。 笑死果元,一個(gè)胖子當(dāng)著我的面吹牛促王,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播而晒,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蝇狼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了倡怎?” 一聲冷哼從身側(cè)響起题翰,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎诈胜,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冯事,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡焦匈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昵仅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缓熟。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖摔笤,靈堂內(nèi)的尸體忽然破棺而出够滑,到底是詐尸還是另有隱情,我是刑警寧澤吕世,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布彰触,位于F島的核電站,受9級(jí)特大地震影響命辖,放射性物質(zhì)發(fā)生泄漏况毅。R本人自食惡果不足惜分蓖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望尔许。 院中可真熱鬧么鹤,春花似錦、人聲如沸味廊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽余佛。三九已至柠新,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間衙熔,已是汗流浹背登颓。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留红氯,地道東北人框咙。 一個(gè)月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像痢甘,于是被迫代替她去往敵國和親喇嘱。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容