/good-mitm

Rule-based MITM engine. Rewriting, redirecting and rejecting on HTTP(S) requests and responses, supports JavaScript.

Primary LanguageRustMIT LicenseMIT

Good Man in the Middle

GitHub stars GitHub forks Release GitHub issues Build GitHub license Docs

利用MITM技术实现请求和返回的重写重定向阻断等操作

功能

  • 基于 TLS ClientHello 的自动证书签署
  • 支持选择性 MITM
  • 基于 YAML 格式的规则描述语言:重写/阻断/重定向
    • 灵活的规则匹配器
      • 域名前缀/后缀/全匹配
      • 正则匹配
      • 多筛选器规则
    • 灵活的文本内容改写
      • 抹除/替换
      • 正则替换
    • 灵活的字典类型内容改写
      • HTTP Header 改写
      • Cookie 改写
    • 支持单条规则多个行为
  • 支持 JavaScript 脚本规则 (编程介入)
  • 支持透明代理
  • 透明代理 HTTPS 和 HTTP 复用单端口
  • 支持自动安装 CA 证书到系统信任区

使用方法

证书准备

由于MITM技术的需要,需要你生成并信任自己的根证书

生成根证书

出于安全考虑,请不要随意信任任何陌生人提供的根证书,你需要自己生成属于自己的根证书和私钥

经验丰富的用户可以自行使用OpenSSL进行相关操作,考虑到没有相关经验的用户,可以使用以下命令直接生成相关内容,生成的证书和私钥将存储在ca目录下

good-mitm.exe genca

在浏览器使用了Good-MITM提供的代理后,通过访问 http://cert.mitm.plus 可以直接下载证书,这在给其他设备提供服务时非常有用

信任证书

你可以将根证书添加到操作系统或者浏览器的信任区中,根据你的需要自行选择

代理

启动Good-MITM,指定使用的规则文件或目录

good-mitm.exe run -r rules

在浏览器或操作系统中使用Good-MITM提供的http代理:http://127.0.0.1:34567

透明代理

See https://docs.mitmproxy.org/stable/howto-transparent/ for docs.

sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -w net.ipv6.conf.all.forwarding=1
sudo sysctl -w net.ipv4.conf.all.send_redirects=0

sudo useradd --create-home mitm
sudo -u mitm -H bash -c 'good-mitm run -r rules/log.yaml -b 0.0.0.0:34567'

sudo iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitm --dport 80 -j REDIRECT --to-port 34567
sudo iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitm --dport 443 -j REDIRECT --to-port 34567
sudo ip6tables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitm --dport 80 -j REDIRECT --to-port 34567
sudo ip6tables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner mitm --dport 443 -j REDIRECT --to-port 34567

Rule 规则

Rule用来操控 Good-MITM

一条合格的规则需要包含以下内容:

  • 规则名:用来区分不同的规则,便与维护
  • 筛选器:用于从众多请求返回中筛选出需要处理的内容
  • 动作:用于执行想要的行为,包括重定向阻断修改
  • 必要时指定需要MITM的域名
- name: "屏蔽Yutube追踪"
  mitm: "*.youtube.com"
  filter:
    url-regex: '^https?:\/\/(www|s)\.youtube\.com\/(pagead|ptracking)'
  action: reject

同时一条合格的规则需要符合以下要求:

  • 专注:一条规则只用来做一件事
  • 简单:使用简单的方法来处理,便与维护
  • 高效:尽量使用高效的方法,比如使用域名后缀和域名前缀来替换域名正则表达式

Filter 筛选器

Filter用来筛选需要处理的请求和返回

候选项

Filter目前包含以下类型:

  • All
  • Domain(String)
  • DomainKeyword(String)
  • DomainPrefix(String)
  • DomainSuffix(String)
  • UrlRegex(fancy_regex::Regex)

注意
当前版本中,domain相关类型匹配的是host,通常情况下不会影响结果
在网站使用非常规端口时,规则需要注明端口
后续版本将会对此行为进行优化

All 全部

指定筛选器为all时将会命中全部请求和返回,通常用来执行日志记录行为

- name: "log"
  filter: all
  action:
    - log-req
    - log-res
Domain 域名

domain对域名进行全量匹配

- name: "redirect"
  filter:
    domain: 'none.zu1k.com'
  action:
    redirect: "https://zu1k.com/"
DomainKeyword 域名关键词

domain-keyword对域名进行关键词匹配

- name: "reject CSDN"
  filter:
    domain-keyword: 'csdn'
  action: reject
DomainPrefix 域名前缀

domain-prefix对域名进行前缀匹配

