系统防火墙:linux和windows分离

This commit is contained in:
samwaf
2023-08-04 15:36:17 +08:00
parent dadb7a88a3
commit 66d0acc1fb
4 changed files with 153 additions and 91 deletions
+13 -79
View File
@@ -1,9 +1,10 @@
//go:build linux
package firewall
import (
"bufio"
"fmt"
"golang.org/x/sys/windows/registry"
"golang.org/x/text/encoding/simplifiedchinese"
"os/exec"
"runtime"
@@ -31,19 +32,6 @@ func (fw *FireWallEngine) IsFirewallEnabled() bool {
return false
}
return len(out) > 0
} else if runtime.GOOS == "windows" {
const firewallRegistryPath = `SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile`
key, err := registry.OpenKey(registry.LOCAL_MACHINE, firewallRegistryPath, registry.QUERY_VALUE)
if err != nil {
return false
}
defer key.Close()
enabled, _, err := key.GetIntegerValue("EnableFirewall")
if err != nil {
return false
}
return enabled == 1
}
return false
}
@@ -67,82 +55,28 @@ func (fw *FireWallEngine) executeCommand(cmd *exec.Cmd) (error error, printstr s
}
func (fw *FireWallEngine) AddRule(ruleName, ipToAdd, action, proc, localport string) error {
var cmd *exec.Cmd
if runtime.GOOS == "linux" {
cmd = exec.Command("iptables", "-A", "INPUT", ipToAdd)
} else if runtime.GOOS == "windows" {
/*s := fmt.Sprintf(`netsh advfirewall firewall add rule name="%s" dir=in action=allow protocol=TCP localport=8080 remoteip=%s`, ruleName, ipToAdd)
cmd = exec.Command("netsh", s)*/
/*cmd = exec.Command("netsh", "advfirewall", "firewall", "add", "rule",
fmt.Sprintf(`name="%s"`, ruleName),
fmt.Sprintf(`dir=in action=allow protocol=TCP localport=8080 remoteip=%s`, ipToAdd),
)*/
cmd = exec.Command("netsh", "advfirewall", "firewall", "add", "rule",
"name="+ruleName, "dir=in", "action="+action, "protocol="+proc, "localport="+localport,
"remoteip="+ipToAdd,
)
} else {
return fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
}
cmd := exec.Command("iptables", "-A", "INPUT", ipToAdd)
err, _ := fw.executeCommand(cmd)
return err
}
/*func (fw *FireWallEngine) EditRule(ruleNum int, newRule string) error {
func (fw *FireWallEngine) EditRule(ruleNum int, newRule string) error {
return fmt.Errorf("editRule is not supported on Windows")
}*/
}
func (fw *FireWallEngine) DeleteRule(ruleName string) (bool, error) {
var cmd *exec.Cmd
if runtime.GOOS == "linux" {
cmd = exec.Command("iptables", "-D", "INPUT", fmt.Sprintf("%s", ruleName))
} else if runtime.GOOS == "windows" {
cmd = exec.Command("netsh", "advfirewall", "firewall", "delete", "rule", fmt.Sprintf("name=%s", ruleName))
err, output := fw.executeCommand(cmd)
fmt.Println(output)
//已删除 1 规则。确定。
if err == nil {
if strings.Contains(output, "No rules match the specified criteria") {
return false, fmt.Errorf("error:delete firewall rule: %s, output: %s", ruleName, output)
}
if strings.Contains(output, "没有与指定标准相匹配的规则。") {
return false, fmt.Errorf("error:delete firewall rule: %s, output: %s", ruleName, output)
}
if strings.Contains(output, "已删除") {
return true, nil
}
} else {
return false, fmt.Errorf("error:delete firewall rule: %s, output: %s", ruleName, output)
}
}
return false, fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
cmd = exec.Command("iptables", "-D", "INPUT", fmt.Sprintf("%s", ruleName))
err, _ := fw.executeCommand(cmd)
return false, err
}
func (fw *FireWallEngine) IsRuleExists(ruleName string) (bool, error) {
if runtime.GOOS == "linux" {
cmd := exec.Command("iptables-save")
output, err := cmd.CombinedOutput()
if err != nil {
return false, fmt.Errorf("failed to list iptables rules: %s, output: %s", err, string(output))
}
return strings.Contains(string(output), "-A INPUT -s "+ruleName+" -j ACCEPT"), nil
} else if runtime.GOOS == "windows" {
cmd := exec.Command("netsh", "advfirewall", "firewall", "show", "rule", "name="+ruleName)
err, output := fw.executeCommand(cmd)
if err == nil {
if strings.Contains(output, "No rules match the specified criteria") {
return false, nil
}
if strings.Contains(output, "没有与指定标准相匹配的规则。") {
return false, nil
}
if strings.Contains(output, " "+ruleName+"-----") {
return true, nil
}
} else {
return false, fmt.Errorf("failed to show firewall rule: %s, output: %s", err, string(output))
}
cmd := exec.Command("iptables-save")
output, err := cmd.CombinedOutput()
if err != nil {
return false, fmt.Errorf("failed to list iptables rules: %s, output: %s", err, string(output))
}
return false, fmt.Errorf("unsupported operating system: %s", runtime.GOOS)
return strings.Contains(string(output), "-A INPUT -s "+ruleName+" -j ACCEPT"), nil
}
func ConvertByte2String(byte []byte, charset Charset) string {
var str string
+11 -12
View File
@@ -48,19 +48,18 @@ func TestFireWallEngine_DeleteRule(t *testing.T) {
}
/*
func TestFireWallEngine_EditRule(t *testing.T) {
fw := FireWallEngine{}
// Edit an existing firewall rule (not supported on Windows)
ruleNum := 1
newRule := "-p tcp --dport 8080 -j DROP"
if err := fw.EditRule(ruleNum, newRule); err != nil {
fmt.Println("Failed to edit firewall rule:", err)
} else {
fmt.Println("Firewall rule edited successfully.")
}
func TestFireWallEngine_EditRule(t *testing.T) {
fw := FireWallEngine{}
// Edit an existing firewall rule (not supported on Windows)
ruleNum := 1
newRule := "-p tcp --dport 8080 -j DROP"
if err := fw.EditRule(ruleNum, newRule); err != nil {
fmt.Println("Failed to edit firewall rule:", err)
} else {
fmt.Println("Firewall rule edited successfully.")
}
*/
}
func TestFireWallEngine_IsFirewallEnabled(t *testing.T) {
fw := FireWallEngine{}
+127
View File
@@ -0,0 +1,127 @@
//go:build !linux
package firewall
import (
"bufio"
"fmt"
"golang.org/x/sys/windows/registry"
"golang.org/x/text/encoding/simplifiedchinese"
"os/exec"
"strings"
)
type Charset string
const (
UTF8 = Charset("UTF-8")
GB18030 = Charset("GB18030")
)
const ACTION_ALLOW string = "allow" //allow 表示允许连接,block 表示阻止连接,bypass 表示只允许安全连接。 =
const ACTION_BLOCK string = "block"
const ACTION_BYPASS string = "bypass"
type FireWallEngine struct {
}
func (fw *FireWallEngine) IsFirewallEnabled() bool {
const firewallRegistryPath = `SYSTEM\CurrentControlSet\Services\SharedAccess\Parameters\FirewallPolicy\StandardProfile`
key, err := registry.OpenKey(registry.LOCAL_MACHINE, firewallRegistryPath, registry.QUERY_VALUE)
if err != nil {
return false
}
defer key.Close()
enabled, _, err := key.GetIntegerValue("EnableFirewall")
if err != nil {
return false
}
return enabled == 1
}
func (fw *FireWallEngine) executeCommand(cmd *exec.Cmd) (error error, printstr string) {
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println(err)
return err, err.Error()
}
cmd.Start()
in := bufio.NewScanner(stdout)
printstr = ""
for in.Scan() {
cmdRe := ConvertByte2String(in.Bytes(), "GB18030")
//fmt.Println(cmdRe)
printstr += cmdRe
}
cmd.Wait()
return nil, printstr
}
func (fw *FireWallEngine) AddRule(ruleName, ipToAdd, action, proc, localport string) error {
/*s := fmt.Sprintf(`netsh advfirewall firewall add rule name="%s" dir=in action=allow protocol=TCP localport=8080 remoteip=%s`, ruleName, ipToAdd)
cmd = exec.Command("netsh", s)*/
/*cmd = exec.Command("netsh", "advfirewall", "firewall", "add", "rule",
fmt.Sprintf(`name="%s"`, ruleName),
fmt.Sprintf(`dir=in action=allow protocol=TCP localport=8080 remoteip=%s`, ipToAdd),
)*/
cmd := exec.Command("netsh", "advfirewall", "firewall", "add", "rule",
"name="+ruleName, "dir=in", "action="+action, "protocol="+proc, "localport="+localport,
"remoteip="+ipToAdd,
)
err, _ := fw.executeCommand(cmd)
return err
}
func (fw *FireWallEngine) EditRule(ruleNum int, newRule string) error {
return fmt.Errorf("editRule is not supported on Windows")
}
func (fw *FireWallEngine) DeleteRule(ruleName string) (bool, error) {
cmd := exec.Command("netsh", "advfirewall", "firewall", "delete", "rule", fmt.Sprintf("name=%s", ruleName))
err, output := fw.executeCommand(cmd)
fmt.Println(output)
//已删除 1 规则。确定。
if err == nil {
if strings.Contains(output, "No rules match the specified criteria") {
return false, fmt.Errorf("error:delete firewall rule: %s, output: %s", ruleName, output)
}
if strings.Contains(output, "没有与指定标准相匹配的规则。") {
return false, fmt.Errorf("error:delete firewall rule: %s, output: %s", ruleName, output)
}
if strings.Contains(output, "已删除") {
return true, nil
}
}
return false, fmt.Errorf("error:delete firewall rule: %s, output: %s", ruleName, output)
}
func (fw *FireWallEngine) IsRuleExists(ruleName string) (bool, error) {
cmd := exec.Command("netsh", "advfirewall", "firewall", "show", "rule", "name="+ruleName)
err, output := fw.executeCommand(cmd)
if err == nil {
if strings.Contains(output, "No rules match the specified criteria") {
return false, nil
}
if strings.Contains(output, "没有与指定标准相匹配的规则。") {
return false, nil
}
if strings.Contains(output, " "+ruleName+"-----") {
return true, nil
}
}
return false, fmt.Errorf("failed to show firewall rule: %s, output: %s", err, string(output))
}
func ConvertByte2String(byte []byte, charset Charset) string {
var str string
switch charset {
case GB18030:
var decodeBytes, _ = simplifiedchinese.GB18030.NewDecoder().Bytes(byte)
str = string(decodeBytes)
case UTF8:
fallthrough
default:
str = string(byte)
}
return str
}
+2
View File
@@ -17,6 +17,8 @@ docker run --rm -v "$PWD":/media/sf_SamWaf -w /media/sf_SamWaf -e CGO_ENABLED=1
//可调试的local ubuntu
docker run --rm -v "$PWD":/home/ubuntu/samwaf -w /home/ubuntu/samwaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go build -v -ldflags="-extldflags "-static"" -o /home/ubuntu/samwaf/release/SamWafLinux64.exe main.go
//单元测试
docker run --rm -v "$PWD":/media/sf_SamWaf -w /media/sf_SamWaf -e CGO_ENABLED=1 -e GOPROXY=https://goproxy.cn,direct golang:1.19 go test -v ./firewall -test.run TestFireWallEngine_IsFirewallEnabled
# 注意事项
1. 如果linux使用multipass 需要以下方式开启