Showing posts with label hacks. Show all posts
Showing posts with label hacks. Show all posts

2026/09/16

Setting up firewall rules for a LG TV

 

I have an LG TV that, by my own choice, does not have Internet access.

It is not disconnected from my network. It is connected to the LAN, uses my DNS server, and can communicate with whatever I decide to allow. I simply have a firewall rule preventing it from accessing the Internet.

My home infrastructure uses shadowcat4 as the router/firewall, a fanless mini PC with an Intel N95 and four Intel I226-V 2.5 Gb Ethernet interfaces. It runs Slackware-current and replaced my old shadowcat3 router.

The Internet connection comes through FTTH with the ONT in bridge mode. Shadowcat4 establishes the PPPoE connection directly and also runs nftables, OpenVPN, dnsmasq, dnscrypt-proxy, and a few other things.

The LAN is 192.168.111.0/24, shadowcat4 is 192.168.111.14, and the LG TV is 192.168.111.191.

The problem appeared because of a rather silly characteristic of the TV: if it completely loses electrical power, it loses its date and time. When power comes back, it may boot believing that it is sometime in 2022.

That by itself would not be a major problem, except that I use the TV's automatic power-on feature. I want it to turn itself on at 06:00, and obviously it needs to know what time it is for that to work.

With Internet access enabled, it recovered the correct time automatically. With Internet access blocked, it did not.

So the question became quite specific:

What is the absolute minimum Internet access the TV needs solely to recover its date and time?

First suspect: NTP

The first thing I thought of, and the first thing I discussed with ChatGPT during the troubleshooting process, was the obvious candidate: NTP.

If a device needs to know the time, one would expect UDP traffic to port 123.

Shadowcat4 already uses NTP and, in fact, during the tests another interesting problem showed up: NTP queries leaving through my PPPoE connection were receiving replies very inconsistently. We captured traffic on ppp0, verified the outgoing queries, and compared the results with another machine using a different ISP.

From that other connection, the same NTP servers responded quickly and consistently.

Everything pointed toward some behavior involving the ISP or the network path used by shadowcat4.

Interesting, but ultimately a false lead for the TV problem.

Capturing the LG's traffic after a cold boot revealed something much more important:

the TV was not attempting to use UDP/123 at all.

No NTP.

Instead, it was repeatedly trying to establish TCP connections to port 443.

Opening HTTPS as a test

The firewall uses nftables with a DROP policy. The LG was given a specific rule before the general LAN access rules:

ip saddr 192.168.111.191 oifname "ppp*" drop

As a test, we temporarily inserted an exception before that DROP rule allowing the TV to connect to any destination over TCP/443.

Then I performed a real cold boot: unplugged the TV from power, waited, and plugged it back in.

It started without the correct time.

With HTTPS allowed, it recovered the correct date and time.

That completely changed the direction of the investigation. We were no longer looking for an NTP server. Some LG service accessible over HTTPS was involved in recovering the time.

Using DNS as a guide

The TV uses dnsmasq on shadowcat4 as its DNS server, so I started logging its queries.

Several domains appeared:

lgtvonline.lge.com
BR7.nextlgsdp.com
AIC.tv.wiselg.com
aic-gfts.nextlgsdp.com
qt2-kic.lgtviot.com
aic.lgtviot.com
BR7.info.lgsmartad.com

The last one was particularly amusing because my HaGeZi blocklist causes:

BR7.info.lgsmartad.com

to return NXDOMAIN.

The TV recovered its time perfectly anyway.

So advertising was out of the picture.

The domain that started looking particularly interesting was:

BR7.nextlgsdp.com

dnsmasq was returning a set of addresses such as:

54.200.71.5
54.186.200.227
32.189.217.166
16.146.234.1
32.188.96.203
52.41.138.142
52.35.116.50
16.147.145.11

The set is not permanent: the addresses rotate and change over time.

Capturing the exact moment

For most of the testing I used tcpdump.

I recorded a complete capture:

tcpdump -ni eth0 -s0 -w /tmp/tv-br7.pcap host 192.168.111.191

Before opening the firewall, there was a succession of SYN packets from the TV toward HTTPS servers, but no replies because nftables was dropping them.

After enabling the exception, the first SYN/ACK appeared:

13:47:57.785790
52.35.116.50:443 -> 192.168.111.191
Flags [S.]

A few seconds later, connections started appearing from:

52.41.138.142:443

Both addresses were part of the set DNS had just returned for BR7.nextlgsdp.com.

The correlation was very strong, but it was still a correlation.

I wanted to prove that those HTTPS connections were actually intended for that hostname.

Enter tshark

Until this point, I did not have tshark installed on shadowcat4.

I installed Wireshark 4.6.8 using the SlackBuild available from SlackBuilds.org. I did not really need the Wireshark graphical interface; I only wanted tshark to analyze the pcap file I had already generated with tcpdump.

The useful part is that, although HTTPS encrypts the application data, the TLS ClientHello can contain the SNI identifying the server name the client wants to reach.

I ran:

