Skip to content
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

python-iptables shows error when using JOOL_SIIT for dual-stack rules #337

Closed
yaoli-zheng-axcient opened this issue Jul 20, 2020 · 8 comments
Milestone

Comments

@yaoli-zheng-axcient
Copy link

Hi,

When I use python-iptables to create rules with jool_siit for both IPv4 and IPv6, I got this error:

  File "/usr/local/lib/python3.5/dist-packages/iptc/ip4tc.py", line 728, in __init__
    raise XTablesError("can't find target %s" % (name))
iptc.errors.XTablesError: can't find target JOOL_SIIT

Here is the script to re-produce the issue:

import iptc

#ipv4 Rule
table = iptc.Table(iptc.Table.MANGLE)
chain = iptc.Chain(table, 'PREROUTING')
rule = iptc.Rule()
target = iptc.Target(rule, 'JOOL_SIIT')
rule.target = target

#ipv6 Rule
table = iptc.Table6(iptc.Table.MANGLE)
chain = iptc.Chain(table, 'PREROUTING')
rule = iptc.Rule6()
target = iptc.Target(rule, 'JOOL_SIIT')
rule.target = target

I found similar issue for other matches(ldx/python-iptables#164) and the solution seems to change _init function in src/usr/iptables/common.c to be non static, not sure if jool_siit will support or fix this use case?

Thanks!
Yaoli

@ydahhrk ydahhrk added this to the 4.1.2 milestone Jul 20, 2020
ydahhrk added a commit that referenced this issue Jul 20, 2020
@ydahhrk
Copy link
Member

ydahhrk commented Jul 20, 2020

Is it normal that it doesn't list any rules in PREROUTING mangle after running the script with apparent success?

$ sudo python3 python-bug.py
$ sudo iptables -L PREROUTING -t mangle
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         
$ sudo ip6tables -L PREROUTING -t mangle
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination 

@yaoli-zheng-axcient
Copy link
Author

Yes, the rules are not inserted, you can use this code to insert rules instead:

import iptc

#ipv4 Rule
table = iptc.Table(iptc.Table.MANGLE)
chain = iptc.Chain(table, 'PREROUTING')
rule = iptc.Rule()
target = iptc.Target(rule, 'JOOL_SIIT')
rule.target = target
chain.insert_rule(rule)

#ipv6 Rule
table = iptc.Table6(iptc.Table.MANGLE)
chain = iptc.Chain(table, 'PREROUTING')
rule = iptc.Rule6()
target = iptc.Target(rule, 'JOOL_SIIT')
rule.target = target
chain.insert_rule(rule)

@ydahhrk
Copy link
Member

ydahhrk commented Jul 23, 2020

4.1.2 released; closing.

@ydahhrk ydahhrk closed this as completed Jul 23, 2020
ydahhrk added a commit that referenced this issue Jan 27, 2023
Fixes Debian bug 1029268:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1029268

man 3 dlopen:

> Use of _init and _fini is now deprecated in favor of the
> aforementioned constructors and destructors, which among other
> advantages, permit multiple initialization and finalization functions
> to be defined.

Replace _init() with __attribute__((constructor)). Vincent Bernat
already confirmed this works.

Also returns the static keyword, which was removed during #337. I'm
conjecturing that patch likely was a misled accident, and the current
one should be the proper fix for both bugs. This, I'm not completely
sure will work, but we'll see.
@hunbalazs
Copy link

hunbalazs commented May 14, 2023

This issue was reintroduced by commit 490ddb0

The main problem is not the static keyword but the inactive define in <xtables.h>:

#define _init __attribute__((constructor)) _INIT

This define can be activated by defining XTABLES_INTERNAL so it will be overridden by _INIT which is already part of Jool's Makefile.
And probably the following line helps too (which is also activated by XTABLES_INTERNAL):

extern void _init(void);

The problem came up with python-iptables because it assumes that every extension have this function in the form of libxt_{name}_init

The second problem is GCC12 related (beginning with GCC12 _init seems to be an internal function or something like that)

Edit: The problem has nothing to do with jool (any probably python-iptables has no control over it too). libxtables is probably not prepared to handle multiple protocols in one process so using JOOL(_SIIT) with both IPv4 and IPv6 in a single run is not handled correctly.

@hunbalazs
Copy link

hunbalazs commented May 14, 2023

Without XTABLES_INTERNAL

 $ x86_64-pc-linux-gnu-gcc -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT -I../.. -Wall -Waggregate-return -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes -Wlogical-op -Winline -pipe -D_INIT=libxt_JOOL_SIIT_init -DPIC -fPIC -O2 -pipe -flto -march=native -mtune=native -o libxt_JOOL_SIIT.o -c libxt_JOOL_SIIT.c
In file included from libxt_JOOL_SIIT.c:5:
common.c:130:6: warning: no previous prototype for ‘_init’ [-Wmissing-prototypes]
  130 | void _init(void)
      |      ^~~~~
 $ nm libxt_JOOL_SIIT.o 
00000000 T iname_validate
00000000 T _init
         U optarg
         U stderr
         U xtables_register_targets

With XTABLES_INTERNAL

 $ x86_64-pc-linux-gnu-gcc -D_LARGEFILE_SOURCE=1 -D_LARGE_FILES -D_FILE_OFFSET_BITS=64 -D_REENTRANT -I../.. -Wall -Waggregate-return -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wshadow -Wstrict-prototypes -Wlogical-op -Winline -pipe -D_INIT=libxt_JOOL_SIIT_init -DPIC -fPIC -O2 -pipe -flto -march=native -mtune=native -o libxt_JOOL_SIIT.o -c libxt_JOOL_SIIT.c -DXTABLES_INTERNAL
 $ nm libxt_JOOL_SIIT.o 
00000000 T iname_validate
00000000 T libxt_JOOL_SIIT_init
         U optarg
         U stderr
         U xtables_register_targets

Edit: constructor name is irrelevant since dlopen runs registered constructor(s) before returning and ctypes uses dlopen

ydahhrk added a commit that referenced this issue May 28, 2023
@ydahhrk
Copy link
Member

ydahhrk commented May 28, 2023

Sorry; I have time now.

Edit: The problem has nothing to do with jool (any probably python-iptables has no control over it too).

So are there any problems left with 490ddb0? I'm ok with returning static if that helps.

libxtables is probably not prepared to handle multiple protocols in one process so using JOOL(_SIIT) with both IPv4 and IPv6 in a single run is not handled correctly.

I don't think this is the case. Did you try opening two sockets? I wrote a custom binary that requests one instance display to SIIT and one instance display to NAT64, and it works fine:

$ sudo modprobe jool
$ sudo modprobe jool_siit
$ 
$ sudo jool instance add -6 65:ff9b::/96 --iptables NAT641
$ sudo jool instance add -6 65:ff9b::/96 --iptables NAT642
$ sudo jool instance add -6 65:ff9b::/96 --iptables NAT643
$ sudo jool_siit instance add --iptables SIIT1
$ sudo jool_siit instance add --iptables SIIT2
$ sudo jool_siit instance add --iptables SIIT3
$ 
$ sudo dual
SIIT instances:
- SIIT2
- SIIT3
- SIIT1
NAT64 instances:
- NAT643
- NAT641
- NAT642

@ydahhrk
Copy link
Member

ydahhrk commented May 28, 2023

This prints the same results; this means the two sockets can also coexist.

@hunbalazs
Copy link

So are there any problems left with 490ddb0? I'm ok with returning static if that helps.

That patch is perfectly fine, static keyword does not seem to make any difference. I mentioned that python-iptables searches for constructors by name but that seems to be a last resort try only.

I don't think this is the case. Did you try opening two sockets? I wrote a custom binary that requests one instance display to SIIT and one instance display to NAT64, and it works fine:

Your tests has nothing to do with libxtables. You opened 2 netlink sockets what is perfectly fine (although unnecessary).

What libxtables does (and python-iptables too because it loads libxtables by dlopen) is loading extensions dynamically but it does not account for L3 protocol because it is not meant to do that since there are two distinct executable for two L3 protocol.

The root cause (to my understanding) is that when libxtables loads an extension it identifies the extension only by its name. When it first loads and extension everything loads correctly, python-iptables uses the loaded module just fine. But when you would like to use the same module for the other protocol the module loading fails since it is already loaded.

python-iptables tries to work around the problem by using a combined key ({protocol}__{modulename}) but since it can not change libxtables behavior the issue occurs.
I tried this with TPROXY too and same issue happens so it is not module dependent.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants