23.01RC - Suricata stops working after Wireguard installed
-
@bmeeks said in 23.01RC - Suricata stops working after Wireguard installed:
After some more digging around, I think this problem may reside in the custom blocking plugin compiled into Suricata for use on pfSense. The error message "<Error> -- [ERRCODE: SC_ERR_FATAL(171)] - prefix or user NULL" is coming from the Radix Tree code in the Suricata binary. There was a change in the Radix Tree itself, and some changes in the custom blocking plugin between Suricata 6.0.4 which is the current binary in pfSense Plus 22.05 and Suricata 6.0.8 which is the current binary in pfSense Plus 23.01. The problem may be related to the subnet mask.
I decided to do some more testing and discovered some wierd issues with the passlist. First of all, I get a discrepancy between what Suricata reports to be doing, like adding an IP to the passlist, and what it then shows when "Loading and parsing passlist."
Going to Interfaces > myVPN (tun_wg0) and changing the IP to e.g. 192.n.n.n or 172.n.n.n the log shows the following:
-> adding firewall interface tun_wg0 IPv4 address 172.6.210.0 to automatic interface IP Pass List.
-> adding firewall interface tun_wg1 IPv4 address 192.168.250.0 to automatic interface IP Pass List.
output device (regular) initialized: block.log
-> Loading and parsing Pass List from: /usr/local/etc/suricata/suricata_28603_vtnet1/passlist.
-> Added IPv4 address 8.8.8.8/32 from assigned Pass List.
This is where it stopped earlier
-> Added IPv4 address 10.6.210.0/31 from assigned Pass List.
-> Added IPv4 address 10.6.250.0/31 from assigned Pass List.
-> Added IPv4 address 127.0.0.1/32 from assigned Pass List.Suricata now works it's way through and actually starts. However it does throw the same PHP error as before.
The actual list found in /usr/local/etc/suricata/suricata_28603_vtnet1 never changes, no matter what changes I make in Interfaces or inside Wireguard.
Manually removing it and restarting Suricata results in a crash, it does not seem to be created or changed? Rebooting makes no difference...
Manually editing the list and setting the same IP's as the interface has, AND using mask /31 in the passlist, will result in Suricata not starting with the same fault reported as before during parsing (this is basically the original setting from a working environment):
<Error> -- [ERRCODE: SC_ERR_FATAL(171)] - prefix or user NULLUsing mask /32 in the passlist allows it to continue through, regardless of the interface having the mask /31.
Making a change in the Interface and clicking Save Changes gives the following in suricata.log
-> Received notification of IP address change on firewall interface tun_wg1.
-> deleted address 10.6.250.0 from automatic firewall interface IP Pass List.
-> Received notification of IP address change on firewall interface tun_wg1.
-> added address 10.6.250.0 to automatic firewall interface IP Pass List.And then the error shows up:
PHP ERROR: Type: 1, File: /usr/local/pkg/suricata/suricata.inc, Line: 4310, Message: Uncaught TypeError: Cannot access offset of type string on string in /usr/local/pkg/suricata/suricata.inc:4310
Stack trace:
#0 /usr/local/pkg/suricata/suricata.inc(599): suricata_get_vpns_list()
#1 /usr/local/pkg/suricata/suricata_generate_yaml.php(46): suricata_build_list(Array, 'default')
#2 /usr/local/pkg/suricata/suricata.inc(3800): include('/usr/local/pkg/...')
#3 /usr/local/pkg/suricata/suricata.inc(933): suricata_generate_yaml(Array)
#4 /etc/inc/pkg-utils.inc(715) : eval()'d code(1): sync_suricata_package_config()
#5 /etc/inc/pkg-utils.inc(715): eval()
#6 /etc/rc.start_packages(66): sync_package('suricata')
#7 {main}
thrown @ 2023-02-04 14:09:51 -
First off, thank you for the detailed troubleshooting steps. You have confirmed what I suspected and was about to test myself today. I'll give the details on what I suspect is wrong farther down below.
You can remove that edit I suggested to the
suricata.inc
file. That turned out to be a red herring. While that area of code needs a little work, it is not the cause of Suricata failing to start when your Wireguard tunnels are present.The problem is the choice of a /31 subnet mask. I know that is now legal per a revision to the RFCs, but not all software is fully compatible yet. I think the Radix Tree subroutine in Suricata has an issue with the /31 mask. I will be looking into that to see if I can come up with a fix.
The Suricata binary does a lot of work with IP addresses in rules, so it needs a fast method for storing lots of IP addresses and subnets and then searching back through them to locate a particular entry. So, the developers included a Radix Tree API. The Radix Tree lets you insert IP addresses or subnet blocks into the tree, and then later search for them when trying to match up an IP or subnet against a previously stored value. In the case of the Pass List function in my custom blocking module, the Pass List IP entries are stored in the Radix Tree. Then, during operation when an alert fires, and the custom plugin needs to know whether to block that IP or not, it looks for it (or a subnet containing that IP) in the Radix Tree. If found, that means the IP is covered by a Pass List entry. If not found, then it is blocked.
There are two Pass Lists present on an interface. One is automatic and hidden. That hidden one contains all of the firewall's interface IP addresses (expressed with a /32 or /128 mask). The custom blocking plugin creates a subscription to receive notifications from the FreeBSD kernel routing table when it changes. That's how it maintains the hidden pass list of firewall interface IPs. The hidden pass list was created to cope with interfaces which have dynamic addresses (such as DHCP on the WAN, for example). Prior to the automatic list being in place, if DHCP changed the WAN IP it was possible for Suricata to block it. The other Pass List is the one you see and can manipulate in the GUI.
As a workaround and additional test, can you try using a /30 mask on your tunnel networks?
-
@bmeeks I might try /30 or /32 as you suggest, but as of now I'm on 22.05 on my actual pfsense...
In terms of lists that I can see, we have the one I was editing. (SSH inside the folder /usr/local/etc/suricata/suricata_28603_vtnet1). This is the same info that I can see if click View List under Interface settings in Suricata.If I add a tunnel on my 22.05 version, that new IP shows up in that list. But in my testing, none of the changes I made were reflected in that list, I had to make the changes manually...
-
@bmeeks The /30 did the trick! Changing the tunnel network to /30 subnet prior to upgrade and suricata + wireguard is running fine with 23.01-RC.
-
@gblenn said in 23.01RC - Suricata stops working after Wireguard installed:
If I add a tunnel on my 22.05 version, that new IP shows up in that list. But in my testing, none of the changes I made were reflected in that list, I had to make the changes manually...
I'm a bit confused by this statement. What do you mean you had to make changes manually?
The text file you find in the interface's subdirectory is what the Pass List code within the custom blocking plugin compiled into the binary reads its input from. That text file is recreated by the PHP code each time you start (or restart) Suricata on the interface. The data written to that file is determined by settings stored in the
config.xml
configuration file for the firewall.The original problem is the custom blocking plugin is experiencing an issue attempting to insert the tunnel address with a /31 subnet mask into the Radix Tree. That is generating the
SC_ERR_FATAL - prefix or user NULL
error message. And since Suricata logs that as a fatal error, it does not start. -
@mrsunfire said in 23.01RC - Suricata stops working after Wireguard installed:
@bmeeks The /30 did the trick! Changing the tunnel network to /30 subnet prior to upgrade and suricata + wireguard is running fine with 23.01-RC.
Thanks for the confirmation. This is a Radix Tree insertion problem within the Suricata binary and my custom blocking plugin. If a /30 works for you now, just use that and I will work on a fix for the Radix Tree problem. Unfortunately it will require a change in the binary portion of the Suricata package, so not as fast and easy as changing something in the PHP GUI code.
-
@bmeeks said in 23.01RC - Suricata stops working after Wireguard installed:
@gblenn said in 23.01RC - Suricata stops working after Wireguard installed:
If I add a tunnel on my 22.05 version, that new IP shows up in that list. But in my testing, none of the changes I made were reflected in that list, I had to make the changes manually...
I'm a bit confused by this statement. What do you mean you had to make changes manually?
I mean that the file did not change when I made changes in the GUI. However, this must have been some issue with my test environment. Just now I changed over to the 23.01 I had running when I started this thread. And now if I make a change in the GUI, it is in fact reflected in the file as well. Might have something to do with the fact that my test environment was running vtnet instead of igb (I use IOMMU). I need to check this further, at some point, but there was an igb1 folder which also contained a passlist (which I never looked at).
-
@mrsunfire said in 23.01RC - Suricata stops working after Wireguard installed:
@bmeeks The /30 did the trick! Changing the tunnel network to /30 subnet prior to upgrade and suricata + wireguard is running fine with 23.01-RC.
Thanks for the confirmation. This is a Radix Tree insertion problem within the Suricata binary and my custom blocking plugin. If a /30 works for you now, just use that and I will work on a fix for the Radix Tree problem. Unfortunately it will require a change in the binary portion of the Suricata package, so not as fast and easy as changing something in the PHP GUI code.
How do you change the tunnel network to a /30 subnet? Do you mean that you set this for the Peer(s) in the Wireguard UI?
I switched over to 23.01 now and changing things there have no effect whatsoever. Suricata is monitoring the interface not the peers, and the passlist file doesn't change until you make a change in the interface.
However, changing the Interface VPN (tun_wg0) to a /30 subnet is not allowed (This IPv4 address is the network address and cannot be used). Changing it to /32 is allowed but breaks the tunnel...
Hmmm, I see now that this is because I'm using n.n.n.0 for the gateway (n.n.n.1 at the other site). I guess if I changed that to .1 & .2 I would be able to use /30 at this end... big risk messing with the remote server though... -
@gblenn Well just change the tunnel interface to /30. Remember that you can't use a 0 at the end of an IP address within this subnet.
-
@mrsunfire said in 23.01RC - Suricata stops working after Wireguard installed:
@gblenn Well just change the tunnel interface to /30. Remember that you can't use a 0 at the end of an IP address within this subnet.
Yes that's what I realized so I need to make changes at the other site as well, which represents a bit of a risk...
-
@gblenn I feel that. Had the same. Turns out it was very handy. First change remote alias (if you have one for the tunnel). Then change remote wg interface. Now on your site and you should be good to go. That's what I did.
-
@mrsunfire Of course it stopped working, since I forgot to change routing on the remote server (as I changed gateway IP at home).... Tailscale to the rescue, I'm back in business...
Next step is to try it on 23.01...
-
And that worked, I'm up and running with 23.01.r.20230202.0019 with my full config.
-
@gblenn said in 23.01RC - Suricata stops working after Wireguard installed:
And that worked, I'm up and running with 23.01.r.20230202.0019 with my full config.
Glad you are back up and running. I will still look into the /31 issue with the Radix Tree, but it may turn out to be something upstream has to modify. The use of /31 subnet masks is still a bit iffy with software apps today. Not everything is fully onboard with that one yet.
-
@bmeeks said in 23.01RC - Suricata stops working after Wireguard installed:
@gblenn said in 23.01RC - Suricata stops working after Wireguard installed:
And that worked, I'm up and running with 23.01.r.20230202.0019 with my full config.
Glad you are back up and running. I will still look into the /31 issue with the Radix Tree, but it may turn out to be something upstream has to modify. The use of /31 subnet masks is still a bit iffy with software apps today. Not everything is fully onboard with that one yet.
Thanks, good that you keep investigating. I have no idea how common it is to use /31 in a site to site config, but I think I was following one of many guides out there...
-
@gblenn said in 23.01RC - Suricata stops working after Wireguard installed:
@bmeeks said in 23.01RC - Suricata stops working after Wireguard installed:
@gblenn said in 23.01RC - Suricata stops working after Wireguard installed:
And that worked, I'm up and running with 23.01.r.20230202.0019 with my full config.
Glad you are back up and running. I will still look into the /31 issue with the Radix Tree, but it may turn out to be something upstream has to modify. The use of /31 subnet masks is still a bit iffy with software apps today. Not everything is fully onboard with that one yet.
Thanks, good that you keep investigating. I have no idea how common it is to use /31 in a site to site config, but I think I was following one of many guides out there...
I cannot seem to reproduce your original failure. Suricata is starting for me every time without error when I put in what I think are your old tunnel networks. I want to reliably reproduce the failure so I can know if my fix actually works or not.
Can you share your Wireguard tunnel and peer addresses? And if you can, the other firewall interface IP settings as well so that I can duplicate everything in my test setup. If you don't want to post that information in the open forum, can you share them via a DM (Forum chat message)?
-
@bmeeks I can provide more detail later on when I'm back home but I think these are the key elements.
- The wireguard Interface for the home site has the IP 10.6.210.0 /31 (the peer site has 10.6.210.1 /31)
- The allowed IP's for the wireguard peer(s) use 10.6.210.0 /31 at both ends. But I do think it is the Interface that is the actual trigger here. This setting is only an internal thing for wireguard as far as I understand...
-
@gblenn said in 23.01RC - Suricata stops working after Wireguard installed:
@bmeeks I can provide more detail later on when I'm back home but I think these are the key elements.
- The wireguard Interface for the home site has the IP 10.6.210.0 /31 (the peer site has 10.6.210.1 /31)
- The allowed IP's for the wireguard peer(s) use 10.6.210.0 /31 at both ends. But I do think it is the Interface that is the actual trigger here. This setting is only an internal thing for wireguard as far as I understand...
Thank you for the details. I will try these settings in my virtual machine. I want to be able to reliably reproduce the issue so that I can test and then have confidence in any fix I come up with.
One small difference is my VM is pfSense 2.7.0 CE instead of 23.01 Plus, but I can't imagine that would matter. Suricata is exactly the same on both platforms.
-
@bmeeks I am also using VM and did make a quick test using 2.7.0 and had the same issues.
I got back home now and as I have my two tunnels up and running using /30 subnet, I decided to make a test with a third tunnel. I basically only created the tunnel, with 10.10.200.0 /31 which includes setting up the interface. I did not bother going into routing or creating a peer for that tunnel...
At first it did not seem to create the crash but I noticed that my passlist did not update.
In the drop down in Suricata I have three options: default, none and passlist_18215. I have had the 18215 selected and it wasn't until I changed over to default that I got the crash this time... So the passlist_18215 did not update but the default did... perhaps something for you to look into. -
@gblenn:
One last request -- can you post the actual contents of both the default Pass List file (from the interface subdirectory), and then also post the contents of thepasslist_18215
file? You can obfuscate the public WAN IP if you wish. I want to see if any other IP address in there is perhaps colliding with the tunnel IPs.Edit: never mind -- I just got the failure. The trick in my case to reproduce is to stop Suricata, have the Wireguard setup in place, then attempt to restart Suricata. I believe I know where and why the failure is happening. It is within the custom blocking plugin and its interaction with the Radix Tree API in the Suricata binary. I am pretty sure I can fix it, though.
Here is the
suricata.log
file showing the failure:6/2/2023 -- 09:38:29 - <Notice> -- This is Suricata version 6.0.8 RELEASE running in SYSTEM mode 6/2/2023 -- 09:38:29 - <Info> -- CPUs/cores online: 4 6/2/2023 -- 09:38:29 - <Info> -- HTTP memcap: 67108864 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> Creating automatic firewall interface IP address Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> adding firewall interface em0 IPv6 address fe80:0000:0000:0000:020c:29ff:fe38:9fdd to automatic interface IP Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> adding firewall interface em0 IPv4 address 192.168.10.29 to automatic interface IP Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> adding firewall interface em1 IPv6 address fe80:0000:0000:0000:020c:29ff:fe38:9fe7 to automatic interface IP Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> adding firewall interface em1 IPv4 address 192.168.233.10 to automatic interface IP Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> adding firewall interface vmx0 IPv6 address fe80:0000:0000:0000:020c:29ff:fe38:9ff1 to automatic interface IP Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> adding firewall interface vmx0 IPv4 address 192.168.2.1 to automatic interface IP Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> adding firewall interface lo0 IPv6 address 0000:0000:0000:0000:0000:0000:0000:0001 to automatic interface IP Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> adding firewall interface lo0 IPv6 address fe80:0000:0000:0000:0000:0000:0000:0001 to automatic interface IP Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> adding firewall interface lo0 IPv4 address 127.0.0.1 to automatic interface IP Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> adding firewall interface tun_wg0 IPv4 address 10.6.210.0 to automatic interface IP Pass List. 6/2/2023 -- 09:38:29 - <Info> -- alert-pf output device (regular) initialized: block.log 6/2/2023 -- 09:38:29 - <Info> -- alert-pf -> Loading and parsing Pass List from: /usr/local/etc/suricata/suricata_22480_em1/passlist. 6/2/2023 -- 09:38:29 - <Error> -- [ERRCODE: SC_ERR_FATAL(171)] - prefix or user NULL
The problem happens when the addition of the VPN address is attempted after the automatic pass list logic has already registered the IP for the Wireguard interface itself. Notice that it fails immediately upon attempting to load the Pass List. The WG Tunnel IP is the very first entry in my Pass List file.
The internal logic of the custom blocking plugin first grabs all of the firewall interface IP addresses and inserts those into the Radix Tree so no firewall interface IP will get blocked. Then the code reads in the Pass List file and adds those IP addresses and/or subnets to the Radix Tree. The collision happens when the Wireguard Tunnel IP values pulled in from the "get configured VPNs" call into pfSense returns the same IP value that exists for the actual Wireguard interface. When insertion of that IP is attempted with the /31 mask, the Radix Tree complains. It wants additional data supplied to help it differentiate between the two IP addresses. I suspect the /31 mask is tripping it up.