- name: "ad prefix"
  filter:
    domain-prefix: 'ads' // example: "ads.xxxxx.com"
  action: reject
DomainSuffix 域名后缀

domain-suffix对域名进行后缀匹配

- name: "redirect"
  filter:
    domain-suffix: 'google.com.cn'
  action:
    redirect: "https://google.com"
UrlRegex Url正则

url-regex对整个url进行正则匹配

- name: "youtube追踪"
  mitm: "*.youtube.com"
  filter:
    url-regex: '^https?:\/\/(www|s)\.youtube\.com\/(pagead|ptracking)'
  action: reject

多个筛选器

filters字段支持单个筛选器和多个筛选器,多个筛选器之间的关系为

- name: "youtube-2"
  mitm:
    - "*.youtube.com"
    - "*.googlevideo.com"
  filters:
    - url-regex: '^https?:\/\/[\w-]+\.googlevideo\.com\/(?!(dclk_video_ads|videoplayback\?)).+(&oad|ctier)'
    - url-regex: '^https?:\/\/(www|s)\.youtube\.com\/api\/stats\/ads'
    - url-regex: '^https?:\/\/(www|s)\.youtube\.com\/(pagead|ptracking)'
    - url-regex: '^https?:\/\/\s.youtube.com/api/stats/qoe?.*adformat='
  action: reject

具有相同动作的多个规则可聚合为一个规则以便于维护

Action 动作

Action 用来对请求或者返回进行操作

候选项

Action目前包含以下选项:

  • Reject
  • Redirect(String)
  • ModifyRequest(Modify)
  • ModifyResponse(Modify)
  • LogRes
  • LogReq
Reject 拒绝

reject类型直接返回502,用来拒绝某些请求,可以用来拒绝追踪和广告

- name: "reject CSDN"
  filter:
    domain-keyword: 'csdn'
  action: reject
Redirect 重定向

redirect类型直接返回302重定向

- name: "youtube-1"
  filter:
    url-regex: '(^https?:\/\/(?!redirector)[\w-]+\.googlevideo\.com\/(?!dclk_video_ads).+)(ctier=L)(&.+)'
  action:
    redirect: "$1$4"
ModifyRequest 修改请求

modify-request用来修改请求,具体修改规则见 修改器

ModifyResponse 修改返回

modify-response用来修改返回,具体修改规则见 修改器

Log 记录日志

log-req 用来记录请求,log-res 用来记录返回

多个动作

actions字段支持单个动作和多个动作,当需要执行多个动作时,应使用数组

- name: "youtube-1"
  filter:
    url-regex: '(^https?:\/\/(?!redirector)[\w-]+\.googlevideo\.com\/(?!dclk_video_ads).+)(ctier=L)(&.+)'
  actions:
    - log-req:
    - redirect: "$1$4"

修改器

修改器用来执行修改操作,包括修改请求和修改返回

候选项

根据需要修改的内容的位置,修改器分为以下几类:

  • Header(MapModify)
  • Cookie(MapModify)
  • Body(TextModify)
TextModify 文本修改器

TextModify 主要对文本就行修改,目前支持两种方式:

  • 直接设置文本内容
  • 普通替换或者正则替换
直接设置

对于plain类型直接设置,内容将被直接重置为指定文本

- name: "modify response body plain"
  filter:
    domain: '126.com'
  action:
    modify-response:
      body: "Hello 126.com, from Good-MITM"
替换

替换支持简单替换和正则替换两种

简单替换

- name: "modify response body replace"
  filter:
    domain-suffix: '163.com'
  action:
    modify-response:
      body:
        origin: "网易首页"
        new: "Good-MITM 首页"

正则替换

- name: "modify response body regex replace"
  filter:
    domain-suffix: 'zu1k.com'
  action:
    - modify-response:
        body:
          re: '(\d{4})'
          new: 'maybe $1'
MapModify 字典修改器

MapModify 字典修改器主要针对字典类型的位置进行修改,例如 headercookies

key 代表字典的键,必须指定

valueTextModify 类型,按照上文方法书写

如果指定 removetrue,则会删除该键值对

- name: "modify response header"
  filter:
    domain: '126.com'
  action:
    - modify-response:
        header:
          key: date
          value:
            origin: "2022"
            new: "1999"
    - modify-response:
        header:
          key: new-header-item
          value: Good-MITM
    - modify-response:
        header:
          key: server
          remove: true
Header 修改

MapModify 部分方法

Cookie 修改

与 Header 修改方法一致

如果指定 removetrue 还会同时对应的移除set-cookie

Body修改

TextModify 部分

License

Good-MITM © zu1k, Released under the MIT License.