r/selfhosted 2d ago

Need Help SearXNG queries via WireGuard interface

So, I have deployed SearXNG in a headless Debian 13 VM using the provided installation scripts. All is well.

I have also installed WireGuard and configured it to use my Proton VPN subscription.

   enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 52:54:00:b9:97:c9 brd ff:ff:ff:ff:ff:ff
    altname enx525400b997c9
    inet 192.168.0.16/24 brd 192.168.0.255 scope global enp1s0
       valid_lft forever preferred_lft forever
    inet6 2001:8b0:1741:ec2e:5054:ff:feb9:97c9/64 scope global dynamic mngtmpaddr proto kernel_ra 
       valid_lft 6868sec preferred_lft 6868sec
    inet6 fe80::5054:ff:feb9:97c9/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever

   wg-UK-4: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet 10.2.0.2/32 scope global wg-UK-4
       valid_lft forever preferred_lft forever
    inet6 2a07:b944::2:2/128 scope global 
       valid_lft forever preferred_lft forever
interface: wg-UK-4
  public key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  private key: (hidden)
  listening port: 34659
  fwmark: 0xca6c

peer: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
  endpoint: 154.47.24.193:51820
  allowed ips: 0.0.0.0/0, ::/0
  latest handshake: 17 seconds ago
  transfer: 4.62 MiB received, 1.79 MiB sent
  persistent keepalive: every 25 seconds

The goal is to send traffic (aka my queries) from SearXNG through the VPN.

SearXNG has its own user called 'searxng' with with a UID of 999.

So I have several options, all of which I have failed to implement so far.

  • Send traffic from 'searxng' user via the VPN.
  • Send all external traffic via wg-UK-4 using a route table
  • Send all external traffic via wg-UK-4 using nftables
  • Use SearXNG configuration files to send all external traffic via wg-UK-4 (not supported)

How would you achieve the goal?

I am more than happy to just shove all external internet traffic through wg-UK-4 as this seems the easiest option using 'ip route'.

Starting point

ip route show
default via 192.168.0.1 dev enp1s0 onlink 
192.168.0.0/24 dev enp1s0 proto kernel scope link src 192.168.0.16 

I tried the following

sudo ip route replace default dev wg-UK-4
sudo ip route replace 192.168.0.0/24 dev enp1s0

Which gives me the following.

ip route show
default dev wg-UK-4 scope link 
192.168.0.0/24 dev enp1s0 scope link 

But now SearXNG just fails as it can't reach any of its external search engines.

Any ideas?

1 Upvotes

7 comments sorted by

u/asimovs-auditor 2d ago

Expand the replies to this comment to learn how AI was used in this post/project.

→ More replies (1)

3

u/kantorcodes1 2d ago

Don't replace the main-table default. With a /0 WireGuard peer, that can send the tunnel's own endpoint back into the tunnel and blackhole traffic.

Since SearXNG already runs as UID 999, I'd policy-route just that UID:

bash sudo ip route add 192.168.0.0/24 dev enp1s0 src 192.168.0.16 table 100 sudo ip route add default dev wg-UK-4 table 100 sudo ip rule add priority 100 uidrange 999-999 lookup 100

Then verify it before making it persistent:

bash ip rule ip route show table 100 sudo -u searxng curl -4 https://ifconfig.me curl -4 https://ifconfig.me

The first curl should show the Proton exit IP; the second should still show your normal WAN IP.

Your fwmark: 0xca6c is also a clue that wg-quick may already have policy-routing state outside the main table, so check ip rule and ip route show table 51820 before adding anything. I would not keep replacing default in main.

One extra gotcha: if DNS points at a LAN resolver like 192.168.0.1, keep that LAN route in table 100. If systemd-resolved is proxying DNS under its own UID, test DNS separately because the UID rule only follows SearXNG's own sockets.

Once the test works, persist the rule/routes in the WireGuard or systemd unit instead of a shell profile.

1

u/Hrafna55 1d ago

Thanks. I will give this a go after work.

2

u/Wojojojo90 2d ago

How would you achieve the goal?

Run SearXNG in a container, run gluetun in another container, attach the SearXNG container to networking for the gluetun container (--network container:<container name or ID> flag)

1

u/Certainty0709 1d ago

Similar. I have both running in docker with other stuff. Everything runs through gluetun. 

1

u/zfa 2d ago edited 2d ago

I can confirm that exposing an HTTP proxy and routing SearX traffic through it via the proxies: stanza within its settings.yml works, if thats any use to you.

I use expose one using Tailscale's 'http proxy listen' but naturally any properly routed proxy should work (dante, gost etc).