tshark -r /tmp/tv-br7.pcap \
  -Y 'ip.src==192.168.111.191 && tls.handshake.extensions_server_name' \
  -T fields \
  -e frame.time \
  -e ip.dst \
  -e tls.handshake.extensions_server_name

And there it was:

2026-09-16T13:47:57.800548000-0300  52.35.116.50   br7.nextlgsdp.com
2026-09-16T13:48:02.134213000-0300  52.41.138.142  br7.nextlgsdp.com
2026-09-16T13:48:05.790571000-0300  52.41.138.142  br7.nextlgsdp.com
...

Case closed.

We no longer merely knew that those IP addresses had been returned by DNS for BR7.nextlgsdp.com: we now had the TV's own TLS ClientHello declaring through SNI that it wanted to talk to:

br7.nextlgsdp.com

The definitive test

We then performed the test that actually mattered.

The firewall was configured to block all Internet access from the TV except TCP/443 toward the eight addresses that BR7.nextlgsdp.com resolved to at that moment.

Then I performed another real cold boot by physically removing power from the TV.

The LG recovered the correct date and time.

During that test it had no access to the other services it had queried through DNS. It also could not access the advertising service blocked by HaGeZi.

So, for my practical purposes, the result was demonstrated:

the TV can remain without general Internet access and only needs HTTPS access to BR7.nextlgsdp.com to recover its date and time.

I am not claiming that TLS itself is being used as a time synchronization protocol. TLS does not normally provide system time that way. Some response or part of the LG service available over HTTPS is apparently what allows the TV to obtain the information it needs.

For my firewall, that distinction does not matter. I now know which traffic needs to be allowed.

The resulting nftables configuration

The important part of the forward chain now conceptually looks like this:

TV -> current BR7.nextlgsdp.com IPs:443   ACCEPT
TV -> Internet                            DROP
established,related                       ACCEPT
LAN -> Internet                           ACCEPT

In /etc/nftables.conf I have:

ip saddr 192.168.111.191 \
ip daddr { 54.200.71.5, 54.186.200.227, 32.189.217.166, 16.146.234.1, \
           32.188.96.203, 52.41.138.142, 52.35.116.50, 16.147.145.11 } \
oifname "ppp*" tcp dport 443 accept

ip saddr 192.168.111.191 oifname "ppp*" drop

The ordering is deliberate.

The exception must come before the TV's DROP rule, and both must come before established,related and the general LAN-to-PPPoE rule.

That way, even an already-established connection from the TV cannot bypass its specific policy.

The dynamic IP problem

Naturally, one final detail remained: those eight addresses are not permanent.

My dnsmasq is version 2.93, as packaged by Slackware-current:

Dnsmasq version 2.93

Interestingly, it recognizes the --nftset option, but the official binary was compiled with:

ipset no-nftset

I could rebuild dnsmasq with nftset support and create an elegant integration between DNS and a named nftables set.

But by this point I was thinking something along the lines of: one more spot isn't going to matter to the tiger.

Updating eight IP addresses once a day does not need to become an engineering project.

So, with ChatGPT's help, I created:

/root/bin/update-lg-tv.sh

The script:

  1. queries the current A records for BR7.nextlgsdp.com using dig;

  2. extracts the IP addresses currently allowed for 192.168.111.191:443 from nftables;

  3. sorts both sets so DNS response ordering does not matter;

  4. exits without doing anything if they match;

  5. if they differ, updates the corresponding rule in /etc/nftables.conf;

  6. validates the new configuration with nft -c;

  7. saves a backup;

  8. loads the new ruleset;

  9. records what happened using logger.

There is also one important safety precaution: if dig returns no IPv4 addresses, the script changes nothing. A temporary DNS failure cannot cause a perfectly good whitelist to be replaced by an empty one.

Its first execution was exactly as boring as an administration script should be:

# /root/bin/update-lg-tv.sh
# echo $?
0

The DNS addresses matched the firewall addresses, so it did nothing.

The script can now simply be run once a day from cron. I do not need to chase DNS changes in real time: the only purpose of this exception is to let the TV recover its clock after completely losing electrical power.

As for organization, I prefer administration scripts to remain readable. If this logic grows, instead of accumulating embedded awk, sed, and subsidiary logic inside one large shell script, I will split it into small scripts under a directory such as:

/root/bin/lg-tv/
    update.sh
    get-dns-ips.sh
    get-nft-ips.sh
    update-nft-conf.sh

Not because Bash cannot do everything in one file, but because six months from now I want to be able to look at a script and immediately understand what it does.

What I liked about this experiment

The most interesting part of the whole exercise was the method.

We started with a perfectly reasonable hypothesis:

the TV needs NTP.

The evidence said otherwise.

Then we saw HTTPS.

We allowed only port 443 and verified that the TV recovered its clock.

We logged DNS queries to identify candidate services.

We reduced firewall access exclusively to the addresses belonging to one domain.

We repeated the cold boot.

It worked.

Finally, we used tshark on the packet capture to extract the TLS SNI and confirm that the connections actually getting through the firewall were going to br7.nextlgsdp.com.

