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

Slow performance loading some web pages #481

Closed
Techtonictools opened this issue Aug 25, 2021 · 17 comments
Closed

Slow performance loading some web pages #481

Techtonictools opened this issue Aug 25, 2021 · 17 comments
Milestone

Comments

@Techtonictools
Copy link

Techtonictools commented Aug 25, 2021

I've been using OpenSnitch starting on a laptop with infrequent use and now I'm using it on my main PC and laptop on a daily basis. It is such a great tool. I've never used or seen anything like it (I don't run mac now) and I'm using it to block Microsoft from trying to update my VM through their back doors and hacks they added so that they can force-feed updates and control my PC. It is also useful to block data mining of my activity on the web and data mining on the PC itself. OpenSnitch additionally enables me to reduce being manipulated through ads on the web and it brings awareness about what apps want to phone home, giving me control of deciding who can phone home and who cannot.

Describe the bug
I have OpenSnitch configured so that everything is blocked except for domains in an exception list. Then I maintain that list of approved sites. The issue I've been hitting is it takes a long time to load some of the heavy websites. Sites that seem to have lots of libraries, requests to complete and code to load like weather underground (WU) does, those sites reproduce a performance issue. Some sites load quickly enough and there isn't any perf issue, like when using old.reddit.com, posting, searching, etc.

I had previously used a tool called Fiddler on Windows to block all http requests that respected the system proxy, except for websites in a list, and I'd surf the web using it for protection. When I was using that setup and loaded WU, it did not have a slow down. I know that Fiddler is not a full software proxy like OpenSnitch, but I think that when using Fiddler in that way to load WU, it demonstrated that failing requests doesn't make the page take a long time to load.

The wait time I'm experiencing to load WU with OpenSnitch is about 68 seconds before seeing any rendering at all and before load completes. With OpenSnitch off and clearing the browser cache, the page loaded in 4 seconds. Tor (unrestricted in OpenSnitch) loads the page in 7 seconds. Tor-like speed would be great. Could there be performance improvements made for the web surfing scenario in OpenSnitch?

To Reproduce
1. Modify the attached rules to include a correct directory path to store the exception list in
2. Create the exception list from using the domains listed below and stick it in that path in step 1
3. Launch Firefox and clear the cache if the WU site has been visited before
4. Enter WU in the address bar, invoke it and begin timing https://www.wunderground.com/forecast/us/wa/seattle
5. End timing when you see the page beginning to render

Expected behavior (optional)
1. Some fonts won't load, there will be spinners that never die and the page may look incomplete.
2. The page will have what looks like an HTML canvas drawing of the 10 day forecast that is completely legible and usable with a mouse-over.
3. Less than 15 second load time. I don't know what is reasonable since I don't know what work is being done for filtering the requests. 15 seconds is just an arbitrary number.

OS (please complete the following information):
The perf issue reproduces on my Macbook Pro 17", but it also reproduces on a custom PC that is much faster. Both have an unused wired NIC and WiFi. Both use the same internet connection/gateway. The config:

