Triggering a curl command from tcpdump event

Hi!

A friend of mine asked me if I can turn an Amazon dash button into a PC-Poweroff trigger. I have tried some approaches I found in internet but I didn't manage to get it to work. So I came up with my own idea. I have some old routers, compatible with OpenWRT, and I know very well how they work - so why not code myself? (or with some expert help :slight_smile: ).
So, I'll start telling you what I've already done.
I have configured and IFTTT applet, which, already, powers off my PC when I visit a url with my browser or curl. So the only thing left is connect the button press to the curl command in my OpenWRT.
Now, the configuration in OpenWRT is as follow:
-This router is called JAZZTEL_VILLEGOLAS
-I have two interfaces: lan and wlan. lan is connected to my home network, subnet 192.168.1.0/24. The static IP for my JAZZTEL_VILLEGOLAS, in the lan side, is 192.168.1.25. The gateway is 192.168.1.3.
I need connection to internet in order to do the curl command. But I need it separate from the dash button, so that it doesn't connect to amazon servers and they can disable the dash button - they don't want us to continue using these buttons.
So the other interface, wlan, is separate from lan.
-The local IP of the JAZZTEL_VILLEGOLAS in the wlan side is 192.168.2.3. The gateway is configured as 192.168.2.1 which doesn't exist, I mean, there is no host with that IP. But I imagine it is necessary to make the dash button think there's a gateway so that it tries to connect home.
-In the lan side the DHCP server is disabled, but in the wlan side the DHCP server is enabled.
-I think it is easier to advance if I share the /etc/config/dhcp, so this is the content:

config dnsmasq
        option domainneeded '1'
        option boguspriv '1'
        option filterwin2k '0'
        option localise_queries '1'
        option rebind_protection '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option nonegcache '0'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
        option nonwildcard '1'
        option localservice '1'
        option ednspacket_max '1232'

config dhcp 'lan'
        option interface 'lan'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'
        option ignore '1'

config dhcp 'wan'
        option interface 'wan'
        option ignore '1'

config odhcpd 'odhcpd'
        option maindhcp '0'
        option leasefile '/tmp/hosts/odhcpd'
        option leasetrigger '/usr/sbin/odhcpd-update'
        option loglevel '4'

config dhcp 'wlan'
        option interface 'wlan'
        option start '100'
        option limit '150'
        option leasetime '12h'
        list dhcp_option '3,192.168.2.1'

config host
        option name 'DASHBUTTON'
        option mac '68:37:E9:33:B5:90'
        option ip '192.168.2.26'

So the networking aspect is, I think, already configured and OK.
Now I'll ask you what I really don't understand.
I want to do a kind of a script, which is always executing in a loop, with the command tcpdump, and when it detects dash button activity, it triggers the curl command. I already have the URL that curl needs to visit.
But I don't know how I can make that script. For example, I have captured the activity that happens when I press the button (connected to the wlan). I saw the output before pressing the button, during a minute, and there's no output. But when I press the button (only once), I see some activity, and then it stops again. This is the output of the command I tried:

root@JAZZTEL_VILLEGOLAS:~# tcpdump -i wlan0 host 192.168.2.26 -U -s0 | cat
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wlan0, link-type EN10MB (Ethernet), capture size 262144 bytes
21:17:15.962210 IP JAZZTEL_VILLEGOLAS.lan.67 > DASHBUTTON.lan.68: BOOTP/DHCP, Reply, length 300
21:17:16.207353 ARP, Request who-has JAZZTEL_VILLEGOLAS.lan tell DASHBUTTON.lan, length 28
21:17:16.207441 ARP, Request who-has JAZZTEL_VILLEGOLAS.lan tell DASHBUTTON.lan, length 28
21:17:16.207537 ARP, Reply JAZZTEL_VILLEGOLAS.lan is-at 38:72:c0:b0:f5:4d (oui Unknown), length 28
21:17:16.354042 IP DASHBUTTON.lan.57558 > JAZZTEL_VILLEGOLAS.lan.53: 57528+ A? dash-button-na.amazon.com. (43)
21:17:16.364336 IP JAZZTEL_VILLEGOLAS.lan.53 > DASHBUTTON.lan.57558: 57528 1/0/0 A 52.46.137.32 (59)
21:17:16.417819 IP DASHBUTTON.lan.57558 > JAZZTEL_VILLEGOLAS.lan.53: 57528+ A? dash-button-na.amazon.com. (43)
21:17:16.418396 IP JAZZTEL_VILLEGOLAS.lan.53 > DASHBUTTON.lan.57558: 57528 1/0/0 A 52.46.137.32 (59)
21:17:16.539424 ARP, Request who-has 192.168.2.1 tell DASHBUTTON.lan, length 28
21:17:16.539507 ARP, Request who-has 192.168.2.1 tell DASHBUTTON.lan, length 28
21:17:19.417512 ARP, Request who-has 192.168.2.1 tell DASHBUTTON.lan, length 28
21:17:19.417605 ARP, Request who-has 192.168.2.1 tell DASHBUTTON.lan, length 28
^C18 packets captured
18 packets received by filter
0 packets dropped by kernel

So I imagine there's a way to detect any activity as the output I showed you, but I imagine too that it has to be something that only occurs once - so that it is triggered only once. But I don't have a lot of experience in shell scripting.
Can you please tell me any example I could do with this information? If you need more information, I could give you the information, please just ask. I will be reviewing this post.
Thanks in advance.
Cheers

Are you sure that this is a correct approach?
There can be any traffic from dashbutton, dhcp request, dhcp renewal, arp request, dns, etc which may trigger the shutdown even if the button was not pressed.

1 Like

Tomorrow I will do a test: I will capture with the same command as in the example, but during, for example, 30 hours. I think, from what I read, that these buttons are designed to save energy, so that the battery lasts a lot of time. So, for example, maybe only connect when you press the button. For example too, they don't have a clock, not to waste energy.
Thanks

If you know the domain/URL the dash button is trying to reach and you don't need to use it outside of your special case, I believe you can tweak the fakeinternet package: https://docs.openwrt.melmac.net/fakeinternet/.

Inside is a shell script and it's designed to render different HTML outputs for different requests, you can easily tweak it to call curl while/instead of rendering an HTML page.

2 Likes

Thanks!
I'm going to try that solution.
I will tell you after.

Hi again @stangri
I have installed fakeinternet and luci-app-fakeinternet.
Now I've explored the /etc/config/fakeinternet and the luci fakeinternet menu, also the /www_fakeinternet/error.cgi
In the first ones, I didn't find any way to trigger the curl command or any way to visit my custom url.
In the error.cgi, I find that it is working with the part of the URL that is after the http://example.com/, so I don't know where to enter the dash-button-na.amazon.com address.
I have started by editing the /etc/config/fakeinternet, as follows:

config fakeinternet 'config'
        option enabled '1'
        option icmp_redirect '0'

config policy
        option action 'block'
        option address 'dash-button-na.amazon.com'

I also tried to edit /etc/init.d/fakeinternet, like this:

[...]
##before this it remains unchanged

load_package_config() {
        config_load "$packageName"
        config_get_bool serviceEnabled 'config' 'enabled' 0
        config_get_bool icmpRedirect   'config' 'icmp_redirect' 0
        config_get wwwIP               'config' 'www_ip' 'https://maker.ifttt.com/trigger/button/json/with/key/mykey-sdpahdf'
        config_get wwwPort             'config' 'www_port' '443'
        config_get domainsList         'config' 'address'
        config_get dnsmasqFile               'config' 'dnsmasqFile' "/var/dnsmasq.d/${packageName}"
}
##and after this it remains unchanged
[...]

but it is not working.
So, please, can you tell me what configuration file I should change to trigger my custom URL, each time my dash button send the previous request I included in my tcpdump capture? and how should I configure the file?
I don't need to use fakeinternet for other uses, so we can set my URL for all URL matching the /etc/config/fakeinternet
Thanks for your help

Hi again. I have been thinking about this and it may be simpler than using fakeinternet.
If @stangri replies my with something valid, it would be ok, but I'm also considering doing a simple script, that pipes the output of

tcpdump -i wlan0 host 192.168.2.26 -U -s0

to

grep dash-button-na.amazon.com

and then it can activate the curl command.
I have been googling and trying to understand how a tcpdump command can pass each line to grep, in realtime, and put all those in an if statement that executes the command

curl https://maker.ifttt.com/trigger/button/json/with/key/mykey-sdpahdf

But everything I tried doesn't work.
Does anybody know how could I code this as a script?
I could then add it to cron with the @reboot option.
Thanks

Like I said above, you need to modify the shell script in error.cgi to call curl instead of/in addition to rendering HTML page. The fakeinternet package will help you intercept and process the request of a specific domain/page you just need to modify shell script to process it the way you want.

That's the extent I can help you, maybe someone else can provide you with the error.cgi which will do exactly what you want if you are unable to modify the shell script yourself.

I have added this to error.cgi:

elif [ "$REQUEST_URI" = "dash-button-na.amazon.com" ]; then
        wget https://maker.ifttt.com/trigger/button/json/with/key/mykey-sdpahdf

between the first if statement and the next elif statement. But it doesn't work.
--EDIT--
I don't know what I'm doing wrong? If you @stangri can help me it would be fine, and if you don't have the time or whatever, please, can something help me with the method I was trying, pipelining tcpdump - grep - wget / curl?
Thanks.

I can't offer help specific to fakeinternet but a suggestion is to look at logs to see what if anything is logged. see any app logs, dmesg and logread.

Adding your own echo or printf statements can help.
Example:

elif [ "$REQUEST_URI" = "dash-button-na.amazon.com" ]; then
        echo "URI matched - $REQUEST_URI - trying wget."
        wget https://maker.ifttt.com/trigger/button/json/with/key/mykey-sdpahdf
        echo "Done with wget."