The interaction with ChatGPT was particularly useful during this process, not because it could tell me in advance that "LG gets its time from this particular server," but precisely because it could not. We built hypotheses, designed tests to eliminate them, and looked at actual evidence coming from my own network.

Some paths led nowhere — the initial NTP investigation being the obvious example — but they were still useful because they eliminated possible explanations.

In the end, there was no need to trust LG documentation, Internet blocklists, or assumptions about what a Smart TV should be doing.

We watched its packets and proved what it was actually doing.

And shadowcat4 continues doing exactly what I wanted from the beginning:

the TV is connected to my network, but that does not mean it has permission to freely talk to the Internet.

2025/05/20

Firefox: Prevent Google AI on web search

 grab Greasymonkey or similar

// ==UserScript==
// @name         Google Web tab redirect
// @match        https://www.google.com/search*
// @run-at       document-start
// ==/UserScript==

(function() {
    let url = new URL(location.href);
    if (!url.searchParams.has("udm")) {
        url.searchParams.set("udm", "14");
        location.replace(url.toString());
    }
})();

 

what it does: it automatically selects the "Web" option.

If tomorrow they change/remover the attribute one could simply hide it using uBlockOrigin. 


2021/03/30

How to prevent web admin session expiration on routers (Huawei at least)

Note: this post is just a  public draft.

1)  open Firefox

2) visit your router's administration web page. 

3) Open debugger. 

4) Log in

5) on the Network tab, right click on the first entry (usually index.php or whatever) and under "Copy" select "Copy as cURL"

6) open konsole or whatever terminal you preffer

7) write watch -n 30 and a double quote, then paste and add -k -o /dev/null and close the double quotes

8) hit enter to run watch and go back to your browser.

leave your web admin tab open, otherwise you will have to repeat all the steps.


this trick might be useful on every site that makes your session expire via ajax calls.


2021/01/05

Script to prevent SSH attacks while allowing you to connect from dynamic IP address.

while most of the time connecting to a remote server using openvpn would be a smart choice, sometimes it's not an option. This script is for a linux behind a firewall/router. It's intended to prevent SSH attacks (by simply denying access to the SSH port) while allowing you to connect from your own dynamic DNS, that is, if you have a dynamic ip given by your ISP, otherwise you could simply use iptables.

#!/bin/bash
valor=`host yourdyndns`
OK=$?
if [ $OK -ne 0 ]; then
  exit
fi
addr=$(echo $valor |egrep "address .*" -o)
ip=$(echo $parte |egrep "[0-9\.]*" -o)

whitelist=/root/whitelist
touch ${whitelist}

exists=`cat ${whitelist} | grep "${parte2}"`

if [ $? -ne 0 ]; then
  echo $ip >$whitelist
  iptables -F   iptables -A INPUT -s $ip -j ACCEPT
  iptables -A FORWARD -s $ip -j \ ACCEPT                                                                                         
  iptables -A INPUT -p tcp --dport 22022 -j DROP                                                                                   
fi

add this to rc.local to reload iptables during bootup:

# delete whitelist

rm /root/whitelist

# run previous script

/root/bin/testso.sh


2021/01/03

x2x on Slackware

 I had to write something. This was kinda shocking to me. I was looking for a KVM (Keyboard, Video and Mouse) software to be able to control my notebook from my PC.  Been using an old free version of Synergy, but for some odd reason seems to be compiled for 32 bits and I felt it was a terrible waste to install multilib just to run it. So I decided to look for an alternative.

As usual, went to google and discovered that Slackbuilds has Barrier but when I tried to install it, it asked for avahi, and avahi asked for something else and that something else asked for other-something-else. So I gave up. Then I came across x2x.

This particular software has a wikipedia page so I wont bother telling the story about it.

    cd

    mkdir -p install/util/x2x

    cd install/util/x2x

    wget https://slackbuilds.org/slackbuilds/14.2/desktop/x2x.tar.gz

    tar xf x2x.tar.gz 

    cd x2x

    wget https://slackware.uk/~urchlay/src/x2x-1.30_beta+20200121_ec10215.tar.xz

    su

    ./x2x.SlackBuild

    installpkg /tmp/x2x-1.30_beta+20200121_ec10215-x86_64-1_SBo.tgz

then I have to create an script to connect to my notebook, but before I get into that I had to read the man page, last section, after the examples, gives an important tip when you have multiple monitors 

Left: 1920*1080 (primary)

Right: 1366*768

So I had to do the math and write the parameters to x2x according to the man page:

#!/bin/bash
ssh -YC rudy@macabra x2x -north -to :0.0 -big  -completeregionleft 0 -completeregionup 0 -completeregionright 3286 -completeregionlow 768

I have ssh configured so it wont ask me for password. North parameter means I placed my notebook "over" my monitors and it doesn't really matter from which monitor my mouse goes up, it appears on my notebook and it's able to travel  the entire notebook screen.

What shocked me about this is the fact it's a very old proyect, but works like a charm.