Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
11 tasks
doveppp opened this issue Dec 7, 2023 · 10 comments
Closed
11 tasks

Comments

@doveppp
Copy link

doveppp commented Dec 7, 2023

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
@doveppp
Copy link
Author

doveppp commented 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

暂未找到更好的解决办法

@doveppp doveppp closed this as completed Dec 7, 2023
@fatedier
Copy link
Owner

fatedier commented Dec 7, 2023

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

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

@doveppp
Copy link
Author

doveppp commented Dec 7, 2023

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

@duchenpaul
Copy link

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

@doveppp
Copy link
Author

doveppp commented Dec 27, 2023

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

@doveppp
Copy link
Author

doveppp commented Dec 27, 2023

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

@pansila
Copy link

pansila commented 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.local

[sshd]
mode = aggressive
enabled = true
maxRetry = 1
banTime = 1s
banaction = report2frps
action = %(banaction)s[port="%(port)s", protocol="%(protocol)s"]

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

action.d/report2frps.local

[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
logger_template = "logger -t 'sshd' -i -p auth.info Invalid user frpc_fail_report from <ip> port 123123"

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

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

或者server段jail.local里面把iptables改成iptables-allport

[sshd]
...
banaction = iptables-allports
...

@SwimmingLiu
Copy link

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

@JsonSong89
Copy link

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

那你在跳板机处理ip啊

@JsonSong89
Copy link

我是用服务端插件处理的
其实代码也没几行啊,
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);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants