[GH-ISSUE #3832] [Feature Request] 服务端好像没有防火墙类的插件?fail2ban 使用说明 #3047

Closed
opened 2026-05-05 13:58:16 -06:00 by gitea-mirror · 10 comments
Owner

Originally created by @doveppp on GitHub (Dec 7, 2023).
Original GitHub issue: https://github.com/fatedier/frp/issues/3832

Describe the feature request

最近服务器ssh被爆破上了挖矿病毒,看了下是内网穿透的原因,找了一圈服务端好像没有防火墙类的插件,在issues里找到了使用fail2ban的办法,但没有找到具体的配置过程,在此记录下,减少后人走的弯路。

安装过程就不说了,安装完成之后在/etc/fail2ban/filter.d/目录下新建frps-ssh.conf,写入:

[Definition]
failregex = \[I\] \[proxy\.go:\d+\] \[\w+\] \[\S+] get a user connection \[<HOST>:\d+\]

该文件是为了匹配frps的连接日志
之后将/etc/fail2ban/jail.conf 复制为 jail.local
在最后添加:

[frps]
enabled = true
# port = 7600	需要封禁的端口,注释的话就是全端口封禁,因为我中转了好几个ssh,所以就注释了
filter = frps-ssh	# 使用刚才新建的filter规则
logpath = <frps_log_path>
findtime = 10m	# 监测行为的时间窗口。如果在findtime时间内发生了达到触发条件的恶意行为次数,那么触发封禁。
bantime  = 600m	# 触发限制之后的限制时间
maxretry = 3 	# 时间窗口内达到3次就封禁。

配置好之后重启fail2ban服务即可
以上

Describe alternatives you've considered

No response

Affected area

  • Docs
  • Installation
  • Performance and Scalability
  • Security
  • User Experience
  • Test and Release
  • Developer Infrastructure
  • Client Plugin
  • Server Plugin
  • Extensions
  • Others
Originally created by @doveppp on GitHub (Dec 7, 2023). Original GitHub issue: https://github.com/fatedier/frp/issues/3832 ### Describe the feature request 最近服务器ssh被爆破上了挖矿病毒,看了下是内网穿透的原因,找了一圈服务端好像没有防火墙类的插件,在issues里找到了使用fail2ban的办法,但没有找到具体的配置过程,在此记录下,减少后人走的弯路。 安装过程就不说了,安装完成之后在/etc/fail2ban/filter.d/目录下新建frps-ssh.conf,写入: ``` [Definition] failregex = \[I\] \[proxy\.go:\d+\] \[\w+\] \[\S+] get a user connection \[<HOST>:\d+\] ``` 该文件是为了匹配frps的连接日志 之后将/etc/fail2ban/jail.conf 复制为 jail.local 在最后添加: ``` [frps] enabled = true # port = 7600 需要封禁的端口,注释的话就是全端口封禁,因为我中转了好几个ssh,所以就注释了 filter = frps-ssh # 使用刚才新建的filter规则 logpath = <frps_log_path> findtime = 10m # 监测行为的时间窗口。如果在findtime时间内发生了达到触发条件的恶意行为次数,那么触发封禁。 bantime = 600m # 触发限制之后的限制时间 maxretry = 3 # 时间窗口内达到3次就封禁。 ``` 配置好之后重启fail2ban服务即可 以上 ### Describe alternatives you've considered _No response_ ### Affected area - [ ] Docs - [ ] Installation - [ ] Performance and Scalability - [ ] Security - [ ] User Experience - [ ] Test and Release - [ ] Developer Infrastructure - [ ] Client Plugin - [ ] Server Plugin - [ ] Extensions - [ ] Others
Author
Owner

@doveppp commented on GitHub (Dec 7, 2023):

然而,效果并不明显,别人的爆破脚本很机智,不会一直爆破,有间隔时间:

2023/12/07 16:50:43 [I] [proxy.go:199] [6e2520c38da01d2c] [ssh-gpu3] get a user connection [92.118.39.17:56696]
2023/12/07 16:50:43 [I] [proxy.go:199] [efde4dbb727a373f] [ssh-gpu4] get a user connection [92.118.39.17:53150]
2023/12/07 16:50:46 [I] [proxy.go:199] [9ddfe9937872a217] [ssh-gpu1] get a user connection [206.189.203.247:41642]
2023/12/07 16:50:46 [I] [proxy.go:199] [efde4dbb727a373f] [ssh-gpu4] get a user connection [206.189.203.247:49426]
2023/12/07 16:50:47 [I] [proxy.go:199] [efde4dbb727a373f] [ssh-gpu4] get a user connection [182.253.108.50:41519]
2023/12/07 16:51:20 [I] [proxy.go:199] [9ddfe9937872a217] [ssh-gpu1] get a user connection [128.199.0.176:38982]
2023/12/07 16:51:20 [I] [proxy.go:199] [efde4dbb727a373f] [ssh-gpu4] get a user connection [128.199.0.176:35414]
2023/12/07 16:51:32 [I] [proxy.go:199] [9ddfe9937872a217] [ssh-gpu1] get a user connection [92.118.39.117:44018]
2023/12/07 16:51:44 [I] [proxy.go:199] [6e2520c38da01d2c] [ssh-gpu3] get a user connection [172.245.91.171:33770]
2023/12/07 16:51:44 [I] [proxy.go:199] [efde4dbb727a373f] [ssh-gpu4] get a user connection [172.245.91.171:60388]

半小时后仅仅才ban了4个ip:

Status for the jail: frps
|- Filter
|  |- Currently failed: 30
|  |- Total failed:     252
|  `- File list:        /var/log/frps.log
`- Actions
   |- Currently banned: 4
   |- Total banned:     4
   `- Banned IP list:   170.64.204.132 170.64.204.218 91.92.255.62 175.6.102.248

暂未找到更好的解决办法

<!-- gh-comment-id:1844938528 --> @doveppp commented on GitHub (Dec 7, 2023): 然而,效果并不明显,别人的爆破脚本很机智,不会一直爆破,有间隔时间: ``` 2023/12/07 16:50:43 [I] [proxy.go:199] [6e2520c38da01d2c] [ssh-gpu3] get a user connection [92.118.39.17:56696] 2023/12/07 16:50:43 [I] [proxy.go:199] [efde4dbb727a373f] [ssh-gpu4] get a user connection [92.118.39.17:53150] 2023/12/07 16:50:46 [I] [proxy.go:199] [9ddfe9937872a217] [ssh-gpu1] get a user connection [206.189.203.247:41642] 2023/12/07 16:50:46 [I] [proxy.go:199] [efde4dbb727a373f] [ssh-gpu4] get a user connection [206.189.203.247:49426] 2023/12/07 16:50:47 [I] [proxy.go:199] [efde4dbb727a373f] [ssh-gpu4] get a user connection [182.253.108.50:41519] 2023/12/07 16:51:20 [I] [proxy.go:199] [9ddfe9937872a217] [ssh-gpu1] get a user connection [128.199.0.176:38982] 2023/12/07 16:51:20 [I] [proxy.go:199] [efde4dbb727a373f] [ssh-gpu4] get a user connection [128.199.0.176:35414] 2023/12/07 16:51:32 [I] [proxy.go:199] [9ddfe9937872a217] [ssh-gpu1] get a user connection [92.118.39.117:44018] 2023/12/07 16:51:44 [I] [proxy.go:199] [6e2520c38da01d2c] [ssh-gpu3] get a user connection [172.245.91.171:33770] 2023/12/07 16:51:44 [I] [proxy.go:199] [efde4dbb727a373f] [ssh-gpu4] get a user connection [172.245.91.171:60388] ``` 半小时后仅仅才ban了4个ip: ``` Status for the jail: frps |- Filter | |- Currently failed: 30 | |- Total failed: 252 | `- File list: /var/log/frps.log `- Actions |- Currently banned: 4 |- Total banned: 4 `- Banned IP list: 170.64.204.132 170.64.204.218 91.92.255.62 175.6.102.248 ``` 暂未找到更好的解决办法
Author
Owner

@fatedier commented on GitHub (Dec 7, 2023):

在未来的版本重构之后,会计划增加 ip 白名单的功能。

但是防火墙是很复杂的能力,也不是项目核心,目前可以尝试通过服务端插件的功能进行扩展,https://github.com/fatedier/frp/blob/dev/doc/server_plugin.md#newuserconn
效果怎么样不确定。

<!-- gh-comment-id:1844950103 --> @fatedier commented on GitHub (Dec 7, 2023): 在未来的版本重构之后,会计划增加 ip 白名单的功能。 但是防火墙是很复杂的能力,也不是项目核心,目前可以尝试通过服务端插件的功能进行扩展,https://github.com/fatedier/frp/blob/dev/doc/server_plugin.md#newuserconn 效果怎么样不确定。
Author
Owner

@doveppp commented on GitHub (Dec 7, 2023):

不知是否可以屏蔽那些多次在短时间内创建连接并关闭的ip,等有时间了尝试写一下插件试试

<!-- gh-comment-id:1844985882 --> @doveppp commented on GitHub (Dec 7, 2023): 不知是否可以屏蔽那些多次在短时间内创建连接并关闭的ip,等有时间了尝试写一下插件试试
Author
Owner

@duchenpaul commented on GitHub (Dec 27, 2023):

可以考虑更严格的fail2ban策略,比如失败3次ban一年

<!-- gh-comment-id:1870128103 --> @duchenpaul commented on GitHub (Dec 27, 2023): 可以考虑更严格的fail2ban策略,比如失败3次ban一年
Author
Owner

@doveppp commented on GitHub (Dec 27, 2023):

目前的策略是大时间窗口检测,24小时内触发250次就ban。

<!-- gh-comment-id:1870140291 --> @doveppp commented on GitHub (Dec 27, 2023): 目前的策略是大时间窗口检测,24小时内触发250次就ban。
Author
Owner

@doveppp commented on GitHub (Dec 27, 2023):

失败3次不行,frps没办法判断这个连接是成功了还是失败了

<!-- gh-comment-id:1870141299 --> @doveppp commented on GitHub (Dec 27, 2023): 失败3次不行,frps没办法判断这个连接是成功了还是失败了
Author
Owner

@pansila commented on GitHub (Jan 10, 2024):

为了更准确一点,可以结合 #2470 里面介绍的方法,从frpc client端拿到真实ip,重写client端fail2ban的sshd的action,发送结果到frps server端(再打洞nc发过去?),然后server的fail2ban再接力自定义filter+action把这个ip ban掉。

更简单一点的办法是,从client中过滤出fail的auth log,然后写到server端的syslog里面去,由server端的fail2ban自动处理这些非法访问。

jail.conf

[sshd]
mode = aggressive
enabled = true
# use systemd-journal if /var/log/auth.log doesn't exist
logpath = journal
backend = systemd
maxRetry = 1
banTime = 1s
banaction = report2frps
action = %(banaction)s[port="%(port)s", protocol="%(protocol)s"]

maxRetry和banTime尽量改小是因为,我们把报告事件当成ban action,这两个频率不一样,需要让server尽量感知变化。

action.d/report2frps.conf

[Definition]
actionban = sudo -u <username> ssh <ssh_username>@<frps_server> -p <frps_server_port> <logger_template>

[Init]
# server and port to report
frps_server = x.x.x.x
frps_server_port = 22
# sudo with the user and its ssh key
username = uuu
# ssh username
ssh_username = sss
# logger template, dummy port 123123, doesn't matter
logger_template = "logger -t 'sshd' -i -p auth.info Invalid user frpc_fail_report from <ip> port 123123"

最后因为复用了sshd的filter和action,默认只会ban ssh默认的port(22),需要把内网转发的port(<ddd>自行替换)也加到规则里

sudo iptables -R INPUT 1  -j f2b-sshd -p tcp -m multiport --dports ssh,<ddd>

或者server端jail.conf里面把iptables改成iptables-allport

[sshd]
...
banaction = iptables-allports
...
<!-- gh-comment-id:1885101996 --> @pansila commented on GitHub (Jan 10, 2024): 为了更准确一点,可以结合 #2470 里面介绍的方法,从frpc client端拿到真实ip,<strike>重写client端fail2ban的sshd的action,发送结果到frps server端(再打洞nc发过去?),然后server的fail2ban再接力自定义filter+action把这个ip ban掉。</strike> 更简单一点的办法是,从client中过滤出fail的auth log,然后写到server端的syslog里面去,由server端的fail2ban自动处理这些非法访问。 jail.conf ``` [sshd] mode = aggressive enabled = true # use systemd-journal if /var/log/auth.log doesn't exist logpath = journal backend = systemd maxRetry = 1 banTime = 1s banaction = report2frps action = %(banaction)s[port="%(port)s", protocol="%(protocol)s"] ``` maxRetry和banTime尽量改小是因为,我们把报告事件当成ban action,这两个频率不一样,需要让server尽量感知变化。 action.d/report2frps.conf ``` [Definition] actionban = sudo -u <username> ssh <ssh_username>@<frps_server> -p <frps_server_port> <logger_template> [Init] # server and port to report frps_server = x.x.x.x frps_server_port = 22 # sudo with the user and its ssh key username = uuu # ssh username ssh_username = sss # logger template, dummy port 123123, doesn't matter logger_template = "logger -t 'sshd' -i -p auth.info Invalid user frpc_fail_report from <ip> port 123123" ``` 最后因为复用了sshd的filter和action,默认只会ban ssh默认的port(22),需要把内网转发的port(\<ddd\>自行替换)也加到规则里 ``` sudo iptables -R INPUT 1 -j f2b-sshd -p tcp -m multiport --dports ssh,<ddd> ``` 或者server端jail.conf里面把iptables改成iptables-allport ``` [sshd] ... banaction = iptables-allports ... ```
Author
Owner

@SwimmingLiu commented on GitHub (Jan 3, 2025):

@pansila 您好,请问如果使用了跳板机的话,从跳板机经frp进去的ip都是127.0.0.1。没办法识别攻击者的ip怎么办呢?

<!-- gh-comment-id:2569012148 --> @SwimmingLiu commented on GitHub (Jan 3, 2025): @pansila 您好,请问如果使用了跳板机的话,从跳板机经`frp`进去的`ip`都是`127.0.0.1`。没办法识别攻击者的`ip`怎么办呢?
Author
Owner

@JsonSong89 commented on GitHub (Jan 20, 2025):

@pansila 您好,请问如果使用了跳板机的话,从跳板机经frp进去的ip都是127.0.0.1。没办法识别攻击者的ip怎么办呢?

那你在跳板机处理ip啊

<!-- gh-comment-id:2601604355 --> @JsonSong89 commented on GitHub (Jan 20, 2025): > [@pansila](https://github.com/pansila) 您好,请问如果使用了跳板机的话,从跳板机经`frp`进去的`ip`都是`127.0.0.1`。没办法识别攻击者的`ip`怎么办呢? 那你在跳板机处理ip啊
Author
Owner

@JsonSong89 commented on GitHub (Jan 20, 2025):

我是用服务端插件处理的
其实代码也没几行啊,
hono.js写的:
自行维护IpList Set

app.post("handle", async (c, next) => {
    let req = await c.req.json() as FrpsRpcReq
    const checkResult = checkFrpsRpcReq(req)
    if (checkResult) {
        return c.json({"reject": false, "unchange": true})
    } else {
        return c.json({"reject": true, "reject_reason": "invalid user"})
    }
});

function checkFrpsRpcReq(req: FrpsRpcReq): boolean {
    const userConnFlag = req && req.op === "NewUserConn"
    // 只判断用户连接请求
    if (!userConnFlag) return true
    //只处理tcp和名称以"_fp"结尾的代理
    const {user, proxy_type, remote_addr, proxy_name} = req.content
    const securityFlag = proxy_type === "tcp" &&  proxy_name.endsWith("_fp")
    if (!securityFlag) return true
    let ip = getUserIp(remote_addr)
    //过滤安全ip
    return IpList.has(ip);
}
<!-- gh-comment-id:2601608431 --> @JsonSong89 commented on GitHub (Jan 20, 2025): 我是用服务端插件处理的 其实代码也没几行啊, hono.js写的: 自行维护IpList Set ```ts app.post("handle", async (c, next) => { let req = await c.req.json() as FrpsRpcReq const checkResult = checkFrpsRpcReq(req) if (checkResult) { return c.json({"reject": false, "unchange": true}) } else { return c.json({"reject": true, "reject_reason": "invalid user"}) } }); function checkFrpsRpcReq(req: FrpsRpcReq): boolean { const userConnFlag = req && req.op === "NewUserConn" // 只判断用户连接请求 if (!userConnFlag) return true //只处理tcp和名称以"_fp"结尾的代理 const {user, proxy_type, remote_addr, proxy_name} = req.content const securityFlag = proxy_type === "tcp" && proxy_name.endsWith("_fp") if (!securityFlag) return true let ip = getUserIp(remote_addr) //过滤安全ip return IpList.has(ip); } ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/frp#3047
No description provided.