Also, /usr/bin/logger can be used to add entries to the sys log buffer if the shell script output does not automatically get written to to it.

Hi, thanks for your help.
I have included the echo commands before and after the wget command, inside the elif statement, then rebooted, and then I press the button and after I did this:

root@JAZZTEL_VILLEGOLAS:~# dmesg | grep URI
root@JAZZTEL_VILLEGOLAS:~# logread | grep URI
root@JAZZTEL_VILLEGOLAS:~#

but no matches.
For making sure about the button press, I captured with the tcpdump command and I saw the dash-button-na.amazon.com line, and after the same log commands again, but no good luck.
Also I read the /usr/bin/logger and I only see strange characters. Anyway, I'm not sure whether or not I understand well what you said about /usr/bin/logger.

No, don't do echo there, as random output will mess up the HTML page being rendered.

Wrong variable to match.

1 Like

logger is a way to write to the sys log and would replace the echo statements. See logger -h or google it for more info. Based on stangri's recent reply, I don't know if logger is safe either.

It may also be better to look at the log with starting logread -f in another ssh session before testing and stopping the logread after so that you see all messages.

In the tcpdump you shared, you only present the DNS request. Is the subsequent web transaction http or https? Does fakeinternet work with https?

I am not saying this approach is suitable as a solution for your use case but to answer your question on how to script something like this, the following example script using a while read loop might get you started on understanding.

#!/bin/sh

#myString="amazon"
myString="dash-button-na.amazon.com"

while read line
do
    aMatch=`echo $line |grep $myString`
    #echo $aMatch
    if [ -n "$aMatch" ]
        then 
        echo "got a hit!"
        curl --head "http://maker.ifttt.com/"
    fi

done

I did a chmod +x on the script file to make it executable.

I tested by putting your sample tcpdump data in a temp file /tmp/pb.z and then piping it to my test script named pb with
cat /tmp/pb.z |pb

I hope this helps.

Hi again!
I found the solution yesterday, but I'm sorry I didn't post it because I was so tired.
I did a script myselft, and based on it I did an init.d service, and it finally worked!
the script:

#!/bin/sh /etc/rc.common
#coded by borhacker


START=21
continue=true
start() {

while [ $continue == true ]
do
if [ `timeout 10 tcpdump -i wlan0 host 192.168.2.26 -U -s0 -v | grep -c "dash-button-na.amazon.com" ` -gt 0 ]
then
echo "match"
curl https://maker.ifttt.com/trigger/button/json/with/key/mykey-sdpahdf
else
echo "no-match"
fi
done
}

stop() {
continue=false
}

Thanks anyway to both @stangri and @spence

1 Like

Hi again!

I thought I had got it to work, but there are some problems regarding the infinite loop I desinged. Initially I made a script called / placed into /etc/init.d/dasbutton. But I saw there were problems, for example, when I execute reboot it doesn't work. Also I couldn't ping google.com.
Then I decided to place a dashbutton2 (after, dashbutton3) in /root/sourced/dasbutton3 . And I added it to /etc/rc.local. I also made dashbutton3 executable. The content of dashbutton3:

#!/bin/sh
#coded by borhacker


continue=true

while [ $continue == true ]
do
if [ `timeout 10 tcpdump -i wlan0 host 192.168.2.26 -U -s0 -v | grep -c "DASHBUTTON.lan" ` -gt 0 ]
then
echo "match"
curl https://maker.ifttt.com/trigger/button/json/with/key/mykey-sdpahdf
else
echo "no-match"
fi
done

The content of /etc/rc.local:

# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.

/root/sourced/dashbutton3
exit 0

But also this script, run continuously, makes impossible to run the reboot command. Like for example, in the command line, I run reboot and the console doesn't close and the system doesn't reboot. Also I don't know what more else could be not working. Then I tried to delete the line:

/root/sourced/dashbutton3

Then poweroff physically and poweron again, and the reboot command is working again. So I'm sure this problem is because of the script dashbutton3.
Also, regarding to the dash button function, it's working well, I have some little problems, but those are related to the button itself, because it doesn't work always the same way. But it's enough for me.
Could someone, please, tell me what I'm doing wrong? related to the script dashbutton3.
--EDIT--
If I don't put the /root/sourced/dashbutton3 in the /etc/rc.local file, and I execute dashbutton3, like this:

root@JAZZTEL_VILLEGOLAS:~# ./sourced/dashbutton3

It works fine and it responds to all button presses, but from /etc/rc.local it doesn't work well.
I have also tried to put this inside /etc/rc.local:

/root/sourced/dashbutton3 &

but it doesn't work well

Thanks in advance

I'm thinking,
while the main problem has already been resolved (tcpdump triggering a curl command), should I continue my new problem in another thread? because now it's about a script which starts at boot and it gives me a problem and I can't reboot, and also I don't know what more else could happen in the future? So can someone tell me whether I should do a new thread or not?
Thanks