firewall_linux.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package firewall
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "os"
  6. "strings"
  7. "github.com/bettercap/bettercap/core"
  8. "github.com/bettercap/bettercap/network"
  9. "github.com/evilsocket/islazy/fs"
  10. "github.com/evilsocket/islazy/str"
  11. )
  12. type LinuxFirewall struct {
  13. iface *network.Endpoint
  14. forwarding bool
  15. redirections map[string]*Redirection
  16. }
  17. const (
  18. IPV4ForwardingFile = "/proc/sys/net/ipv4/ip_forward"
  19. IPV6ForwardingFile = "/proc/sys/net/ipv6/conf/all/forwarding"
  20. )
  21. func Make(iface *network.Endpoint) FirewallManager {
  22. firewall := &LinuxFirewall{
  23. iface: iface,
  24. forwarding: false,
  25. redirections: make(map[string]*Redirection),
  26. }
  27. firewall.forwarding = firewall.IsForwardingEnabled()
  28. return firewall
  29. }
  30. func (f LinuxFirewall) enableFeature(filename string, enable bool) error {
  31. var value string
  32. if enable {
  33. value = "1"
  34. } else {
  35. value = "0"
  36. }
  37. fd, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
  38. if err != nil {
  39. return err
  40. }
  41. defer fd.Close()
  42. _, err = fd.WriteString(value)
  43. return err
  44. }
  45. func (f LinuxFirewall) IsForwardingEnabled() bool {
  46. if out, err := ioutil.ReadFile(IPV4ForwardingFile); err != nil {
  47. return false
  48. } else {
  49. return str.Trim(string(out)) == "1"
  50. }
  51. }
  52. func (f LinuxFirewall) EnableForwarding(enabled bool) error {
  53. if err := f.enableFeature(IPV4ForwardingFile, enabled); err != nil {
  54. return err
  55. }
  56. if fs.Exists(IPV6ForwardingFile) {
  57. return f.enableFeature(IPV6ForwardingFile, enabled)
  58. }
  59. return nil
  60. }
  61. func (f *LinuxFirewall) getCommandLine(r *Redirection, enabled bool) (cmdLine []string) {
  62. action := "-A"
  63. destination := ""
  64. if !enabled {
  65. action = "-D"
  66. }
  67. if strings.Count(r.DstAddress, ":") < 2 {
  68. destination = r.DstAddress
  69. } else {
  70. destination = fmt.Sprintf("[%s]", r.DstAddress)
  71. }
  72. if r.SrcAddress == "" {
  73. cmdLine = []string{
  74. "-t", "nat",
  75. action, "PREROUTING",
  76. "-i", r.Interface,
  77. "-p", r.Protocol,
  78. "--dport", fmt.Sprintf("%d", r.SrcPort),
  79. "-j", "DNAT",
  80. "--to", fmt.Sprintf("%s:%d", destination, r.DstPort),
  81. }
  82. } else {
  83. cmdLine = []string{
  84. "-t", "nat",
  85. action, "PREROUTING",
  86. "-i", r.Interface,
  87. "-p", r.Protocol,
  88. "-d", r.SrcAddress,
  89. "--dport", fmt.Sprintf("%d", r.SrcPort),
  90. "-j", "DNAT",
  91. "--to", fmt.Sprintf("%s:%d", destination, r.DstPort),
  92. }
  93. }
  94. return
  95. }
  96. func (f *LinuxFirewall) EnableRedirection(r *Redirection, enabled bool) error {
  97. cmdLine := f.getCommandLine(r, enabled)
  98. rkey := r.String()
  99. _, found := f.redirections[rkey]
  100. cmd := ""
  101. if strings.Count(r.DstAddress, ":") < 2 {
  102. cmd = "iptables"
  103. } else {
  104. cmd = "ip6tables"
  105. }
  106. if enabled {
  107. if found {
  108. return fmt.Errorf("Redirection '%s' already enabled.", rkey)
  109. }
  110. f.redirections[rkey] = r
  111. // accept all
  112. if _, err := core.Exec(cmd, []string{"-P", "FORWARD", "ACCEPT"}); err != nil {
  113. return err
  114. } else if _, err := core.Exec(cmd, cmdLine); err != nil {
  115. return err
  116. }
  117. } else {
  118. if !found {
  119. return nil
  120. }
  121. delete(f.redirections, r.String())
  122. if _, err := core.Exec(cmd, cmdLine); err != nil {
  123. return err
  124. }
  125. }
  126. return nil
  127. }
  128. func (f LinuxFirewall) Restore() {
  129. for _, r := range f.redirections {
  130. if err := f.EnableRedirection(r, false); err != nil {
  131. fmt.Printf("%s", err)
  132. }
  133. }
  134. if err := f.EnableForwarding(f.forwarding); err != nil {
  135. fmt.Printf("%s", err)
  136. }
  137. }