OpenSnitch 1.4.0rc4
Debian GNU/Linux 11 (bullseye)
Gnome 3.38.5
Firefox 78.13.0esr 
Tor 10.5.5
USB NIC: Bus 003 Device 003: ID 148f:761a Ralink Technology, Corp. MT7610U ("Archer T2U" 2.4G+5G WLAN Adapter
00:19.0 Ethernet controller: Intel Corporation 82579V Gigabit Network Connection (rev 05)
Intel® Core™ i7-3930K CPU @ 3.20GHz × 12 
24 GB RAM

Additional context
Traceroute

anon@dev:~$ traceroute wunderground.com
traceroute to wunderground.com (23.212.36.241), 30 hops max, 60 byte packets
 1  _gateway (192.168.43.1)  2.769 ms  3.063 ms  4.153 ms
 2  202.sub-66-174-26.myvzw.com (66.174.26.202)  74.140 ms  67.462 ms  74.276 ms
 3  * * *
 4  50.sub-69-83-152.myvzw.com (69.83.152.50)  67.260 ms  73.449 ms  73.770 ms
 5  * * *
 6  76.sub-69-83-128.myvzw.com (69.83.128.76)  73.207 ms  76.739 ms  60.019 ms
 7  135.sub-69-83-129.myvzw.com (69.83.129.135)  71.213 ms  71.544 ms  71.528 ms
 8  0.csi1.WJRDUT30-MSE01-BB-SU1.ALTER.NET (140.222.7.46)  76.963 ms  77.048 ms  76.751 ms
 9  * * *
10  * * *
11  0.ae2.GW8.LAX15.ALTER.NET (140.222.3.107)  96.008 ms  90.581 ms 0.ae1.GW8.LAX15.ALTER.NET (140.222.3.105)  90.940 ms
12  152.179.21.130 (152.179.21.130)  91.456 ms  87.283 ms  109.814 ms
13  * * *
14  * * *
15  * * *
16  * * *
17  * * *
18  * * *
19  * * *
20  * * *
21  * * *
22  * * *
23  * * *
24  * * *
25  * * *
26  * * *
27  * * *
28  * * *
29  * * *
30  * * *
anon@dev:~$ 

Exception list for WU

127.0.0.1 api3.weather.com
127.0.0.1 api2.weather.com
127.0.0.1 api0.weather.com
127.0.0.1 api1.weather.com
127.0.0.1 api.weather.com
127.0.0.1 api.mapbox.com
127.0.0.1 dsx.weather.com 
127.0.0.1 www.wunderground.com
127.0.0.1 wunderground.com

rules.zip

@gustavo-iniguez-goya
Copy link
Collaborator

The wait time I'm experiencing to load WU with OpenSnitch is about 68 seconds before seeing any rendering at all and before load completes. With OpenSnitch off and clearing the browser cache, the page loaded in 4 seconds. Tor (unrestricted in OpenSnitch) loads the page in 7 seconds. Tor-like speed would be great. Could there be performance improvements made for the web surfing scenario in OpenSnitch?

Sure. I think in this case the problem will be the blocklists, I've experienced similar issues on some websites, did you try it out without the blocklists rules?

I'll take a look at it.

@Techtonictools
Copy link
Author

The wait time I'm experiencing to load WU with OpenSnitch is about 68 seconds before seeing any rendering at all and before load completes. With OpenSnitch off and clearing the browser cache, the page loaded in 4 seconds. Tor (unrestricted in OpenSnitch) loads the page in 7 seconds. Tor-like speed would be great. Could there be performance improvements made for the web surfing scenario in OpenSnitch?

Sure. I think in this case the problem will be the blocklists, I've experienced similar issues on some websites, did you try it out without the blocklists rules?

I'll take a look at it.

Awesome. With OpenSnitch running and unrestricted firefox rules (as was Tor in the 7 sec load result), it took 4 seconds to load WU.

@gustavo-iniguez-goya
Copy link
Collaborator

Yes, I've reproduced it, and it's the same problem I already saw. I think the problem is that we're just dropping the requests instead of rejecting them , so in some cases the apps wait until the DNS resolution times out. I didn't find a way of rejecting them with libnetfilter-queue. One way of fixing this issue could be replying a DNS answer poiting to localhost.

@Techtonictools
Copy link
Author

That makes sense, I did see a host request name bubble in firefox sit there for a long time. I wouldn't know what to suggest other than close the socket, but that may not be supported for all protocols. I've used ss -K dst xxx to kill requests, but it is limited.

@gustavo-iniguez-goya
Copy link
Collaborator

gustavo-iniguez-goya commented Aug 25, 2021

well, mmmh, now that you mention killing requests, I guess that we could kill connections via netlink.conntrack .. interesting. So conman.Parse() could return an action along with the properties of a connection and kill it on demand. I'll write a PoC some day in the near future 👍

edit:
killing connections doesn't make any difference.

@gustavo-iniguez-goya
Copy link
Collaborator

hey @Techtonictools , could you test it with this daemon?
opensnitchd-reject-#481.gz

Stop the running service, rename the daemon to opensnitchd if you wish, and launch it from a terminal: ./opensnitchd-reject -rules-path /etc/opensnitchd/rules/
Edit the .json that blocks everything with a text editor (not the GUI) and change the Action to "reject".

I think it's working as expected, killing the outgoing requests. WU loads much faster.

@Techtonictools
Copy link
Author

Absolutely. On my laptop I edited the default-config.json and changed the DefaultAction field to reject, stopped the service and launched the private binary. The program spewed an error and didn't start.

{"Server": {"Address": "unix:///tmp/osui.sock", "LogFile": "/var/log/opensnitchd.log"}, "DefaultAction": "reject", "DefaultDuration": "once", "InterceptUnknown": false, "ProcMonitorMethod": "proc", "LogLevel": 0}


anon@debian:~/Downloads$ ./opensnitchd-reject-.481 -rules-path /etc/opensnitchd/rules/
[2021-08-26 16:50:15]  IMP  Starting opensnitch-daemon v1.4.0rc4
[2021-08-26 16:50:15]  INF  Loading rules from /etc/opensnitchd/rules ...
[2021-08-26 16:50:15]  INF  loading domains lists: lists, lists.domains, /home/anon/opensnitch
[2021-08-26 16:50:15]  INF  loading domains lists: lists, lists.domains, /home/anon/opensnitch/
[2021-08-26 16:50:15]  INF  monitor lists started: /home/anon/opensnitch
[2021-08-26 16:50:15]  INF  monitor lists started: /home/anon/opensnitch/
[2021-08-26 16:50:15]  INF  loading domains lists: lists, lists.domains, /home/anon/opensnitch
[2021-08-26 16:50:15]  INF  clearing domains lists: 0 - /home/anon/opensnitch/
[2021-08-26 16:50:15]  INF  clearing domains lists: 0 - /home/anon/opensnitch
[2021-08-26 16:50:15]  INF  monitor lists started: /home/anon/opensnitch
[2021-08-26 16:50:15]  INF  clearing domains lists: 0 - /home/anon/opensnitch
[2021-08-26 16:50:15]  INF  loading domains lists: lists, lists.domains, /home/anon/opensnitch
[2021-08-26 16:50:15]  WAR  Is opensnitchd already running?
[2021-08-26 16:50:15]  !!!  Error while creating queue #0: Error unbinding existing q handler from AF_INET protocol family: operation not permitted
anon@debian:~/Downloads$ sudo systemctl status opensnitch
● opensnitch.service - OpenSnitch is a GNU/Linux application firewall.
   Loaded: loaded (/lib/systemd/system/opensnitch.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Thu 2021-08-26 09:42:06 MST; 8min ago
     Docs: https://github.com/gustavo-iniguez-goya/opensnitch/wiki
  Process: 3332 ExecStartPre=/bin/mkdir -p /etc/opensnitchd/rules (code=exited, status=0/SUCCESS)
  Process: 3333 ExecStart=/usr/bin/opensnitchd -rules-path /etc/opensnitchd/rules (code=exited, status=0/SUCCESS)
 Main PID: 3333 (code=exited, status=0/SUCCESS)

Aug 26 09:39:22 debian opensnitchd[3333]: [2021-08-26 16:39:22]  INF  loading domains lists: lists, lists.domains, /home/anon/opensnitch
Aug 26 09:39:22 debian opensnitchd[3333]: [2021-08-26 16:39:22]  INF  clearing domains lists: 0 - /home/anon/opensnitch/
Aug 26 09:39:22 debian opensnitchd[3333]: [2021-08-26 16:39:22]  INF  loading domains lists: lists, lists.domains, /home/anon/opensnitch
Aug 26 09:39:22 debian opensnitchd[3333]: [2021-08-26 16:39:22]  INF  monitor lists started: /home/anon/opensnitch
Aug 26 09:39:22 debian opensnitchd[3333]: [2021-08-26 16:39:22]  INF  clearing domains lists: 0 - /home/anon/opensnitch
Aug 26 09:39:22 debian opensnitchd[3333]: [2021-08-26 16:39:22]  INF  monitor lists started: /home/anon/opensnitch
Aug 26 09:39:22 debian opensnitchd[3333]: [2021-08-26 16:39:22]  INF  clearing domains lists: 0 - /home/anon/opensnitch
Aug 26 09:42:06 debian systemd[1]: Stopping OpenSnitch is a GNU/Linux application firewall....
Aug 26 09:42:06 debian systemd[1]: opensnitch.service: Succeeded.
Aug 26 09:42:06 debian systemd[1]: Stopped OpenSnitch is a GNU/Linux application firewall..
anon@debian:~/Downloads$

debian version:

Linux version 4.19.0-17-amd64 ([email protected]) (gcc version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.194-1 (2021-06-10)

@gustavo-iniguez-goya
Copy link
Collaborator

oops, I see, you need to launch it as root:

anon@debian:~/Downloads$ sudo su

# service opensnitch stop
# ./opensnitchd-reject-.481 -rules-path /etc/opensnitchd/rules/

@Techtonictools
Copy link
Author

When running the private as root, I didn't notice a perf change. It took 38 seconds to load WU on the laptop with the private bin and on my main pc on the same gateway with the release version it took 37 seconds. How long does it take for it to load on your host?

@gustavo-iniguez-goya
Copy link
Collaborator

Without killing connections (Action: deny) it takes 1' to just display some text of the page and 1'40" for the loading progress bar to stop (I'm on a really slow connection, 50-500KB/s).

Killing connections (Action: reject) the loading progress bar stops in about 10-22s, almost at the same time that any text is displayed. Although it seems to load faster, I can see that it keeps loading resources in background, and it takes 40s in total +-.

I think I'll push these changes to a new branch in order to save it, and maybe add the "reject" Action for the v1.5.0.

In any case, we could also reply to DNS queries pointing blocked domains to localhost. If someone wants to work on this and make a PoC it'd be more than welcome.

gustavo-iniguez-goya added a commit that referenced this issue Aug 27, 2021
When blocking a connection via libnetfilter-queue using NF_DROP the
connection is discarded. If the blocked connection is a DNS query, the app
that initiated it will wait until it times out, which is ~30s.

This behaviour can for example cause slowdowns loading web pages: #481

This change adds the option to reject connections by killing the socket
that initiated it. Just set a rule's Action to "reject".

Denying:
    $ time telnet 1.1.1.1 22
    Trying 1.1.1.1...
    telnet: Unable to connect to remote host: Connection timed out

    real	2m10,039s

Rejecting:
    $ time telnet 1.1.1.1 22
    Trying 1.1.1.1...
    telnet: Unable to connect to remote host: Software caused connection abort

    real	0m0,005s

TODO: add the reject option to the GUI (preferences, pop-up and rules
dialog)
@gustavo-iniguez-goya
Copy link
Collaborator

gustavo-iniguez-goya commented Aug 27, 2021

for anyone interested and future reference: 1b8ec16

feedback welcome by the way.

@Techtonictools
Copy link
Author

Without killing connections (Action: deny) it takes 1' to just display some text of the page and 1'40" for the loading progress bar to stop (I'm on a really slow connection, 50-500KB/s).

Killing connections (Action: reject) the loading progress bar stops in about 10-22s, almost at the same time that any text is displayed. Although it seems to load faster, I can see that it keeps loading resources in background, and it takes 40s in total +-.

I think I'll push these changes to a new branch in order to save it, and maybe add the "reject" Action for the v1.5.0.

In any case, we could also reply to DNS queries pointing blocked domains to localhost. If someone wants to work on this and make a PoC it'd be more than welcome.

I'd like to look at the code, but I'm not sure I can fix it and for sure can't do it right away. Where in the source is the logic that determines if a request will be allowed or denied?

@gustavo-iniguez-goya
Copy link
Collaborator

There're 2 points in the code that you can look at:

  1. outbound connections:

If the domain is in a block/allowlist the response could be crafted here.

  1. DNS responses:

    Intercepted by a rule in the INPUT chain of ip/nftables:

    target     prot opt source               destination         
    NFQUEUE    udp  --  anywhere             anywhere             udp spt:domain NFQUEUE num 0 bypass
    

Modifying the packet here wouldn't have much sense I guess, since we would have to wait for the response.

SetVerdict*() funcs are defined in netfilter/packet.go and they send the verdict through a channel (netfilter/queue.go), optionally

@Techtonictools
Copy link
Author

Thanks for laying that out, gustavo. I started to read the code path going backwards from onPacket for this issue and also for issue #482 . All these types, libraries and golang are new to me. I want to read up on all the libraries and learn how this program works so I can understand it.

@gustavo-iniguez-goya
Copy link
Collaborator

I'm starting to feel confident with the Action: reject, it seems to work fine (if it improves web pages loading times is another story). Maybe I'll add it for this release:

deny:

$ time curl duckduckgo.com
curl: (6) Could not resolve host: duckduckgo.com

real    0m20,049s
user    0m0,007s
sys     0m0,012s

reject:

$ time curl duckduckgo.com
curl: (6) Could not resolve host: duckduckgo.com

real    0m0,043s
user    0m0,012s
sys     0m0,006s

I don't know if you mentioned it already, but could you reproduce this problem using "proc" monitor method? I want to discard that it's not due to the ebpf module.

@Techtonictools
Copy link
Author

Techtonictools commented Sep 6, 2021 via email

@gustavo-iniguez-goya gustavo-iniguez-goya added this to the 1.5.0 milestone Sep 10, 2021
gustavo-iniguez-goya added a commit that referenced this issue Sep 12, 2021
When blocking a connection via libnetfilter-queue using NF_DROP the
connection is discarded. If the blocked connection is a DNS query, the app
that initiated it will wait until it times out, which is ~30s.

This behaviour can for example cause slowdowns loading web pages: #481

This change adds the option to reject connections by killing the socket
that initiated them.

Denying:
    $ time telnet 1.1.1.1 22
    Trying 1.1.1.1...
    telnet: Unable to connect to remote host: Connection timed out

    real	2m10,039s

Rejecting:
    $ time telnet 1.1.1.1 22
    Trying 1.1.1.1...
    telnet: Unable to connect to remote host: Software caused connection abort

    real	0m0,005s
@gustavo-iniguez-goya
Copy link
Collaborator

hey! I think this issue is resolved in latest RC2: https://github.com/evilsocket/opensnitch/releases/tag/v1.5.0-rc.2

So I'm closing this now. If the issue remains, please reopen it and we'll take a look.

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

No branches or pull requests

2 participants