2 Star 0 Fork 0

carlmax_my/go-iptables

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
iptables_args.go 5.94 KB
一键复制 编辑 原始数据 按行查看 历史
carlmax_my 提交于 2025-12-01 11:20 +08:00 . fix utc issue
package core
import (
"fmt"
"strings"
"gitee.com/carlmax_my/console-core-go/pkg/net/constant"
"gitee.com/carlmax_my/vpn-core-go/pkg/net/proto"
)
// iptables 有四个内置表:
// ​filter​ - 默认表,用于包过滤( INPUT, FORWARD, OUTPUT )
// ​nat​ - 用于网络地址转换( PREROUTING, POSTROUTING, OUTPUT )
// ​mangle​ - 用于特殊的数据包修改(所有链)
// ​raw​ - 用于连接跟踪豁免( PREROUTING, OUTPUT )
// target:
// ACCEPT 允许数据包通过
// DROP 丢弃数据包
// REJECT 拒绝数据包并发送通知
// MASQUERADE 动态源地址转换(用于拨号连接)
// --icmp-type
// allow ping:
// iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
// iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
// INPUT链 处理 ​以本机为目标地址​ 的数据包(即发往本机的流量)
// iptables -A INPUT -p tcp --dport 22 -j ACCEPT # 允许SSH访问本机
// iptables -A INPUT -j DROP # 默认拒绝其他入站流量
// FORWARD链
// 处理 ​经过本机路由/转发​ 的数据包(即流量目的地是其他设备,本机仅作为中间节点)
// 前提条件​:需启用Linux主机的IP转发功能(sysctl net.ipv4.ip_forward=1)
// 1. 是否为目标本机? → INPUT链 → 本机进程
// 2. 是否需要转发? → FORWARD链 → 路由到其他设备
// 如果单独命令行执行iptables 命令,不能用%i,因为不知道当前的iface,如果是配置在wireguard配置文件里,当然可以配置文件名就是iface name
// Placeholders: %i can be used as a placeholder for the interface name.
// Target=ACCEPT/REJECT/..., default is DROP
func BuildCmdArgs(args []string, opts ...RuleOptionFunc) ([]string, *RuleOption) {
opt := new(RuleOption)
for _, f := range opts {
f(opt)
}
if opt.InIface != "" {
args = append(args, "-i", opt.InIface)
}
if opt.OutIface != "" {
args = append(args, "-o", opt.OutIface)
}
if opt.Src != nil {
if opt.Src.IP != "" {
args = append(args, "-s", opt.Src.IP) // short for --src/--source
} else if opt.Src.Cidr != nil {
args = append(args, "-s", opt.Src.Cidr.CidrIpStr())
} else if opt.Src.Range != nil {
// -m iprange --src-range 192.168.1.90-192.168.1.101
args = append(args, "-m", "iprange", "--src-range", IpRangeToStr(opt.Src.Range))
} // todo: 支持ipset/list
}
if opt.Dst != nil {
if opt.Dst.IP != "" {
args = append(args, "-d", opt.Dst.IP) // short for --dst/--destination
} else if opt.Dst.Cidr != nil {
args = append(args, "-d", opt.Dst.Cidr.CidrIpStr())
} else if opt.Dst.Range != nil {
// -m iprange --dst-range 192.168.1.90-192.168.1.101
args = append(args, "-m", "iprange", "--dst-range", IpRangeToStr(opt.Dst.Range))
}
}
if opt.Protocol != "" {
args = append(args, "-p", opt.Protocol)
if opt.Protocol == constant.NET_PROTOCOL_ICMP {
if opt.ProtocolExtraByte != nil {
v := proto.IcmpCodeToStr(*opt.ProtocolExtraByte)
args = append(args, "--icmp-type", v)
} else if opt.ProtocolExtraStr != nil {
args = append(args, "--icmp-type", *opt.ProtocolExtraStr)
}
}
}
// port 必须放在protocol后面
// --dport 80
// -m multiport --dports 10000:20000
// -m multiport --dports ssh,smtp,http,https
// -m multiport --dports 1000,1001,1002:1500,1501:2000
// -m multiport ! --dports 0:999,2001:65535
if opt.SrcPort != nil || opt.DstPort != nil {
multiport := []string{}
if opt.SrcPort != nil {
if opt.SrcPort.Port != 0 {
args = append(args, "--sport", fmt.Sprintf("%d", opt.SrcPort.Port))
} else if len(opt.SrcPort.List) > 0 {
multiport = append(multiport, "--sports", Uint16ListToStr(opt.SrcPort.List))
} else if opt.SrcPort.Range != nil {
multiport = append(multiport, "--sports", PortRangeToStr(opt.SrcPort.Range))
}
}
if opt.DstPort != nil {
if opt.DstPort.Port != 0 {
args = append(args, "--dport", fmt.Sprintf("%d", opt.DstPort.Port))
} else if len(opt.DstPort.List) > 0 {
multiport = append(multiport, "--dports", Uint16ListToStr(opt.DstPort.List))
} else if opt.DstPort.Range != nil {
multiport = append(multiport, "--dports", PortRangeToStr(opt.DstPort.Range))
}
}
if len(multiport) > 0 {
args = append(args, "-m", "multiport")
args = append(args, multiport...)
}
}
ctstate := ConvertCtState(opt.CtState)
if ctstate != "" {
args = append(args, "-m", "conntrack", "--ctstate", ctstate)
}
state := ConvertCtState(opt.State)
if state != "" {
args = append(args, "-m", "state", "--state", state)
}
// iptables is working with UTC time not your local time.
// iptables -A FORWARD -p tcp -m multiport --dport http,https -o eth0 -i eth1 -m time --timestart 21:30 --timestop 22:30 --weekdays Mon,Tue,Wed,Thu,Fri -j ACCEPT
if opt.Time != nil {
if opt.Time.HourRange != nil || len(opt.Time.WeekDays) > 0 {
args = append(args, "-m", "time")
if opt.Time.HourRange.Min != 0 || opt.Time.HourRange.Max != 0 {
args = append(args, "--timestart", FmtHour2Second(opt.Time.HourRange.Min))
args = append(args, "--timestop", FmtHour2Second(opt.Time.HourRange.Max))
}
if len(opt.Time.WeekDays) != 0 {
// --weekdays day[,day...]
// Only match on the given weekdays. Possible values are Mon, Tue, Wed, Thu, Fri, Sat, Sun,
// or values from 1 to 7, respectively.
// You may also use two-character variants (Mo, Tu, etc.).
args = append(args, "--weekdays", FmtWeekDaysShort(opt.Time.WeekDays))
}
if opt.Time.UTC != nil && *opt.Time.UTC {
args = append(args, "--utc")
}
}
}
if opt.Target == "" {
args = append(args, "-j", TARGET_DROP)
} else {
args = append(args, "-j", opt.Target)
}
return args, opt
}
// PostUp = iptables -A INPUT -i %i -p tcp --dport 3306 -j ACCEPT # 仅允许MySQL端口
// PostDown = iptables -D INPUT -i %i -p tcp --dport 3306 -j ACCEPT
func BuildCmdArgsStr(args []string, chain string, opts ...RuleOptionFunc) (string, *RuleOption) {
args, opt := BuildCmdArgs(args, opts...)
return chain + " " + strings.Join(args, " "), opt
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/carlmax_my/go-iptables.git
git@gitee.com:carlmax_my/go-iptables.git
carlmax_my
go-iptables
go-iptables
v0.1.21

搜索帮助