mirror of
https://github.com/bettercap/bettercap
synced 2025-07-05 20:42:09 -07:00
178 lines
3.8 KiB
Go
178 lines
3.8 KiB
Go
package firewall
|
|
|
|
import (
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/evilsocket/bettercap/core"
|
|
"github.com/op/go-logging"
|
|
)
|
|
|
|
type LinuxFirewall struct {
|
|
forwarding bool
|
|
redirections map[string]*Redirection
|
|
}
|
|
|
|
var log = logging.MustGetLogger("mitm")
|
|
|
|
const (
|
|
IPV4ForwardingFile = "/proc/sys/net/ipv4/ip_forward"
|
|
IPV4ICMPBcastFile = "/proc/sys/net/ipv4/icmp_echo_ignore_broadcasts"
|
|
IPV4SendRedirectsFile = "/proc/sys/net/ipv4/conf/all/send_redirects"
|
|
)
|
|
|
|
func Make() FirewallManager {
|
|
firewall := &LinuxFirewall{
|
|
forwarding: false,
|
|
redirections: make(map[string]*Redirection, 0),
|
|
}
|
|
|
|
firewall.forwarding = firewall.IsForwardingEnabled()
|
|
|
|
log.Debugf("Created Linux Firewall ( forwarding=%v )\n", firewall.forwarding)
|
|
|
|
return firewall
|
|
}
|
|
|
|
func (f LinuxFirewall) enableFeature(filename string, enable bool) error {
|
|
var value string
|
|
if enable {
|
|
value = "1"
|
|
} else {
|
|
value = "0"
|
|
}
|
|
|
|
fd, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer fd.Close()
|
|
|
|
if _, err = fd.WriteString(value); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (f LinuxFirewall) IsForwardingEnabled() bool {
|
|
|
|
if out, err := ioutil.ReadFile(IPV4ForwardingFile); err != nil {
|
|
log.Error(err)
|
|
return false
|
|
} else {
|
|
return strings.Trim(string(out), "\r\n\t ") == "1"
|
|
}
|
|
}
|
|
|
|
func (f LinuxFirewall) EnableForwarding(enabled bool) error {
|
|
return f.enableFeature(IPV4ForwardingFile, enabled)
|
|
}
|
|
|
|
func (f LinuxFirewall) EnableIcmpBcast(enabled bool) error {
|
|
return f.enableFeature(IPV4ICMPBcastFile, enabled)
|
|
}
|
|
|
|
func (f LinuxFirewall) EnableSendRedirects(enabled bool) error {
|
|
return f.enableFeature(IPV4SendRedirectsFile, enabled)
|
|
}
|
|
|
|
func (f *LinuxFirewall) EnableRedirection(r *Redirection, enabled bool) error {
|
|
var opts []string
|
|
|
|
rkey := r.String()
|
|
_, found := f.redirections[rkey]
|
|
|
|
if enabled == true {
|
|
if found == true {
|
|
return fmt.Errorf("Redirection '%s' already enabled.", rkey)
|
|
}
|
|
|
|
log.Debugf("Enabling redirection %s\n", rkey)
|
|
|
|
f.redirections[rkey] = r
|
|
|
|
// accept all
|
|
if _, err := core.Exec("iptables", []string{"-P", "FORWARD", "ACCEPT"}); err != nil {
|
|
return err
|
|
}
|
|
|
|
if r.SrcAddress == "" {
|
|
opts = []string{
|
|
"-t", "nat",
|
|
"-A", "PREROUTING",
|
|
"-i", r.Interface,
|
|
"-p", r.Protocol,
|
|
"--dport", fmt.Sprintf("%d", r.SrcPort),
|
|
"-j", "DNAT",
|
|
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort),
|
|
}
|
|
} else {
|
|
opts = []string{
|
|
"-t", "nat",
|
|
"-A", "PREROUTING",
|
|
"-i", r.Interface,
|
|
"-p", r.Protocol,
|
|
"-d", r.SrcAddress,
|
|
"--dport", fmt.Sprintf("%d", r.SrcPort),
|
|
"-j", "DNAT",
|
|
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort),
|
|
}
|
|
}
|
|
if _, err := core.Exec("iptables", opts); err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
if found == false {
|
|
log.Debugf("Did not remove redirection '%s' as it was already removed.\n", r.String())
|
|
return nil
|
|
}
|
|
|
|
log.Debugf("Disabling redirection %s\n", r.String())
|
|
|
|
delete(f.redirections, r.String())
|
|
|
|
if r.SrcAddress == "" {
|
|
opts = []string{
|
|
"-t", "nat",
|
|
"-D", "PREROUTING",
|
|
"-i", r.Interface,
|
|
"-p", r.Protocol,
|
|
"--dport", fmt.Sprintf("%d", r.SrcPort),
|
|
"-j", "DNAT",
|
|
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort),
|
|
}
|
|
} else {
|
|
opts = []string{
|
|
"-t", "nat",
|
|
"-D", "PREROUTING",
|
|
"-i", r.Interface,
|
|
"-p", r.Protocol,
|
|
"-d", r.SrcAddress,
|
|
"--dport", fmt.Sprintf("%d", r.SrcPort),
|
|
"-j", "DNAT",
|
|
"--to", fmt.Sprintf("%s:%d", r.DstAddress, r.DstPort),
|
|
}
|
|
}
|
|
if _, err := core.Exec("iptables", opts); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (f LinuxFirewall) Restore() {
|
|
log.Debugf("Restoring firewall state.\n")
|
|
for _, r := range f.redirections {
|
|
if err := f.EnableRedirection(r, false); err != nil {
|
|
log.Error(err)
|
|
}
|
|
}
|
|
|
|
if err := f.EnableForwarding(f.forwarding); err != nil {
|
|
log.Error(err)
|
|
}
|
|
}
|