1Panel/agent/utils/firewall/client/iptables/forward.go

127 lines
3.7 KiB
Go

package iptables
import (
"fmt"
"strings"
)
func AddForward(protocol, srcPort, dest, destPort, iface string, save bool) error {
if dest != "" && dest != "127.0.0.1" && dest != "localhost" {
iptablesArg := fmt.Sprintf("-A %s", Chain1PanelPreRouting)
if iface != "" {
iptablesArg += fmt.Sprintf(" -i %s", iface)
}
iptablesArg += fmt.Sprintf(" -p %s --dport %s -j DNAT --to-destination %s:%s", protocol, srcPort, dest, destPort)
if err := Run(NatTab, iptablesArg); err != nil {
return err
}
if err := Run(NatTab, fmt.Sprintf("-A %s -d %s -p %s --dport %s -j MASQUERADE", Chain1PanelPostRouting, dest, protocol, destPort)); err != nil {
return err
}
if err := Run(FilterTab, fmt.Sprintf("-A %s -d %s -p %s --dport %s -j ACCEPT", Chain1PanelForward, dest, protocol, destPort)); err != nil {
return err
}
if err := Run(FilterTab, fmt.Sprintf("-A %s -s %s -p %s --sport %s -j ACCEPT", Chain1PanelForward, dest, protocol, destPort)); err != nil {
return err
}
} else {
iptablesArg := fmt.Sprintf("-A %s", Chain1PanelPreRouting)
if iface != "" {
iptablesArg += fmt.Sprintf(" -i %s", iface)
}
iptablesArg += fmt.Sprintf(" -p %s --dport %s -j REDIRECT --to-port %s", protocol, srcPort, destPort)
if err := Run(NatTab, iptablesArg); err != nil {
return err
}
}
return nil
}
func DeleteForward(num string, protocol, srcPort, dest, destPort, iface string) error {
if err := Run(NatTab, fmt.Sprintf("-D %s %s", Chain1PanelPreRouting, num)); err != nil {
return err
}
if dest != "" && dest != "127.0.0.1" && dest != "localhost" {
if err := Run(NatTab, fmt.Sprintf("-D %s -d %s -p %s --dport %s -j MASQUERADE", Chain1PanelPostRouting, dest, protocol, destPort)); err != nil {
return err
}
if err := Run(FilterTab, fmt.Sprintf("-D %s -d %s -p %s --dport %s -j ACCEPT", Chain1PanelForward, dest, protocol, destPort)); err != nil {
return err
}
if err := Run(FilterTab, fmt.Sprintf("-D %s -s %s -p %s --sport %s -j ACCEPT", Chain1PanelForward, dest, protocol, destPort)); err != nil {
return err
}
}
return nil
}
func ListForward(chain ...string) ([]IptablesNatInfo, error) {
if len(chain) == 0 {
chain = append(chain, Chain1PanelPreRouting)
}
stdout, err := RunWithStd(NatTab, fmt.Sprintf("-nvL %s --line-numbers", chain[0]))
if err != nil {
return nil, err
}
var forwardList []IptablesNatInfo
lines := strings.Split(stdout, "\n")
for i := 0; i < len(lines); i++ {
fields := strings.Fields(lines[i])
if len(fields) < 13 {
continue
}
item := IptablesNatInfo{
Num: fields[0],
Protocol: loadProtocol(fields[4]),
InIface: fields[6],
OutIface: fields[7],
Source: fields[8],
SrcPort: loadNatSrcPort(fields[11]),
}
if len(fields) == 15 && fields[13] == "ports" {
item.DestPort = fields[14]
}
if len(fields) == 13 && strings.HasPrefix(fields[12], "to:") {
parts := strings.Split(fields[12], ":")
if len(parts) > 2 {
item.DestPort = parts[2]
item.Destination = parts[1]
}
}
if len(item.Destination) == 0 {
item.Destination = "127.0.0.1"
}
forwardList = append(forwardList, item)
}
return forwardList, nil
}
func loadNatSrcPort(portStr string) string {
var portItem string
if strings.Contains(portStr, "dpt:") {
portItem = strings.ReplaceAll(portStr, "dpt:", "")
}
if strings.Contains(portStr, "dpts:") {
portItem = strings.ReplaceAll(portStr, "dpts:", "")
}
portItem = strings.ReplaceAll(portItem, ":", "-")
return portItem
}
type IptablesNatInfo struct {
Num string `json:"num"`
Protocol string `json:"protocol"`
InIface string `json:"inIface"`
OutIface string `json:"outIface"`
Source string `json:"source"`
Destination string `json:"destination"`
SrcPort string `json:"srcPort"`
DestPort string `json:"destPort"`
}