summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--pkg/abi/linux/netfilter.go14
-rw-r--r--pkg/sentry/socket/netfilter/netfilter.go144
-rw-r--r--pkg/tcpip/iptables/types.go15
-rw-r--r--pkg/tcpip/iptables/udp_matcher.go62
-rw-r--r--test/iptables/filter_input.go6
5 files changed, 88 insertions, 153 deletions
diff --git a/pkg/abi/linux/netfilter.go b/pkg/abi/linux/netfilter.go
index effed7976..8e40bcc62 100644
--- a/pkg/abi/linux/netfilter.go
+++ b/pkg/abi/linux/netfilter.go
@@ -198,6 +198,8 @@ type XTEntryMatch struct {
// SizeOfXTEntryMatch is the size of an XTEntryMatch.
const SizeOfXTEntryMatch = 32
+// KernelXTEntryMatch is identical to XTEntryMatch, but contains
+// variable-length Data field.
type KernelXTEntryMatch struct {
XTEntryMatch
Data []byte
@@ -349,19 +351,19 @@ func goString(cstring []byte) string {
// XTUDP holds data for matching UDP packets. It corresponds to struct xt_udp
// in include/uapi/linux/netfilter/xt_tcpudp.h.
type XTUDP struct {
- // SourcePortStart specifies the inclusive start of the range of source
- // ports to which the matcher applies.
+ // SourcePortStart is the inclusive start of the range of source ports
+ // to which the matcher applies.
SourcePortStart uint16
- // SourcePortEnd specifies the inclusive end of the range of source ports
- // to which the matcher applies.
+ // SourcePortEnd is the inclusive end of the range of source ports to
+ // which the matcher applies.
SourcePortEnd uint16
- // DestinationPortStart specifies the start of the destination port
+ // DestinationPortStart is the inclusive start of the destination port
// range to which the matcher applies.
DestinationPortStart uint16
- // DestinationPortEnd specifies the start of the destination port
+ // DestinationPortEnd is the inclusive end of the destination port
// range to which the matcher applies.
DestinationPortEnd uint16
diff --git a/pkg/sentry/socket/netfilter/netfilter.go b/pkg/sentry/socket/netfilter/netfilter.go
index 6c88a50a6..b8848f08a 100644
--- a/pkg/sentry/socket/netfilter/netfilter.go
+++ b/pkg/sentry/socket/netfilter/netfilter.go
@@ -34,9 +34,16 @@ import (
// shouldn't be reached - an error has occurred if we fall through to one.
const errorTargetName = "ERROR"
-// metadata is opaque to netstack. It holds data that we need to translate
-// between Linux's and netstack's iptables representations.
-// TODO(gvisor.dev/issue/170): Use metadata to check correctness.
+const (
+ matcherNameUDP = "udp"
+)
+
+// Metadata is used to verify that we are correctly serializing and
+// deserializing iptables into structs consumable by the iptables tool. We save
+// a metadata struct when the tables are written, and when they are read out we
+// verify that certain fields are the same.
+//
+// metadata is opaque to netstack.
type metadata struct {
HookEntry [linux.NF_INET_NUMHOOKS]uint32
Underflow [linux.NF_INET_NUMHOOKS]uint32
@@ -44,10 +51,12 @@ type metadata struct {
Size uint32
}
-const enableDebugLog = true
+const enableDebug = false
+// nflog logs messages related to the writing and reading of iptables, but only
+// when enableDebug is true.
func nflog(format string, args ...interface{}) {
- if enableDebugLog {
+ if enableDebug {
log.Infof("netfilter: "+format, args...)
}
}
@@ -80,7 +89,7 @@ func GetInfo(t *kernel.Task, stack *stack.Stack, outPtr usermem.Addr) (linux.IPT
info.NumEntries = metadata.NumEntries
info.Size = metadata.Size
- nflog("GetInfo returning info: %+v", info)
+ nflog("returning info: %+v", info)
return info, nil
}
@@ -163,19 +172,19 @@ func convertNetstackToBinary(tablename string, table iptables.Table) (linux.Kern
copy(entries.Name[:], tablename)
for ruleIdx, rule := range table.Rules {
- nflog("Current offset: %d", entries.Size)
+ nflog("convert to binary: current offset: %d", entries.Size)
// Is this a chain entry point?
for hook, hookRuleIdx := range table.BuiltinChains {
if hookRuleIdx == ruleIdx {
- nflog("Found hook %d at offset %d", hook, entries.Size)
+ nflog("convert to binary: found hook %d at offset %d", hook, entries.Size)
meta.HookEntry[hook] = entries.Size
}
}
// Is this a chain underflow point?
for underflow, underflowRuleIdx := range table.Underflows {
if underflowRuleIdx == ruleIdx {
- nflog("Found underflow %d at offset %d", underflow, entries.Size)
+ nflog("convert to binary: found underflow %d at offset %d", underflow, entries.Size)
meta.Underflow[underflow] = entries.Size
}
}
@@ -195,7 +204,7 @@ func convertNetstackToBinary(tablename string, table iptables.Table) (linux.Kern
// Serialize the matcher and add it to the
// entry.
serialized := marshalMatcher(matcher)
- nflog("matcher serialized as: %v", serialized)
+ nflog("convert to binary: matcher serialized as: %v", serialized)
if len(serialized)%8 != 0 {
panic(fmt.Sprintf("matcher %T is not 64-bit aligned", matcher))
}
@@ -212,14 +221,14 @@ func convertNetstackToBinary(tablename string, table iptables.Table) (linux.Kern
entry.Elems = append(entry.Elems, serialized...)
entry.NextOffset += uint16(len(serialized))
- nflog("Adding entry: %+v", entry)
+ nflog("convert to binary: adding entry: %+v", entry)
entries.Size += uint32(entry.NextOffset)
entries.Entrytable = append(entries.Entrytable, entry)
meta.NumEntries++
}
- nflog("Finished with an marshalled size of %d", meta.Size)
+ nflog("convert to binary: finished with an marshalled size of %d", meta.Size)
meta.Size = entries.Size
return entries, meta, nil
}
@@ -237,16 +246,18 @@ func marshalMatcher(matcher iptables.Matcher) []byte {
}
func marshalUDPMatcher(matcher *iptables.UDPMatcher) []byte {
- nflog("Marshalling UDP matcher: %+v", matcher)
+ nflog("convert to binary: marshalling UDP matcher: %+v", matcher)
+
+ // We have to pad this struct size to a multiple of 8 bytes.
+ const size = linux.SizeOfXTEntryMatch + linux.SizeOfXTUDP + 6
linuxMatcher := linux.KernelXTEntryMatch{
XTEntryMatch: linux.XTEntryMatch{
- MatchSize: linux.SizeOfXTEntryMatch + linux.SizeOfXTUDP + 6,
- // Name: "udp",
+ MatchSize: size,
},
Data: make([]byte, 0, linux.SizeOfXTUDP),
}
- copy(linuxMatcher.Name[:], "udp")
+ copy(linuxMatcher.Name[:], matcherNameUDP)
xtudp := linux.XTUDP{
SourcePortStart: matcher.Data.SourcePortStart,
@@ -255,17 +266,12 @@ func marshalUDPMatcher(matcher *iptables.UDPMatcher) []byte {
DestinationPortEnd: matcher.Data.DestinationPortEnd,
InverseFlags: matcher.Data.InverseFlags,
}
- nflog("marshalUDPMatcher: xtudp: %+v", xtudp)
linuxMatcher.Data = binary.Marshal(linuxMatcher.Data, usermem.ByteOrder, xtudp)
- nflog("marshalUDPMatcher: linuxMatcher: %+v", linuxMatcher)
- // We have to pad this struct size to a multiple of 8 bytes, so we make
- // this a little longer than it needs to be.
- buf := make([]byte, 0, linux.SizeOfXTEntryMatch+linux.SizeOfXTUDP+6)
+ buf := make([]byte, 0, size)
buf = binary.Marshal(buf, usermem.ByteOrder, linuxMatcher)
buf = append(buf, []byte{0, 0, 0, 0, 0, 0}...)
- nflog("Marshalled into matcher of size %d", len(buf))
- nflog("marshalUDPMatcher: buf is: %v", buf)
+ nflog("convert to binary: marshalled UDP matcher into %v", buf)
return buf[:]
}
@@ -283,9 +289,8 @@ func marshalTarget(target iptables.Target) []byte {
}
func marshalStandardTarget(verdict iptables.Verdict) []byte {
- nflog("Marshalling standard target with size %d", linux.SizeOfXTStandardTarget)
+ nflog("convert to binary: marshalling standard target with size %d", linux.SizeOfXTStandardTarget)
- // TODO: Must be aligned.
// The target's name will be the empty string.
target := linux.XTStandardTarget{
Target: linux.XTEntryTarget{
@@ -353,8 +358,6 @@ func translateToStandardVerdict(val int32) (iptables.Verdict, *syserr.Error) {
// SetEntries sets iptables rules for a single table. See
// net/ipv4/netfilter/ip_tables.c:translate_table for reference.
func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
- // printReplace(optVal)
-
// Get the basic rules data (struct ipt_replace).
if len(optVal) < linux.SizeOfIPTReplace {
log.Warningf("netfilter.SetEntries: optVal has insufficient size for replace %d", len(optVal))
@@ -375,13 +378,13 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
return syserr.ErrInvalidArgument
}
- nflog("Setting entries in table %q", replace.Name.String())
+ nflog("set entries: setting entries in table %q", replace.Name.String())
// Convert input into a list of rules and their offsets.
var offset uint32
var offsets []uint32
for entryIdx := uint32(0); entryIdx < replace.NumEntries; entryIdx++ {
- nflog("Processing entry at offset %d", offset)
+ nflog("set entries: processing entry at offset %d", offset)
// Get the struct ipt_entry.
if len(optVal) < linux.SizeOfIPTEntry {
@@ -406,11 +409,13 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
return err
}
- // TODO: Matchers (and maybe targets) can specify that they only work for certiain protocols, hooks, tables.
+ // TODO(gvisor.dev/issue/170): Matchers and targets can specify
+ // that they only work for certiain protocols, hooks, tables.
// Get matchers.
matchersSize := entry.TargetOffset - linux.SizeOfIPTEntry
if len(optVal) < int(matchersSize) {
log.Warningf("netfilter: entry doesn't have enough room for its matchers (only %d bytes remain)", len(optVal))
+ return syserr.ErrInvalidArgument
}
matchers, err := parseMatchers(filter, optVal[:matchersSize])
if err != nil {
@@ -423,6 +428,7 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
targetSize := entry.NextOffset - entry.TargetOffset
if len(optVal) < int(targetSize) {
log.Warningf("netfilter: entry doesn't have enough room for its target (only %d bytes remain)", len(optVal))
+ return syserr.ErrInvalidArgument
}
target, err := parseTarget(optVal[:targetSize])
if err != nil {
@@ -500,10 +506,11 @@ func SetEntries(stack *stack.Stack, optVal []byte) *syserr.Error {
// parseMatchers parses 0 or more matchers from optVal. optVal should contain
// only the matchers.
func parseMatchers(filter iptables.IPHeaderFilter, optVal []byte) ([]iptables.Matcher, *syserr.Error) {
- nflog("Parsing matchers of size %d", len(optVal))
+ nflog("set entries: parsing matchers of size %d", len(optVal))
var matchers []iptables.Matcher
for len(optVal) > 0 {
- nflog("parseMatchers: optVal has len %d", len(optVal))
+ nflog("set entries: optVal has len %d", len(optVal))
+
// Get the XTEntryMatch.
if len(optVal) < linux.SizeOfXTEntryMatch {
log.Warningf("netfilter: optVal has insufficient size for entry match: %d", len(optVal))
@@ -512,7 +519,7 @@ func parseMatchers(filter iptables.IPHeaderFilter, optVal []byte) ([]iptables.Ma
var match linux.XTEntryMatch
buf := optVal[:linux.SizeOfXTEntryMatch]
binary.Unmarshal(buf, usermem.ByteOrder, &match)
- nflog("parseMatchers: parsed entry match %q: %+v", match.Name.String(), match)
+ nflog("set entries: parsed entry match %q: %+v", match.Name.String(), match)
// Check some invariants.
if match.MatchSize < linux.SizeOfXTEntryMatch {
@@ -528,17 +535,17 @@ func parseMatchers(filter iptables.IPHeaderFilter, optVal []byte) ([]iptables.Ma
var matcher iptables.Matcher
var err error
switch match.Name.String() {
- case "udp":
+ case matcherNameUDP:
if len(buf) < linux.SizeOfXTUDP {
log.Warningf("netfilter: optVal has insufficient size for UDP match: %d", len(optVal))
return nil, syserr.ErrInvalidArgument
}
+ // For alignment reasons, the match's total size may
+ // exceed what's strictly necessary to hold matchData.
var matchData linux.XTUDP
- // For alignment reasons, the match's total size may exceed what's
- // strictly necessary to hold matchData.
binary.Unmarshal(buf[:linux.SizeOfXTUDP], usermem.ByteOrder, &matchData)
log.Infof("parseMatchers: parsed XTUDP: %+v", matchData)
- matcher, err = iptables.NewUDPMatcher(filter, iptables.UDPMatcherData{
+ matcher, err = iptables.NewUDPMatcher(filter, iptables.UDPMatcherParams{
SourcePortStart: matchData.SourcePortStart,
SourcePortEnd: matchData.SourcePortEnd,
DestinationPortStart: matchData.DestinationPortStart,
@@ -557,19 +564,22 @@ func parseMatchers(filter iptables.IPHeaderFilter, optVal []byte) ([]iptables.Ma
matchers = append(matchers, matcher)
- // TODO: Support revision.
- // TODO: Support proto -- matchers usually specify which proto(s) they work with.
+ // TODO(gvisor.dev/issue/170): Check the revision field.
optVal = optVal[match.MatchSize:]
}
- // TODO: Check that optVal is exhausted.
+ if len(optVal) != 0 {
+ log.Warningf("netfilter: optVal should be exhausted after parsing matchers")
+ return nil, syserr.ErrInvalidArgument
+ }
+
return matchers, nil
}
// parseTarget parses a target from optVal. optVal should contain only the
// target.
func parseTarget(optVal []byte) (iptables.Target, *syserr.Error) {
- nflog("Parsing target of size %d", len(optVal))
+ nflog("set entries: parsing target of size %d", len(optVal))
if len(optVal) < linux.SizeOfXTEntryTarget {
log.Warningf("netfilter: optVal has insufficient size for entry target %d", len(optVal))
return nil, syserr.ErrInvalidArgument
@@ -598,7 +608,8 @@ func parseTarget(optVal []byte) (iptables.Target, *syserr.Error) {
case iptables.Drop:
return iptables.UnconditionalDropTarget{}, nil
default:
- panic(fmt.Sprintf("Unknown verdict: %v", verdict))
+ log.Warningf("Unknown verdict: %v", verdict)
+ return nil, syserr.ErrInvalidArgument
}
case errorTargetName:
@@ -673,52 +684,3 @@ func hookFromLinux(hook int) iptables.Hook {
}
panic(fmt.Sprintf("Unknown hook %d does not correspond to a builtin chain", hook))
}
-
-// printReplace prints information about the struct ipt_replace in optVal. It
-// is only for debugging.
-func printReplace(optVal []byte) {
- // Basic replace info.
- var replace linux.IPTReplace
- replaceBuf := optVal[:linux.SizeOfIPTReplace]
- optVal = optVal[linux.SizeOfIPTReplace:]
- binary.Unmarshal(replaceBuf, usermem.ByteOrder, &replace)
- log.Infof("Replacing table %q: %+v", replace.Name.String(), replace)
-
- // Read in the list of entries at the end of replace.
- var totalOffset uint16
- for entryIdx := uint32(0); entryIdx < replace.NumEntries; entryIdx++ {
- var entry linux.IPTEntry
- entryBuf := optVal[:linux.SizeOfIPTEntry]
- binary.Unmarshal(entryBuf, usermem.ByteOrder, &entry)
- log.Infof("Entry %d (total offset %d): %+v", entryIdx, totalOffset, entry)
-
- totalOffset += entry.NextOffset
- if entry.TargetOffset == linux.SizeOfIPTEntry {
- log.Infof("Entry has no matches.")
- } else {
- log.Infof("Entry has matches.")
- }
-
- var target linux.XTEntryTarget
- targetBuf := optVal[entry.TargetOffset : entry.TargetOffset+linux.SizeOfXTEntryTarget]
- binary.Unmarshal(targetBuf, usermem.ByteOrder, &target)
- log.Infof("Target named %q: %+v", target.Name.String(), target)
-
- switch target.Name.String() {
- case "":
- var standardTarget linux.XTStandardTarget
- stBuf := optVal[entry.TargetOffset : entry.TargetOffset+linux.SizeOfXTStandardTarget]
- binary.Unmarshal(stBuf, usermem.ByteOrder, &standardTarget)
- log.Infof("Standard target with verdict %q (%d).", linux.VerdictStrings[standardTarget.Verdict], standardTarget.Verdict)
- case errorTargetName:
- var errorTarget linux.XTErrorTarget
- etBuf := optVal[entry.TargetOffset : entry.TargetOffset+linux.SizeOfXTErrorTarget]
- binary.Unmarshal(etBuf, usermem.ByteOrder, &errorTarget)
- log.Infof("Error target with name %q.", errorTarget.Name.String())
- default:
- log.Infof("Unknown target type.")
- }
-
- optVal = optVal[entry.NextOffset:]
- }
-}
diff --git a/pkg/tcpip/iptables/types.go b/pkg/tcpip/iptables/types.go
index d47447d40..ba5ed75b4 100644
--- a/pkg/tcpip/iptables/types.go
+++ b/pkg/tcpip/iptables/types.go
@@ -169,8 +169,6 @@ type IPHeaderFilter struct {
Protocol tcpip.TransportProtocolNumber
}
-// TODO: Should these be able to marshal/unmarshal themselves?
-// TODO: Something has to map the name to the matcher.
// A Matcher is the interface for matching packets.
type Matcher interface {
// Match returns whether the packet matches and whether the packet
@@ -179,19 +177,6 @@ type Matcher interface {
//
// Precondition: packet.NetworkHeader is set.
Match(hook Hook, packet tcpip.PacketBuffer, interfaceName string) (matches bool, hotdrop bool)
-
- // TODO: Make this typesafe by having each Matcher have their own, typed CheckEntry?
- // CheckEntry(params MatchCheckEntryParams) bool
-}
-
-// TODO: Unused?
-type MatchCheckEntryParams struct {
- Table string // TODO: Tables should be an enum...
- Filter IPHeaderFilter
- Info interface{} // TODO: Type unsafe.
- // HookMask uint8
- // Family uint8
- // NFTCompat bool
}
// A Target is the interface for taking an action for a packet.
diff --git a/pkg/tcpip/iptables/udp_matcher.go b/pkg/tcpip/iptables/udp_matcher.go
index 65ae7f9e0..f59ca2027 100644
--- a/pkg/tcpip/iptables/udp_matcher.go
+++ b/pkg/tcpip/iptables/udp_matcher.go
@@ -16,33 +16,28 @@ package iptables
import (
"fmt"
- "runtime/debug"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/tcpip"
"gvisor.dev/gvisor/pkg/tcpip/header"
)
+// TODO(gvisor.dev/issue/170): The following per-matcher params should be
+// supported:
+// - Table name
+// - Match size
+// - User size
+// - Hooks
+// - Proto
+// - Family
+
+// UDPMatcher matches UDP packets and their headers. It implements Matcher.
type UDPMatcher struct {
- Data UDPMatcherData
-
- // tablename string
- // unsigned int matchsize;
- // unsigned int usersize;
- // #ifdef CONFIG_COMPAT
- // unsigned int compatsize;
- // #endif
- // unsigned int hooks;
- // unsigned short proto;
- // unsigned short family;
+ Data UDPMatcherParams
}
-// TODO: Delete?
-// MatchCheckEntryParams
-
-type UDPMatcherData struct {
- // Filter IPHeaderFilter
-
+// UDPMatcherParams are the parameters used to create a UDPMatcher.
+type UDPMatcherParams struct {
SourcePortStart uint16
SourcePortEnd uint16
DestinationPortStart uint16
@@ -50,12 +45,12 @@ type UDPMatcherData struct {
InverseFlags uint8
}
-func NewUDPMatcher(filter IPHeaderFilter, data UDPMatcherData) (Matcher, error) {
- // TODO: We currently only support source port and destination port.
- log.Infof("Adding rule with UDPMatcherData: %+v", data)
+// NewUDPMatcher returns a new instance of UDPMatcher.
+func NewUDPMatcher(filter IPHeaderFilter, data UDPMatcherParams) (Matcher, error) {
+ log.Infof("Adding rule with UDPMatcherParams: %+v", data)
if data.InverseFlags != 0 {
- return nil, fmt.Errorf("unsupported UDP matcher flags set")
+ return nil, fmt.Errorf("unsupported UDP matcher inverse flags set")
}
if filter.Protocol != header.UDPProtocolNumber {
@@ -65,21 +60,18 @@ func NewUDPMatcher(filter IPHeaderFilter, data UDPMatcherData) (Matcher, error)
return &UDPMatcher{Data: data}, nil
}
-// TODO: Check xt_tcpudp.c. Need to check for same things (e.g. fragments).
+// Match implements Matcher.Match.
func (um *UDPMatcher) Match(hook Hook, pkt tcpip.PacketBuffer, interfaceName string) (bool, bool) {
- log.Infof("UDPMatcher called from: %s", string(debug.Stack()))
netHeader := header.IPv4(pkt.NetworkHeader)
- // TODO: Do we check proto here or elsewhere? I think elsewhere (check
- // codesearch).
+ // TODO(gvisor.dev/issue/170): Proto checks should ultimately be moved
+ // into the iptables.Check codepath as matchers are added.
if netHeader.TransportProtocol() != header.UDPProtocolNumber {
- log.Infof("UDPMatcher: wrong protocol number")
return false, false
}
// We dont't match fragments.
if frag := netHeader.FragmentOffset(); frag != 0 {
- log.Infof("UDPMatcher: it's a fragment")
if frag == 1 {
return false, true
}
@@ -89,20 +81,18 @@ func (um *UDPMatcher) Match(hook Hook, pkt tcpip.PacketBuffer, interfaceName str
// Now we need the transport header. However, this may not have been set
// yet.
- // TODO
+ // TODO(gvisor.dev/issue/170): Parsing the transport header should
+ // ultimately be moved into the iptables.Check codepath as matchers are
+ // added.
var udpHeader header.UDP
if pkt.TransportHeader != nil {
- log.Infof("UDPMatcher: transport header is not nil")
udpHeader = header.UDP(pkt.TransportHeader)
} else {
- log.Infof("UDPMatcher: transport header is nil")
- log.Infof("UDPMatcher: is network header nil: %t", pkt.NetworkHeader == nil)
// The UDP header hasn't been parsed yet. We have to do it here.
if len(pkt.Data.First()) < header.UDPMinimumSize {
// There's no valid UDP header here, so we hotdrop the
// packet.
- // TODO: Stats.
- log.Warningf("Dropping UDP packet: size to small.")
+ log.Warningf("Dropping UDP packet: size too small.")
return false, true
}
udpHeader = header.UDP(pkt.Data.First())
@@ -112,10 +102,6 @@ func (um *UDPMatcher) Match(hook Hook, pkt tcpip.PacketBuffer, interfaceName str
// matching range.
sourcePort := udpHeader.SourcePort()
destinationPort := udpHeader.DestinationPort()
- log.Infof("UDPMatcher: sport and dport are %d and %d. sports and dport start and end are (%d, %d) and (%d, %d)",
- udpHeader.SourcePort(), udpHeader.DestinationPort(),
- um.Data.SourcePortStart, um.Data.SourcePortEnd,
- um.Data.DestinationPortStart, um.Data.DestinationPortEnd)
if sourcePort < um.Data.SourcePortStart || um.Data.SourcePortEnd < sourcePort {
return false, false
}
diff --git a/test/iptables/filter_input.go b/test/iptables/filter_input.go
index bc963d40e..e9f0978eb 100644
--- a/test/iptables/filter_input.go
+++ b/test/iptables/filter_input.go
@@ -264,9 +264,9 @@ func (FilterInputMultiUDPRules) ContainerAction(ip net.IP) error {
if err := filterTable("-A", "INPUT", "-p", "udp", "-m", "udp", "--destination-port", fmt.Sprintf("%d", dropPort), "-j", "DROP"); err != nil {
return err
}
- // if err := filterTable("-A", "INPUT", "-p", "udp", "-m", "udp", "--destination-port", fmt.Sprintf("%d", acceptPort), "-j", "ACCEPT"); err != nil {
- // return err
- // }
+ if err := filterTable("-A", "INPUT", "-p", "udp", "-m", "udp", "--destination-port", fmt.Sprintf("%d", acceptPort), "-j", "ACCEPT"); err != nil {
+ return err
+ }
return filterTable("-L")
}