-
Notifications
You must be signed in to change notification settings - Fork 138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding rules in code produces different results and logs than the rules I added directly from the command line #247
Comments
Hi @xlango, your code does not replicate netlink messages sent by the Can you test the following code and let me know if it works? package main
import (
"github.com/google/nftables"
"github.com/google/nftables/binaryutil"
"github.com/google/nftables/expr"
"golang.org/x/sys/unix"
"net"
)
func main() {
c, err := nftables.New()
if err != nil {
panic(err)
}
c.FlushRuleset()
filter := c.AddTable(&nftables.Table{
Family: nftables.TableFamilyIPv4,
Name: "filter",
})
input := c.AddChain(&nftables.Chain{
Name: "output",
Hooknum: nftables.ChainHookOutput,
Priority: nftables.ChainPriorityFilter,
Table: filter,
Type: nftables.ChainTypeFilter,
})
ipSet := &nftables.Set{
Name: "ipSet",
Table: filter,
Interval: true,
KeyType: nftables.TypeIPAddr,
}
if err := c.AddSet(ipSet, nil); err != nil {
panic(err)
}
if err := c.SetAddElements(ipSet, []nftables.SetElement{
{
Key: []byte{0x00, 0x00, 0x00, 0x00},
IntervalEnd: true,
},
{
Key: []byte(net.ParseIP("10.34.11.179").To4()),
},
{
Key: []byte(net.ParseIP("10.34.11.180").To4()),
IntervalEnd: true,
},
}); err != nil {
panic(err)
}
portSet := &nftables.Set{
Name: "portSet",
Table: filter,
Interval: true,
KeyType: nftables.TypeInetService,
}
if err := c.AddSet(portSet, nil); err != nil {
panic(err)
}
if err := c.SetAddElements(portSet, []nftables.SetElement{
{
Key: []byte{0x00, 0x00},
IntervalEnd: true,
},
{
Key: binaryutil.BigEndian.PutUint16(1234),
},
{
Key: binaryutil.BigEndian.PutUint16(1235),
IntervalEnd: true,
},
}); err != nil {
panic(err)
}
c.AddRule(&nftables.Rule{
Table: filter,
Chain: input,
Exprs: []expr.Any{
&expr.Payload{
DestRegister: 1,
Base: expr.PayloadBaseNetworkHeader,
Offset: 16,
Len: 4,
},
&expr.Lookup{
SourceRegister: 1,
SetName: ipSet.Name,
SetID: ipSet.ID,
},
&expr.Meta{Key: expr.MetaKeyL4PROTO, Register: 1},
&expr.Cmp{
Op: expr.CmpOpEq,
Register: 1,
Data: []byte{unix.IPPROTO_TCP},
},
&expr.Payload{
DestRegister: 1,
Base: expr.PayloadBaseTransportHeader,
Offset: 2,
Len: 2,
},
&expr.Lookup{
SourceRegister: 1,
SetName: portSet.Name,
SetID: portSet.ID,
},
&expr.Counter{},
&expr.Log{},
&expr.Verdict{
Kind: expr.VerdictDrop,
},
},
})
if err := c.Flush(); err != nil {
panic(err)
}
} I hope that this resolves your issue. |
@turekt |
Hi @realsyy, when analysing mnl debug information, you will see that this set element is added by
Dissection of the netlink packet (
Same structure is observed when setting debug to
As to why this additional element is added by nftables, my guess would be due to use of segment trees in nftables intervals. I don't know for sure but code shows a call to
The
Condition whether the first segment should be added is met because the set exists and there are no elements yet: https://git.netfilter.org/nftables/tree/src/intervals.c?id=2f1050a6b30b41f4125ab6f0da7ea5255090ccce#n631
The content of this first segment is added inside the if block. Its value is set to 0 and flags to INTERVAL_END: https://git.netfilter.org/nftables/tree/src/intervals.c?id=2f1050a6b30b41f4125ab6f0da7ea5255090ccce#n680
|
@turekt How can i dissect a netlink packet as you do, like: |
@realsyy Once you obtain the debug messages, you need to check the source code to dissect packets. Using your case as an example. Obtain the debug message:
Use The
Checking for message types in source code: https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=3eaa940bc33a3186dc7ba1e30640ec79b5f261b9#n101, index in the enum corresponds to its value, so
The last 8 bits in the type are the same, so we can conclude that this is a message for adding a new set element. The meaning of the first 4 bits in the message type value (2560) is for you to try and conclude on your own. Now that we know that this is a message for adding a new set element, the comment above the
Moving to the appropriate struct: https://git.netfilter.org/libnftnl/tree/include/linux/netfilter/nf_tables.h?id=3eaa940bc33a3186dc7ba1e30640ec79b5f261b9#n422 The enum index corresponds to its integer value, so I'm leaving further dissection of the above packet to you as an exercise. |
@turekt Yes, i can analyze a debug message as you do by doing manual work,i thought there may be a tool like nft or any other binary program which can analyze a debug message itself, all you do is just type a bash command.Thanks very much for your guidance! |
When i used command lines
{
nft add table ip filter
nft add chain ip filter output { type filter hook output priority 0; }
nft add set filter ipSet { type ipv4_addr ; flags interval;}
nft add element ip filter ipSet {10.34.11.179}
nft add set filter portSet { type inet_service ; flags interval;}
nft add element ip filter portSet {1234}
nft add rule ip filter output ip daddr @ipSet tcp dport @portSet counter log drop
}
to add a rule related to set, it worked correctly.
But when i used nftables-main to add a similar rule, it blocked tcp flow to "127.0.0.1" too.
The code is :
func main() {
c, err := nftables.New()
if err != nil {
return
}
}
log
The text was updated successfully, but these errors were encountered: