2023-11-16 06:40:08 +00:00
|
|
|
package toolbox
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/1Panel-dev/1Panel/backend/global"
|
|
|
|
"github.com/1Panel-dev/1Panel/backend/utils/cmd"
|
|
|
|
"github.com/1Panel-dev/1Panel/backend/utils/systemctl"
|
|
|
|
)
|
|
|
|
|
2023-11-27 06:04:08 +00:00
|
|
|
type Fail2ban struct{}
|
2023-11-16 06:40:08 +00:00
|
|
|
|
|
|
|
const defaultPath = "/etc/fail2ban/jail.local"
|
|
|
|
|
|
|
|
type FirewallClient interface {
|
2024-05-20 10:48:42 +00:00
|
|
|
Status() (bool, bool, bool)
|
2023-11-16 06:40:08 +00:00
|
|
|
Version() (string, error)
|
|
|
|
Operate(operate string) error
|
|
|
|
OperateSSHD(operate, ip string) error
|
|
|
|
}
|
|
|
|
|
2023-11-27 06:04:08 +00:00
|
|
|
func NewFail2Ban() (*Fail2ban, error) {
|
2023-11-16 06:40:08 +00:00
|
|
|
isExist, _ := systemctl.IsExist("fail2ban.service")
|
|
|
|
if isExist {
|
|
|
|
if _, err := os.Stat(defaultPath); err != nil {
|
|
|
|
if err := initLocalFile(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-12-07 11:02:07 +00:00
|
|
|
stdout, err := cmd.Exec("systemctl restart fail2ban.service")
|
2023-11-16 06:40:08 +00:00
|
|
|
if err != nil {
|
2023-12-07 11:02:07 +00:00
|
|
|
global.LOG.Errorf("restart fail2ban failed, err: %s", stdout)
|
2023-11-16 06:40:08 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-11-27 06:04:08 +00:00
|
|
|
return &Fail2ban{}, nil
|
2023-11-16 06:40:08 +00:00
|
|
|
}
|
|
|
|
|
2023-11-27 06:04:08 +00:00
|
|
|
func (f *Fail2ban) Status() (bool, bool, bool) {
|
2023-11-16 06:40:08 +00:00
|
|
|
isEnable, _ := systemctl.IsEnable("fail2ban.service")
|
|
|
|
isActive, _ := systemctl.IsActive("fail2ban.service")
|
|
|
|
isExist, _ := systemctl.IsExist("fail2ban.service")
|
|
|
|
|
|
|
|
return isEnable, isActive, isExist
|
|
|
|
}
|
|
|
|
|
2023-11-27 06:04:08 +00:00
|
|
|
func (f *Fail2ban) Version() string {
|
2023-11-16 06:40:08 +00:00
|
|
|
stdout, err := cmd.Exec("fail2ban-client version")
|
|
|
|
if err != nil {
|
|
|
|
global.LOG.Errorf("load the fail2ban version failed, err: %s", stdout)
|
|
|
|
return "-"
|
|
|
|
}
|
|
|
|
return strings.ReplaceAll(stdout, "\n", "")
|
|
|
|
}
|
|
|
|
|
2023-11-27 06:04:08 +00:00
|
|
|
func (f *Fail2ban) Operate(operate string) error {
|
2023-11-16 06:40:08 +00:00
|
|
|
switch operate {
|
|
|
|
case "start", "restart", "stop", "enable", "disable":
|
|
|
|
stdout, err := cmd.Execf("systemctl %s fail2ban.service", operate)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("%s the fail2ban.service failed, err: %s", operate, stdout)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
case "reload":
|
|
|
|
stdout, err := cmd.Exec("fail2ban-client reload")
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("fail2ban-client reload, err: %s", stdout)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("not support such operation: %v", operate)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-27 06:04:08 +00:00
|
|
|
func (f *Fail2ban) ReBanIPs(ips []string) error {
|
2023-11-16 06:40:08 +00:00
|
|
|
ipItems, _ := f.ListBanned()
|
|
|
|
stdout, err := cmd.Execf("fail2ban-client unban --all")
|
|
|
|
if err != nil {
|
|
|
|
stdout1, err := cmd.Execf("fail2ban-client set sshd banip %s", strings.Join(ipItems, " "))
|
|
|
|
if err != nil {
|
|
|
|
global.LOG.Errorf("rebanip after fail2ban-client unban --all failed, err: %s", stdout1)
|
|
|
|
}
|
|
|
|
return fmt.Errorf("fail2ban-client unban --all failed, err: %s", stdout)
|
|
|
|
}
|
|
|
|
stdout1, err := cmd.Execf("fail2ban-client set sshd banip %s", strings.Join(ips, " "))
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("handle `fail2ban-client set sshd banip %s` failed, err: %s", strings.Join(ips, " "), stdout1)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-11-27 06:04:08 +00:00
|
|
|
func (f *Fail2ban) ListBanned() ([]string, error) {
|
2023-11-16 06:40:08 +00:00
|
|
|
var lists []string
|
2024-01-02 13:56:28 +00:00
|
|
|
stdout, err := cmd.Exec("fail2ban-client status sshd | grep 'Banned IP list:'")
|
2023-11-16 06:40:08 +00:00
|
|
|
if err != nil {
|
|
|
|
return lists, err
|
|
|
|
}
|
2024-01-02 13:56:28 +00:00
|
|
|
itemList := strings.Split(strings.Trim(stdout, "\n"), "Banned IP list:")
|
|
|
|
if len(itemList) != 2 {
|
|
|
|
return lists, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
ips := strings.Fields(itemList[1])
|
|
|
|
for _, item := range ips {
|
2023-12-08 07:40:07 +00:00
|
|
|
if len(item) != 0 {
|
|
|
|
lists = append(lists, item)
|
|
|
|
}
|
2023-11-16 06:40:08 +00:00
|
|
|
}
|
|
|
|
return lists, nil
|
|
|
|
}
|
|
|
|
|
2023-11-27 06:04:08 +00:00
|
|
|
func (f *Fail2ban) ListIgnore() ([]string, error) {
|
2023-11-16 06:40:08 +00:00
|
|
|
var lists []string
|
|
|
|
stdout, err := cmd.Exec("fail2ban-client get sshd ignoreip")
|
|
|
|
if err != nil {
|
|
|
|
return lists, err
|
|
|
|
}
|
|
|
|
stdout = strings.ReplaceAll(stdout, "|", "")
|
|
|
|
stdout = strings.ReplaceAll(stdout, "`", "")
|
|
|
|
stdout = strings.ReplaceAll(stdout, "\n", "")
|
|
|
|
addrs := strings.Split(stdout, "-")
|
|
|
|
for _, addr := range addrs {
|
|
|
|
if !strings.HasPrefix(addr, " ") {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
lists = append(lists, strings.ReplaceAll(addr, " ", ""))
|
|
|
|
}
|
|
|
|
return lists, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func initLocalFile() error {
|
|
|
|
if _, err := os.Create(defaultPath); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
initFile := `#DEFAULT-START
|
|
|
|
[DEFAULT]
|
|
|
|
bantime = 600
|
|
|
|
findtime = 300
|
|
|
|
maxretry = 5
|
2023-12-06 09:22:11 +00:00
|
|
|
banaction = $banaction
|
2023-11-16 06:40:08 +00:00
|
|
|
action = %(action_mwl)s
|
|
|
|
#DEFAULT-END
|
|
|
|
|
|
|
|
[sshd]
|
|
|
|
ignoreip = 127.0.0.1/8
|
|
|
|
enabled = true
|
|
|
|
filter = sshd
|
|
|
|
port = 22
|
|
|
|
maxretry = 5
|
|
|
|
findtime = 300
|
|
|
|
bantime = 600
|
2023-12-08 07:40:07 +00:00
|
|
|
banaction = $banaction
|
2023-11-16 06:40:08 +00:00
|
|
|
action = %(action_mwl)s
|
2023-12-07 06:40:07 +00:00
|
|
|
logpath = $logpath`
|
2023-12-06 09:22:11 +00:00
|
|
|
|
|
|
|
banaction := ""
|
|
|
|
if active, _ := systemctl.IsActive("firewalld"); active {
|
|
|
|
banaction = "firewallcmd-ipset"
|
|
|
|
} else if active, _ := systemctl.IsActive("ufw"); active {
|
|
|
|
banaction = "ufw"
|
|
|
|
} else {
|
|
|
|
banaction = "iptables-allports"
|
|
|
|
}
|
|
|
|
initFile = strings.ReplaceAll(initFile, "$banaction", banaction)
|
2023-12-07 06:40:07 +00:00
|
|
|
|
|
|
|
logPath := ""
|
|
|
|
if _, err := os.Stat("/var/log/secure"); err == nil {
|
|
|
|
logPath = "/var/log/secure"
|
|
|
|
} else {
|
|
|
|
logPath = "/var/log/auth.log"
|
|
|
|
}
|
|
|
|
initFile = strings.ReplaceAll(initFile, "$logpath", logPath)
|
2023-11-16 06:40:08 +00:00
|
|
|
if err := os.WriteFile(defaultPath, []byte(initFile), 0640); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|