Simple Linux Panel
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mdserver-web/class/core/firewall_api.py

464 lines
17 KiB

6 years ago
# coding: utf-8
3 years ago
# ---------------------------------------------------------------------------------
# MW-Linux面板
# ---------------------------------------------------------------------------------
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
# ---------------------------------------------------------------------------------
# Author: midoks <midoks@163.com>
# ---------------------------------------------------------------------------------
# ---------------------------------------------------------------------------------
# 防火墙操作
# ---------------------------------------------------------------------------------
6 years ago
import psutil
import time
import os
import sys
import mw
6 years ago
import re
import json
import pwd
6 years ago
from flask import request
6 years ago
class firewall_api:
6 years ago
__isFirewalld = False
__isUfw = False
6 years ago
__isMac = False
6 years ago
6 years ago
def __init__(self):
6 years ago
if os.path.exists('/usr/sbin/firewalld'):
self.__isFirewalld = True
if os.path.exists('/usr/sbin/ufw'):
self.__isUfw = True
if mw.isAppleSystem():
6 years ago
self.__isMac = True
6 years ago
6 years ago
##### ----- start ----- ###
6 years ago
# 添加屏蔽IP
def addDropAddressApi(self):
import re
port = request.form.get('port', '').strip()
ps = request.form.get('ps', '').strip()
rep = "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2})?$"
if not re.search(rep, port):
return mw.returnJson(False, '您输入的IP地址不合法!')
6 years ago
address = port
if mw.M('firewall').where("port=?", (address,)).count() > 0:
return mw.returnJson(False, '您要放屏蔽的IP已存在屏蔽列表,无需重复处理!')
6 years ago
if self.__isUfw:
mw.execShell('ufw deny from ' + address + ' to any')
6 years ago
else:
if self.__isFirewalld:
6 years ago
cmd = 'firewall-cmd --permanent --add-rich-rule=\'rule family=ipv4 source address="' + \
address + '" drop\''
mw.execShell(cmd)
6 years ago
else:
6 years ago
cmd = 'iptables -I INPUT -s ' + address + ' -j DROP'
mw.execShell(cmd)
6 years ago
msg = mw.getInfo('屏蔽IP[{1}]成功!', (address,))
mw.writeLog("防火墙管理", msg)
6 years ago
addtime = time.strftime('%Y-%m-%d %X', time.localtime())
mw.M('firewall').add('port,ps,addtime', (address, ps, addtime))
6 years ago
self.firewallReload()
return mw.returnJson(True, '添加成功!')
6 years ago
# 添加放行端口
6 years ago
def addAcceptPortApi(self):
if not self.getFwStatus():
return mw.returnJson(False, '防火墙启动时,才能添加规则!')
6 years ago
port = request.form.get('port', '').strip()
ps = request.form.get('ps', '').strip()
6 years ago
stype = request.form.get('type', '').strip()
6 years ago
3 years ago
data = self.addAcceptPortArgs(port, ps, stype)
return mw.getJson(data)
# 添加放行端口
def addAcceptPortArgs(self, port, ps, stype):
import re
import time
if not self.getFwStatus():
self.setFw(0)
6 years ago
rep = "^\d{1,5}(:\d{1,5})?$"
if not re.search(rep, port):
3 years ago
return mw.returnData(False, '端口范围不正确!')
6 years ago
if mw.M('firewall').where("port=?", (port,)).count() > 0:
3 years ago
return mw.returnData(False, '您要放行的端口已存在,无需重复放行!')
6 years ago
msg = mw.getInfo('放行端口[{1}]成功', (port,))
mw.writeLog("防火墙管理", msg)
6 years ago
addtime = time.strftime('%Y-%m-%d %X', time.localtime())
mw.M('firewall').add('port,ps,addtime', (port, ps, addtime))
6 years ago
self.addAcceptPort(port)
6 years ago
self.firewallReload()
3 years ago
return mw.returnData(True, '添加放行(' + port + ')端口成功!')
6 years ago
6 years ago
# 删除IP屏蔽
def delDropAddressApi(self):
if not self.getFwStatus():
return mw.returnJson(False, '防火墙启动时,才能删除规则!')
6 years ago
port = request.form.get('port', '').strip()
ps = request.form.get('ps', '').strip()
sid = request.form.get('id', '').strip()
address = port
if self.__isUfw:
mw.execShell('ufw delete deny from ' + address + ' to any')
6 years ago
else:
if self.__isFirewalld:
mw.execShell(
6 years ago
'firewall-cmd --permanent --remove-rich-rule=\'rule family=ipv4 source address="' + address + '" drop\'')
elif self.__isMac:
pass
else:
cmd = 'iptables -D INPUT -s ' + address + ' -j DROP'
mw.execShell(cmd)
6 years ago
msg = mw.getInfo('解除IP[{1}]的屏蔽!', (address,))
mw.writeLog("防火墙管理", msg)
mw.M('firewall').where("id=?", (sid,)).delete()
6 years ago
self.firewallReload()
return mw.returnJson(True, '删除成功!')
6 years ago
# 删除放行端口
6 years ago
def delAcceptPortApi(self):
6 years ago
port = request.form.get('port', '').strip()
sid = request.form.get('id', '').strip()
mw_port = mw.readFile('data/port.pl')
6 years ago
try:
6 years ago
if(port == mw_port):
return mw.returnJson(False, '失败,不能删除当前面板端口!')
6 years ago
if self.__isUfw:
mw.execShell('ufw delete allow ' + port + '/tcp')
6 years ago
else:
if self.__isFirewalld:
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/tcp')
mw.execShell(
'firewall-cmd --permanent --zone=public --remove-port=' + port + '/udp')
6 years ago
else:
mw.execShell(
6 years ago
'iptables -D INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
msg = mw.getInfo('删除防火墙放行端口[{1}]成功!', (port,))
mw.writeLog("防火墙管理", msg)
mw.M('firewall').where("id=?", (sid,)).delete()
6 years ago
self.firewallReload()
return mw.returnJson(True, '删除成功!')
except Exception as e:
return mw.returnJson(False, '删除失败!:' + str(e))
6 years ago
6 years ago
def getWwwPathApi(self):
path = mw.getLogsDir()
return mw.getJson({'path': path})
6 years ago
def getListApi(self):
p = request.form.get('p', '1').strip()
limit = request.form.get('limit', '10').strip()
return self.getList(int(p), int(limit))
def getLogListApi(self):
p = request.form.get('p', '1').strip()
limit = request.form.get('limit', '10').strip()
search = request.form.get('search', '').strip()
return self.getLogList(int(p), int(limit), search)
6 years ago
def getSshInfoApi(self):
3 years ago
data = {}
6 years ago
file = '/etc/ssh/sshd_config'
conf = mw.readFile(file)
6 years ago
rep = "#*Port\s+([0-9]+)\s*\n"
port = re.search(rep, conf).groups(0)[0]
isPing = True
try:
if mw.isAppleSystem():
isPing = True
else:
file = '/etc/sysctl.conf'
3 years ago
sys_conf = mw.readFile(file)
rep = "#*net\.ipv4\.icmp_echo_ignore_all\s*=\s*([0-9]+)"
3 years ago
tmp = re.search(rep, sys_conf).groups(0)[0]
if tmp == '1':
isPing = False
except:
isPing = True
# sshd 检测
status = True
cmd = "service sshd status | grep -P '(dead|stop)'|grep -v grep"
ssh_status = mw.execShell(cmd)
if ssh_status[0] != '':
status = False
cmd = "systemctl status sshd.service | grep 'dead'|grep -v grep"
ssh_status = mw.execShell(cmd)
if ssh_status[0] != '':
6 years ago
status = False
data['pass_prohibit_status'] = False
3 years ago
# 密码登陆配置检查
pass_rep = "#PasswordAuthentication\s+(\w*)\s*\n"
pass_status = re.search(pass_rep, conf)
if pass_status:
data['pass_prohibit_status'] = True
if not data['pass_prohibit_status']:
pass_rep = "PasswordAuthentication\s+(\w*)\s*\n"
pass_status = re.search(pass_rep, conf)
if pass_status and pass_status.groups(0)[0].strip() == 'no':
data['pass_prohibit_status'] = True
6 years ago
3 years ago
data['port'] = port
6 years ago
data['status'] = status
data['ping'] = isPing
if mw.isAppleSystem():
6 years ago
data['firewall_status'] = False
else:
6 years ago
data['firewall_status'] = self.getFwStatus()
return mw.getJson(data)
6 years ago
6 years ago
def setSshPortApi(self):
port = request.form.get('port', '1').strip()
if int(port) < 22 or int(port) > 65535:
return mw.returnJson(False, '端口范围必需在22-65535之间!')
6 years ago
3 years ago
ports = ['21', '25', '80', '443', '888']
6 years ago
if port in ports:
return mw.returnJson(False, '(' + port + ')' + '特殊端口不可设置!')
6 years ago
file = '/etc/ssh/sshd_config'
conf = mw.readFile(file)
6 years ago
rep = "#*Port\s+([0-9]+)\s*\n"
conf = re.sub(rep, "Port " + port + "\n", conf)
mw.writeFile(file, conf)
6 years ago
if self.__isFirewalld:
mw.execShell('setenforce 0')
mw.execShell(
6 years ago
'sed -i "s#SELINUX=enforcing#SELINUX=disabled#" /etc/selinux/config')
mw.execShell("systemctl restart sshd.service")
6 years ago
elif self.__isUfw:
mw.execShell('ufw allow ' + port + '/tcp')
mw.execShell("service ssh restart")
6 years ago
else:
mw.execShell(
6 years ago
'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT')
mw.execShell("/etc/init.d/sshd restart")
6 years ago
self.firewallReload()
# mw.M('firewall').where(
6 years ago
# "ps=?", ('SSH远程管理服务',)).setField('port', port)
msg = "改SSH端口为[{}]成功!".format(port)
mw.writeLog("防火墙管理", msg)
return mw.returnJson(True, '修改成功!')
6 years ago
6 years ago
def setSshStatusApi(self):
if mw.isAppleSystem():
return mw.returnJson(True, '开发机不能操作!')
6 years ago
6 years ago
status = request.form.get('status', '1').strip()
msg = 'SSH服务已启用'
act = 'start'
if status == "1":
6 years ago
msg = 'SSH服务已停用'
act = 'stop'
ssh_service = mw.systemdCfgDir() + '/sshd.service'
if os.path.exists(ssh_service):
mw.execShell("systemctl " + act + " sshd.service")
6 years ago
else:
mw.execShell('service sshd ' + act)
if os.path.exists('/etc/init.d/sshd'):
mw.execShell('/etc/init.d/sshd ' + act)
6 years ago
mw.writeLog("防火墙管理", msg)
return mw.returnJson(True, '操作成功!')
3 years ago
def setSshPassStatusApi(self):
if mw.isAppleSystem():
return mw.returnJson(True, '开发机不能操作!')
3 years ago
status = request.form.get('status', '1').strip()
msg = '禁止密码登陆成功'
3 years ago
if status == "1":
msg = '开启密码登陆成功'
3 years ago
file = '/etc/ssh/sshd_config'
if not os.path.exists(file):
return mw.returnJson(False, '无法设置!')
3 years ago
conf = mw.readFile(file)
if status == '1':
3 years ago
rep = "(#)?PasswordAuthentication\s+(\w*)\s*\n"
conf = re.sub(rep, "PasswordAuthentication yes\n", conf)
3 years ago
else:
3 years ago
rep = "(#)?PasswordAuthentication\s+(\w*)\s*\n"
conf = re.sub(rep, "PasswordAuthentication no\n", conf)
3 years ago
mw.writeFile(file, conf)
mw.execShell("systemctl restart sshd.service")
mw.writeLog("SSH管理", msg)
return mw.returnJson(True, msg)
6 years ago
6 years ago
def setPingApi(self):
if mw.isAppleSystem():
return mw.returnJson(True, '开发机不能操作!')
6 years ago
status = request.form.get('status')
6 years ago
filename = '/etc/sysctl.conf'
conf = mw.readFile(filename)
6 years ago
if conf.find('net.ipv4.icmp_echo') != -1:
rep = u"net\.ipv4\.icmp_echo.*"
conf = re.sub(rep, 'net.ipv4.icmp_echo_ignore_all=' + status, conf)
else:
conf += "\nnet.ipv4.icmp_echo_ignore_all=" + status
mw.writeFile(filename, conf)
mw.execShell('sysctl -p')
return mw.returnJson(True, '设置成功!')
6 years ago
6 years ago
def setFwApi(self):
if mw.isAppleSystem():
return mw.returnJson(True, '开发机不能设置!')
6 years ago
status = request.form.get('status', '1')
3 years ago
return mw.getJson(self.setFw(status))
def setFw(self, status):
6 years ago
if status == '1':
if self.__isUfw:
3 years ago
mw.execShell('/usr/sbin/ufw disable')
6 years ago
if self.__isFirewalld:
mw.execShell('systemctl stop firewalld.service')
mw.execShell('systemctl disable firewalld.service')
6 years ago
elif self.__isMac:
pass
else:
mw.execShell('service iptables save')
mw.execShell('service iptables stop')
6 years ago
else:
if self.__isUfw:
mw.execShell("echo 'y'| ufw enable")
6 years ago
if self.__isFirewalld:
mw.execShell('systemctl start firewalld.service')
mw.execShell('systemctl enable firewalld.service')
6 years ago
elif self.__isMac:
pass
else:
mw.execShell('service iptables save')
mw.execShell('service iptables restart')
6 years ago
3 years ago
return mw.returnData(True, '设置成功!')
6 years ago
def delPanelLogsApi(self):
mw.M('logs').where('id>?', (0,)).delete()
mw.writeLog('面板设置', '面板操作日志已清空!')
return mw.returnJson(True, '面板操作日志已清空!')
6 years ago
##### ----- start ----- ###
6 years ago
def getList(self, page, limit):
start = (page - 1) * limit
_list = mw.M('firewall').field('id,port,ps,addtime').limit(
6 years ago
str(start) + ',' + str(limit)).order('id desc').select()
data = {}
data['data'] = _list
count = mw.M('firewall').count()
6 years ago
_page = {}
_page['count'] = count
_page['tojs'] = 'showAccept'
_page['p'] = page
data['page'] = mw.getPage(_page)
return mw.getJson(data)
6 years ago
def getLogList(self, page, limit, search=''):
find_search = ''
if search != '':
find_search = "type like '%" + search + "%' or log like '%" + \
search + "%' or addtime like '%" + search + "%'"
start = (page - 1) * limit
_list = mw.M('logs').where(find_search, ()).field(
6 years ago
'id,type,log,addtime').limit(str(start) + ',' + str(limit)).order('id desc').select()
data = {}
data['data'] = _list
count = mw.M('logs').where(find_search, ()).count()
6 years ago
_page = {}
_page['count'] = count
_page['tojs'] = 'getLogs'
_page['p'] = page
data['page'] = mw.getPage(_page)
return mw.getJson(data)
6 years ago
def addAcceptPort(self, port):
if self.__isUfw:
mw.execShell('ufw allow ' + port + '/tcp')
3 years ago
elif self.__isFirewalld:
port = port.replace(':', '-')
cmd = 'firewall-cmd --permanent --zone=public --add-port=' + port + '/tcp'
mw.execShell(cmd)
elif self.__isMac:
pass
else:
3 years ago
cmd = 'iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport ' + port + ' -j ACCEPT'
mw.execShell(cmd)
6 years ago
def firewallReload(self):
if self.__isUfw:
mw.execShell('/usr/sbin/ufw reload')
6 years ago
return
if self.__isFirewalld:
mw.execShell('firewall-cmd --reload')
6 years ago
elif self.__isMac:
pass
else:
mw.execShell('service iptables save')
mw.execShell('service iptables restart')
6 years ago
def getFwStatus(self):
if self.__isUfw:
cmd = "/usr/sbin/ufw status| grep Status | awk -F ':' '{print $2}'"
data = mw.execShell(cmd)
3 years ago
if data[0].strip() == 'inactive':
6 years ago
return False
return True
if self.__isFirewalld:
cmd = "ps -ef|grep firewalld |grep -v grep | awk '{print $2}'"
data = mw.execShell(cmd)
6 years ago
if data[0] == '':
return False
return True
elif self.__isMac:
return False
else:
6 years ago
cmd = "ps -ef|grep iptables |grep -v grep | awk '{print $2}'"
data = mw.execShell(cmd)
6 years ago
if data[0] == '':
return False
return True