Linux自动banip脚本(1)

Linux自动banip脚本(1)

前置知识

Linux系统被暴力破解密码的自动阻断脚本

项目背景:只要是暴露在公网的服务器,每天都会有大量的被暴力破解的行为。
我们来思考解决的方法:

  1. 更换服务器端口。(根据现有的端口发现技术,基本无济于事)
  2. 买云防护,waf 防火墙等。(需要有一定经济条件)

我们可以自己来写一个自动banip的脚本

在正式写脚本之前需要学习一定前置知识:

re正则表达式模块
subprocess模块

re模块

  1. 匹配普通字符
    findall函数
    功能:
    找到匹配到的全部子字符串,并返回一个列表,如果没有匹配到就返回空列表

    Python 3.12.7 (main, Nov  8 2024, 17:55:36) [GCC 14.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import re
    >>> s = 'hello burgess 猪猪侠'
    >>> re.findall('hello',s)
    ['hello']
    >>> re.findall('猪猪侠',s)
    ['猪猪侠']
    >>> re.findall('猪猪',s)
    ['猪猪']
    >>> re.findall('555',s)
    []
    >>> re.findall('l',s)
    ['l', 'l']
    

    search函数
    功能:
    扫描整个字符串,并且返回第一个,如果没有成功匹配就返回空(None)

    Python 3.12.7 (main, Nov  8 2024, 17:55:36) [GCC 14.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import re
    >>> s = 'hello burgess 猪猪侠'
    >>> re.search('hello',s)
    <re.Match object; span=(0, 5), match='hello'>
    >>> m = re.search('hello',s)
    >>> m.group()
    'hello'
    >>> m.span()
    (0, 5)
    >>> m = re.search('l',s)
    >>> m.group()
    'l'
    >>> m = re.search('999',s)
    >>> m.group()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    >>>
    
  2. 匹配元字符
    \d 匹配全部数字0-9
    \D 匹配非数字
    \w 匹配全部单词字符,包括大小写字母 数字 下划线 中文
    \W 匹配其余剩下的,空白符(空格,换行符,制表符) 特殊字符

    Python 3.12.7 (main, Nov  8 2024, 17:55:36) [GCC 14.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import re
    >>> s = 'abcdefg__123456789056\n\t%#@!n奥特曼'
    >>> re.findall('\d',s)
    <stdin>:1: SyntaxWarning: invalid escape sequence '\d'
    ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '5', '6']
    >>> re.findall('\D',s)
    <stdin>:1: SyntaxWarning: invalid escape sequence '\D'
    ['a', 'b', 'c', 'd', 'e', 'f', 'g', '_', '_', '\n', '\t', '%', '#', '@', '!', 'n', '奥', '特', '曼']
    >>> re.findall(r'\d',s)
    ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '5', '6']
    >>> re.findall(r'\D',s)
    ['a', 'b', 'c', 'd', 'e', 'f', 'g', '_', '_', '\n', '\t', '%', '#', '@', '!', 'n', '奥', '特', '曼']
    >>> re.findall(r'\w',s)
    ['a', 'b', 'c', 'd', 'e', 'f', 'g', '_', '_', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '5', '6', 'n', '奥', '特', '曼']
    >>> re.findall(r'\W',s)
    ['\n', '\t', '%', '#', '@', '!']
    >>>
    
  3. 匹配字符集
    字符的集合,用[]表示,字符集内用“^”表示“非”
    \d=[0-9]
    \w!=[a-zA-Z_0-9] 还有中文

    Python 3.12.7 (main, Nov  8 2024, 17:55:36) [GCC 14.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import re
    >>> s = 'char_achar_bchar_c,char_python,char_java 中国##@!'
    >>> re.findall('char_[ab]',s)
    ['char_a', 'char_b']
    >>> re.findall('char_[^ab]',s)
    ['char_c', 'char_p', 'char_j']
    >>> re.findall('char_[a-c]',s)
    ['char_a', 'char_b', 'char_c']
    >>> re.findall('char_[a-p]',s)
    ['char_a', 'char_b', 'char_c', 'char_p', 'char_j']
    >>> re.findall('[^0-9a-zA-Z_]',s)
    [',', ',', ' ', '中', '国', '#', '#', '@', '!']
    >>> re.findall(r'[^\w]',s)
    [',', ',', ' ', '#', '#', '@', '!']
    
  4. 匹配空白符
    空白符包含:
    ' '空格 \r回车符 \n换行符 \t制表符
    使用\s来匹配

    Python 3.12.7 (main, Nov  8 2024, 17:55:36) [GCC 14.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import re
    >>> s = '     Python与渗透测试    \r\n'
    >>> re.findall(r'\s',s)
    [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '\r', '\n']
    >>> re.findall(r'[^\s]',s)
    ['P', 'y', 't', 'h', 'o', 'n', '与', '渗', '透', '测', '试']
    >>> re.findall(r'[\S]',s)
    ['P', 'y', 't', 'h', 'o', 'n', '与', '渗', '透', '测', '试']
    >>>
    
  5. {}表示匹配标定字符数量

    特殊数量符号:

    * 匹配前一个字符0or无限次

    + 匹配前一个字符1or无限次
    . 匹配除换行符\n以外的任意1个字符
    注意点:特殊数量符号控制的是紧挨着该符号左边的字符or字符集

    Python 3.12.7 (main, Nov  8 2024, 17:55:36) [GCC 14.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import re
    >>> s = '     Python与渗透测试 中文 \r\n '
    >>> re.findall('[a-z]{3}',s)
    ['yth']
    >>> s = 'linux windows macos git python java'
    >>> re.findall('[a-z]{3}',s)
    ['lin', 'win', 'dow', 'mac', 'git', 'pyt', 'hon', 'jav']
    >>> re.findall('[a-z]{3,6}',s)
    ['linux', 'window', 'macos', 'git', 'python', 'java']
    >>> s = 'hell#hello$helloo@'
    >>> re.findall('hello*',s)
    ['hell', 'hello', 'helloo']
    >>> re.findall('hello+',s)
    ['hello', 'helloo']
    
  6. 字符组:
    把字符用()括起来,叫字符组,目的就为将匹配成的字符串分组

    匹配参数模式
    findall函数其实有第三个参数,是默认参数,参数模式。
    re.I 忽略大小写
    re.S 匹配空白符
    多个参数用 “|”

    Python 3.12.7 (main, Nov  8 2024, 17:55:36) [GCC 14.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import re
    >>> s = '    Python与渗透测试   \n'
    >>> re.findall(r'\s*(\w+)\s*',s)
    ['Python与渗透测试']
    >>> s = 'Hello\nBurgess'
    >>> re.findall('Lo',s)
    []
    >>> re.findall('Lo',s,re.I)
    ['lo']
    >>> re.findall('Lo.',s,re.I)
    []
    >>> re.findall('Lo.',s,re.I|re.S)
    ['lo\n']
    >>>
    

subprocess 模块

项目需求:执行命令并将输出劫持实现日志的监控。

用于启动新的进程的模块,它可以用于执行外部命令,获取进程的输出,向进程发送输入和等待进程结束。

多进程协同,在python里大概有这么三种方式:
1.os.system函数
阻塞式
2.multiprocessing 模块
使用场景:密集型的计算

3.subprocess模块
subprocess.run 执行指定的命令,等待命令执行完成后返回一个对象
subprocess.call 执行指定的命令,返回命令执行的状态
subprocess.check_call (跟上面差不多),区别是会输出报错信息
subprocess .getoutput 执行命令,返回结果

参数格式:

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, timeout=None, check=False, universal_newlines=False)

subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

args:要执行的命令,必须是个字符串,或者是字符串参数列表
stdin stdout stderr : 子进程的标准输入 输出 错误 最常用的是subprocess.PIPE
timeout : 设置命令超时
shell : 值为bool,如果参数为True 将通过操作系统的shell执行命令

subprocess.Popen (上面方法的祖宗)
process = subprocess.Popen(
cmd(命令),
shell=True,
stdout=subprocess.PIPE,
stdin = subprocess.PIPE,
stderr = subprocess.PIPE)

shell: 打开终端,Linux中是终端,Windows中是cmd
stdout=subprocess.PIPE:如果该命令执行成功,那么将该命令的标准输出放入管道(后面的以此类推)

终端输入命令分两种:
1.直接在终端输入
2.进入环境再输入,比如直接输入python回车就是python交互式模式

代码示例(1)

└─# python
Python 3.12.7 (main, Nov  8 2024, 17:55:36) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> subprocess.run(['ls','-al'])
total 8
drwxr-xr-x 2 root root 4096 Jul  7 05:41 .
drwxr-xr-x 8 root root 4096 Jul  3 11:52 ..
-rw-r--r-- 1 root root    0 Jul  7 05:41 1.txt
-rw-r--r-- 1 root root    0 Jul  7 05:41 2.txt
-rw-r--r-- 1 root root    0 Jul  7 05:41 3.txt
CompletedProcess(args=['ls', '-al'], returncode=0)
>>> subprocess.call(['ls','-al'])
total 8
drwxr-xr-x 2 root root 4096 Jul  7 05:41 .
drwxr-xr-x 8 root root 4096 Jul  3 11:52 ..
-rw-r--r-- 1 root root    0 Jul  7 05:41 1.txt
-rw-r--r-- 1 root root    0 Jul  7 05:41 2.txt
-rw-r--r-- 1 root root    0 Jul  7 05:41 3.txt
0
>>> subprocess.call(['ls','-we'])
ls: invalid line width: ‘e’
2
>>> subprocess.check_call(['ls','-we'])
ls: invalid line width: ‘e’
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.12/subprocess.py", line 413, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['ls', '-we']' returned non-zero exit status 2.
>>>

代码示例(2)

Python 3.12.7 (main, Nov  8 2024, 17:55:36) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> obj = subprocess.Popen('mkdir 666',shell=True,cwd='/root/python_code/python_5')
>>>

执行结果

┌──(root㉿kali)-[~/python_code/python_5]
└─# ls
1.txt  2.txt  3.txt  666

代码示例(3)

#!/usr/bin/env python

import subprocess

obj = subprocess.Popen(['python'],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE,universal_newlines=True)

obj.stdin.write('print(1)\n')
obj.stdin.write('print(2)')
obj.stdin.close()

cmd_out = obj.stdout.read()
obj.stdout.close()
cmd_err = obj.stderr.read()
obj.stderr.close()

print(cmd_out)
print(cmd_err)

运行结果

┌──(root㉿kali)-[~/python_code/python_5]
└─# python popen.py
1
2

代码示例(4)

Python 3.12.7 (main, Nov  8 2024, 17:55:36) [GCC 14.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> obj = subprocess.Popen('ls /tmp',shell=True,stdout=subprocess.PIPE)
>>> obj.stdout.readline()
b'config-err-KAZ6u1\n'
>>> obj.stdout.readlines()
[b'ssh-pROSvXnIjWXs\n', b'systemd-private-8f7b4dfb4b4444a3948a006dcec066bc-colord.service-VUxSz2\n', b'systemd-private-8f7b4dfb4b4444a3948a006dcec066bc-haveged.service-PgLynO\n', b'systemd-private-8f7b4dfb4b4444a3948a006dcec066bc-ModemManager.service-1qyafj\n', b'systemd-private-8f7b4dfb4b4444a3948a006dcec066bc-polkit.service-aR7CHl\n', b'systemd-private-8f7b4dfb4b4444a3948a006dcec066bc-systemd-logind.service-yqtZOV\n', b'systemd-private-8f7b4dfb4b4444a3948a006dcec066bc-systemd-timesyncd.service-QssV0a\n', b'systemd-private-8f7b4dfb4b4444a3948a006dcec066bc-upower.service-B6pB3N\n', b'VMwareDnD\n', b'vmware-root_584-2688619665\n']
>>> type(obj)
<class 'subprocess.Popen'>
>>>
>>> obj = subprocess.Popen('ls -l',shell=True,stdout=subprocess.PIPE)
>>> p = subprocess.Popen('wc',shell=True,stdin=obj.stdout,stdout=subprocess.PIPE)
>>> p.stdout.readlines()
[b'      5      38     194\n']
>>>
posted on 2025-07-07 18:28  burgess0x  阅读(62)  评论(0)    收藏  举报