Search This Blog

Showing posts with label Linux. Show all posts
Showing posts with label Linux. Show all posts

Wednesday, July 09, 2025

Renew getssl automatically

 run this on cron every 30 */13 - requires preshared ssh key between the webserver and router

 #!/bin/bash
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3 RETURN
exec 1>>/var/log/upd-gtssl.log 2>&1
echo "$(date) : Script - start" >&3 # This still shows on console

# make sure this runs every 89 days since the day the cert was renew. (in my case this happen to be "day 59 of a 89 days cycle")
if test $(( $(date +%s)/24/60/60%89 )) = 59; then
echo $(date) - renew cert.

#open port 80 in firewall, so getssl can be confirmed
ssh -x router -q 'iptables -t nat -I PREROUTING -d $(nvram get wan_ipaddr) -p tcp --dport 80 -j DNAT --to-destination webserver:80 && iptables -I FORWARD -p tcp -d webserver --dport 80 -j ACCEPT'

#renew cert
cd /usr/local/etc/getssl/
/usr/local/etc/getssl/getssl mydomain.tld
sleep 10

#close port 80 in firewall, we don't run plain http
ssh -x router -q 'iptables -t nat -D PREROUTING -d $(nvram get wan_ipaddr) -p tcp --dport 80 -j DNAT --to-destination webserver:80 && iptables -D FORWARD -p tcp -d webserver --dport 80 -j ACCEPT'
else
echo $(date) - Cert still good.
fi

Wednesday, February 05, 2025

RPI network reconnect

to be run */10 * * * * from cron

#!/bin/bash

wlan='wlan0'
gateway='192.168.1.1'

ping -c2 $gateway 2>&1 >/dev/null; rc=$?
if [[ $rc -eq 0 ]] ; then
        echo `date +"%b %d %T "`$0": The network is up."
else
        echo `date +"%b %d %T "`$0": Network down! Attempting reconnection."
        if [ -f /storage/.cache/nonet ]; then
                rm -f /storage/.cache/nonet
                reboot
        fi
        ifdown $wlan
        rmmod brcmfmac
        sleep 2
        modprobe brcmfmac brcmfmac_wcc
        ifup --force $wlan
        sleep 2
        connmanctl connect wifi_dc345a1743d_6e6545675289d3567_managed_psk &>/dev/null
        sleep 10
        ping -c2 $gateway 2>&1 >/dev/null; rc=$?
        if [[ $rc -ne 0 ]] ; then
                echo "1" > /storage/.cache/nonet
        fi
fi
exit 0

 

Thursday, November 02, 2023

MULTIPLE SAMBA INSTANCES

 

In order to allow clients with different encryption levels access to the same network share, multiple instances of SAMBA must be configured on the same machine. We are benefiting from a feature of SAMBA called “bind_interface” that allow a certain instance to only run on a specific network interface. If only one interface is available, “Virtual interfaces” might be defined.


Optional step – Define virtual interfaces:

cd /etc/sysconfig/network-scripts

vi ifcfg-eth0:1

DEVICE=eth0:1

BOOTPROTO=static

IPADDR=192.168.127.1

NETMASK=255.255.0.0

NETWORK=192.168.0.0

BROADCAST=192.168.100.255

ONBOOT=yes

TYPE=Ethernet


vi ifcfg-eth0:2

DEVICE=eth0:2

BOOTPROTO=static

IPADDR=192.168.127.2

NETMASK=255.255.0.0

NETWORK=192.168.0.0

BROADCAST=192.168.100.255

ONBOOT=yes

TYPE=Ethernet


vi /etc/hosts

192.168.127.1 SMB1.domain.tld SMB1

192.168.127.2 SMB2.domain.tld SMB2



Step 1 – Prepare directories for instances:

mkdir -p /var/run/samba/SMB1 /var/run/samba/SMB2

mkdir -p /var/cache/samba/SMB1 /var/cache/samba/SMB2

mkdir -p /var/log/samba/SMB1 /var/log/samba/SMB2



Step 2 – Modify logrotate to care for the new log directories:

vi /etc/logrotate.d/samba

/var/log/samba/SMB*/log.* {

[…]

/bin/kill -HUP \`cat /var/run/samba/SMB1/smbd.pid /var/run/samba/SMB1/nmbd.pid /var/run/samba/SMB1/winbindd.pid 2> /dev/null\` 2> /dev/null || true

/bin/kill -HUP \`cat /var/run/samba/SMB2/smbd.pid /var/run/samba/SMB2/nmbd.pid /var/run/samba/SMB2/winbindd.pid 2> /dev/null\` 2> /dev/null || true

}


Step 3 – Create two configuration files:


vi /etc/samba/samba.conf.SMB1

[global]

workgroup = WORKGROUP

client min protocol = NT1

server min protocol = NT1

client ipc min protocol = NT1

client ipc signing = desired

client plaintext auth = yes

ntlm auth = ntlmv1-permitted

null passwords = yes

netbios name = SMB1

pid directory = /var/run/samba/SMB1

lock directory = /var/cache/samba/SMB1

private dir = /var/cache/samba/SMB1

server role = standalone

security = user

passdb backend = tdbsam

guest account = nobody

map to guest = Bad User

bind interfaces only = yes

interfaces = lo;eth0:1

log file = /var/log/samba/SMB1/log.%m

logging = file

log level = 2

load printers = no

printing = bsd

printcap name = /dev/null

disable spoolss = yes

[test]

Comment = Test Share

path = /tmp/test

browsable = yes

read only = no

guest ok = yes


vi /etc/samba/samba.conf.SMB2

[global]

workgroup = WORKGROUP

null passwords = yes

netbios name = SMB2

pid directory = /var/run/samba/SMB2

lock directory = /var/cache/samba/SMB2

private dir = /var/cache/samba/SMB2

server role = standalone

security = user

passdb backend = tdbsam

bind interfaces only = yes

interfaces = eth0:2

log file = /var/log/samba/SMB2/log.%m

logging = file

log level = 2

load printers = no

printing = bsd

printcap name = /dev/null

disable spoolss = yes

[test]

Comment = Test Share

path = /tmp/test

browsable = yes

read only = no

guest ok = yes


Step 4 – Edit/create sysconfig configuration files:


vi /etc/sysconfig/samba.SMB1

SMBDOPTIONS="-D -s /etc/samba/smb.conf.SMB1 -l /var/log/samba/SMB1"

NMBDOPTIONS="-D -s /etc/samba/smb.conf.SMB1 -l /var/log/samba/SMB1"


vi /etc/sysconfig/samba.SMB2

SMBDOPTIONS="-D -s /etc/samba/smb.conf.SMB2 -l /var/log/samba/SMB2"

NMBDOPTIONS="-D -s /etc/samba/smb.conf.SMB2 -l /var/log/samba/SMB2"


Step 4 – Edit/create systemctl startup files:


vi /usr/lib/systemd/system/smb1.service

[Unit]

Description=Samba SMB1 Daemon

Documentation=man:smbd(8) man:samba(7) man:smb.conf(5)

Wants=network-online.target

After=network.target network-online.target nmb1.service winbind.service

[Service]

Type=notify

PIDFile=/var/run/SMB1/smbd.pid

LimitNOFILE=16384

EnvironmentFile=-/etc/sysconfig/samba.SMB1

ExecStart=/usr/sbin/smbd --foreground --no-process-group $SMBDOPTIONS

ExecReload=/bin/kill -HUP $MAINPID

LimitCORE=infinity

Environment=KRB5CCNAME=FILE:/var/run/samba/SMB1/krb5cc_samba

[Install]

WantedBy=multi-user.target


vi /usr/lib/systemd/system/smb2.service

[Unit]

Description=Samba SMB2 Daemon

Documentation=man:smbd(8) man:samba(7) man:smb.conf(5)

Wants=network-online.target

After=network.target network-online.target nmb2.service winbind.service

[Service]

Type=notify

PIDFile=/var/run/SMB2/smbd.pid

LimitNOFILE=16384

EnvironmentFile=-/etc/sysconfig/samba.SMB2

ExecStart=/usr/sbin/smbd --foreground --no-process-group $SMBDOPTIONS

ExecReload=/bin/kill -HUP $MAINPID

LimitCORE=infinity

Environment=KRB5CCNAME=FILE:/var/run/samba/SMB2/krb5cc_samba

[Install]

WantedBy=multi-user.target


vi /usr/lib/systemd/system/nmb1.service

[Unit]

Description=Samba NMB1 Daemon

Documentation=man:nmbd(8) man:samba(7) man:smb.conf(5)

Wants=network-online.target

After=network.target network-online.target

[Service]

Type=notify

PIDFile=/var/run/SMB1/nmbd.pid

EnvironmentFile=-/etc/sysconfig/samba.SMB1

ExecStart=/usr/sbin/nmbd --foreground --no-process-group $NMBDOPTIONS

ExecReload=/bin/kill -HUP $MAINPID

LimitCORE=infinity

Environment=KRB5CCNAME=FILE:/var/run/samba/SMB1/krb5cc_samba

[Install]

WantedBy=multi-user.target


vi /usr/lib/systemd/system/nmb2.service

[Unit]

Description=Samba NMB2 Daemon

Documentation=man:nmbd(8) man:samba(7) man:smb.conf(5)

Wants=network-online.target

After=network.target network-online.target

[Service]

Type=notify

PIDFile=/var/run/SMB2/nmbd.pid

EnvironmentFile=-/etc/sysconfig/samba.SMB2

ExecStart=/usr/sbin/nmbd --foreground --no-process-group $NMBDOPTIONS

ExecReload=/bin/kill -HUP $MAINPID

LimitCORE=infinity

Environment=KRB5CCNAME=FILE:/var/run/samba/SMB2/krb5cc_samba

[Install]

WantedBy=multi-user.target


Step 5 – Create local users:


useradd -d /tmp/test test

smbpasswd -c /etc/samba/smb.conf.SMB1 -a test

smbpasswd -c /etc/samba/smb.conf.SMB2 -a test



Step 6 – Enable & Start the new services:


systemctl daemon-reload

systemctl enable nmb2

systemctl enable smb2

systemctl enable smb1

systemctl enable nmb1

systemctl start nmb1

systemctl start nmb2

systemctl start smb1

systemctl start smb2



Step 6 – Test the share:


Ideally from a different Linux machine,

mkdir /tmp/1

mount-t cifs //SMB1.domain.tld/test /tmp/1 -o username=test,password=p455w0rd,vers=1.0

umount /tmp/1

mount-t cifs //SMB2.domain.tld/test /tmp/1 -o username=test,password=p455w0rd,vers=2.0



Friday, June 24, 2022

EliteBook ambientlight sensor

Map keycode e033 (or any other key you choose) to the following command that toggles the sensor on or off:

echo $((1 - $(cat /sys/devices/platform/hp-wmi/als))) | sudo tee -a /sys/devices/platform/hp-wmi/als

Saturday, April 23, 2022

HiSilicon Hi3516Ev200 debrick

 HiSilicon Hi3516Ev200 camera gets bricked if tried to update the OpenIPC from the web interface running on :85, as the mtd block erase crashes the system during the process.

Download the latest build from github, unpack it and put it on the tftp directory.

wget https://github.com/OpenIPC/firmware/releases/download/latest/openipc.hi3516ev200-br.tgz | tar -zvx /tmp/tftboot

Set the local IP as 192.168.1.254

Start tftp server:   in.tftpd -L -vvvv -a 192.168.1.254:69 -s /tmp/tftpboot 

Connect the USBSerial adapter and configure minicom speed at 115200bps.


Connect power to the HiSilicon board and press CTRL+C

At the prompt, type:

setenv bootargs 'mem=${osmem:-32M} console=ttyAMA0,115200 panic=20 root=/dev/mtdblock3 rootfstype=squashfs init=/init mtdparts=hi_sfc:256k(boot),64k(env),2048k(kernel),5120k(rootfs),-(rootfs_data)'
setenv bootcmd 'setenv setargs setenv bootargs ${bootargs}; run setargs; sf probe 0; sf read 0x42000000 0x50000 0x200000; bootm 0x42000000'
setenv uk 'mw.b 0x42000000 ff 1000000; tftp 0x42000000 uImage.${soc} && sf probe 0; sf erase 0x50000 0x200000; sf write 0x42000000 0x50000 ${filesize}'
setenv ur 'mw.b 0x42000000 ff 1000000; tftp 0x42000000 rootfs.squashfs.${soc} && sf probe 0; sf erase 0x250000 0x500000; sf write 0x42000000 0x250000 ${filesize}'
setenv soc hi3516ev200
setenv osmem 32M
setenv totalmem 64M
setenv ipaddr 192.168.1.10
setenv serverip 192.168.1.254
saveenv
run uk; run ur; reset  
 
Enjoy!

Saturday, January 02, 2021

ESP OTA update - server side

 <?php

date_default_timezone_set('America/New_York');

header('Content-type: text/plain; charset=utf8', true);

 

$pattern = ".php";

$debuglog = "/var/log/ESP8266-ESPUpdate.log";

 

//update files must be named "LoadCell-$Version_number.bin"

foreach(glob('./bin/LoadCell*.{bin}', GLOB_BRACE) as $filename){

     $filenm = pathinfo($filename, PATHINFO_FILENAME);

     $arr = explode('-', $filenm);

     $upd_version  = $arr[ count($arr) -1 ];

     error_log("\n".'['.date('Y-M-d H:m:s').'] Filename: '.$filename.' Shortname: '.$filenm.' Version: '.$upd_version."\n", 3, $debuglog);

}

 

function check_header($name, $value = false) {

    if(!isset($_SERVER[$name])) {

        return false;

    }

    if($value && $_SERVER[$name] != $value) {

        return false;

    }

    return true;

}

 

function sendFile($path) {

    header($_SERVER["SERVER_PROTOCOL"].' 200 OK', true, 200);

    header('Content-Type: application/octet-stream', true);

    header('Content-Disposition: attachment; filename='.basename($path));

    header('Content-Length: '.filesize($path), true);

    header('x-MD5: '.md5_file($path), true);

    readfile($path);

}

 

if(!check_header('HTTP_USER_AGENT', 'ESP8266-http-Update'))

{

    header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);

    echo "only for ESP8266 updater! (UA)\n";

    error_log("\n".'['.date('YYYY-MM-dd HH:mm:ss').'] Not correct user_agent.\n\n', 3, $debuglog);

    exit();

}

 

if(

    !check_header('HTTP_X_ESP8266_STA_MAC') ||

    !check_header('HTTP_X_ESP8266_AP_MAC') ||

    !check_header('HTTP_X_ESP8266_FREE_SPACE') ||

    !check_header('HTTP_X_ESP8266_SKETCH_SIZE') ||

    !check_header('HTTP_X_ESP8266_SKETCH_MD5') ||

    !check_header('HTTP_X_ESP8266_CHIP_SIZE') ||

    !check_header('HTTP_X_ESP8266_SDK_VERSION')

) {

    header($_SERVER["SERVER_PROTOCOL"].' 403 Forbidden', true, 403);

    echo "only for ESP8266 updater! (header)\n";

    error_log("\n".'['.date('Y-M-d H:m:s').'] Not correct headers.\n\n', 3, $debuglog);

    exit();

}

 

//    foreach (getallheaders() as $name => $value) {

//    error_log("\n".'['.date('Y-M-d H:m:s').'] Header_name: '.$name.": \t".$value, 3, $debuglog);

//    }

 

if (($_SERVER['HTTP_X_ESP8266_VERSION']) < $upd_version && $_SERVER["HTTP_X_ESP8266_SKETCH_MD5"] != md5_file($filename)) {

    sendFile($filename);

    error_log("\n".'['.date('Y-M-d H:m:s').'] NEED UPDATE! ', 3, $debuglog);

    error_log("\n".'['.date('Y-M-d H:m:s').'] Ver on server: '.($upd_version).' Ver remote: '.($_SERVER['HTTP_X_ESP8266_VERSION']), 3, $debuglog);

    error_log("\n".'['.date('Y-M-d H:m:s').'] MD5 on server: '.(md5_file($filename)).' Value remote: '.($_SERVER['HTTP_X_ESP8266_SKETCH_MD5'])."\n", 3, $debuglog);

} else {

    error_log("\n".'['.date('Y-M-d H:m:s').'] NO NEED. Ver equal, small or same MD5', 3, $debuglog);

    error_log("\n".'['.date('Y-M-d H:m:s').'] Ver on server: '.($upd_version).' Ver remote: '.($_SERVER['HTTP_X_ESP8266_VERSION']), 3, $debuglog);

    error_log("\n".'['.date('Y-M-d H:m:s').'] MD5 on server: '.(md5_file($filename)).' Value remote: '.($_SERVER['HTTP_X_ESP8266_SKETCH_MD5'])."\n", 3, $debuglog);

}

 

?>

Wednesday, December 02, 2020

ESP WiFi sniffer with OLED and http upload

#include "ESP8266WiFi.h"
#include "oled.h"
ADC_MODE(ADC_VCC);
OLED Display=OLED(D1,D2);
int RawPort = A0;
char server[] = "192.168.1.101";
String uploadfile = "wifi.php";
String postVariable = "WiFi=";
const char* ssid = "MyWiFi";
const char* password = "P@55w0rd";
String total = "";
void setup() {
//  Serial.begin(115200);
//  Serial.println("");
  Display.begin();
  Display.setTTYMode(true);
  pinMode(LED_BUILTIN, OUTPUT);
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  Display.print("Battery: ");
  Display.print(ESP.getVcc());
//  Display.print("\n\rSetup done");
}
void loop() {
//  int Batt = ESP.getVcc();
//  Serial.print("Battery voltage is: "+Batt);
//  Display.print(ESP.getVcc());
//  Serial.print("Wifi scan...");
  Display.set_contrast(128);
  Display.print("\n\rScan...");
  int n = WiFi.scanNetworks();
//  Serial.println(" done");
  Display.println(" done");
  if (n == 0) {
//    Serial.println("No Networks Found");
    Display.printf("No Networks Found");
    digitalWrite(LED_BUILTIN, LOW);
  }
  else {
//    Serial.print(n);
//    Serial.println(" Networks found");
    digitalWrite(LED_BUILTIN, HIGH);
    Display.set_contrast(8);
    Display.printf("%d networks found",n);
    String nr = String(n) + " APs detected. ";
    for (int i = 0; i < n; ++i) {
//      Serial.print(i + 1);
//      Serial.print(": ");
//      Serial.print(WiFi.SSID(i));
//      Serial.print(" RSSI: ");
//      Serial.print(WiFi.RSSI(i)); 
//      Serial.print(" MAC: ");
//      Serial.print(WiFi.BSSIDstr(i));
//      Serial.print(" Enc: ");
//      Serial.println(encType(i));
    Display.println();
    Display.print(i + 1);
    Display.print(": ");
    Display.print(WiFi.SSID(i));
    Display.print(" (");
    Display.print(WiFi.RSSI(i));
    Display.println(")");
    Display.print("   ");
    Display.print(WiFi.BSSIDstr(i));
    total = total+String(i+1)+": "+String(WiFi.SSID(i))+" "+String(WiFi.BSSIDstr(i))+" "+String(WiFi.RSSI(i))+"db "+String(encType(i))+". ";
    delay(500);
    }
 
    WiFi.scanDelete();
    delay (500);
    Display.println("\n\rSleep for 1min...");
    
    WiFiClient client;
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
     delay(500);
    }
    
    
    String postData = postVariable + nr + total;
//    Serial.print("Transmitted data: ");
//    Serial.println(postData);
    
    if (client.connect(server, 80)) {
     client.print("POST /");
     client.print(uploadfile);
     client.println(" HTTP/1.1");
     client.print("Host: ");
     client.println (server);
     client.println("Content-Type: application/x-www-form-urlencoded");
     client.print("Content-Length: ");
     client.println(postData.length());
     client.println();
     client.print(postData);
    }
    if (client.connected()) {
      client.stop();
    }
//   Serial.println("Sleeping ");
   Display.set_power(false);
//   delay(10000);
   ESP.deepSleep(6e+7); // 60 sec  
  }
}
// Readable Encryption Type
String encType(int id){
String type;
  if(WiFi.encryptionType(id) == ENC_TYPE_WEP){ type=" WEP";
  }else if(WiFi.encryptionType(id) == ENC_TYPE_TKIP){ type="WPA-TKIP";    
  }else if(WiFi.encryptionType(id) == ENC_TYPE_CCMP){ type="WPA2-CCMP";    
  }else if(WiFi.encryptionType(id) == ENC_TYPE_AUTO){ type="WPA-WPA2";    
  }else if(WiFi.encryptionType(id) == ENC_TYPE_NONE){ type="OPEN";    
  }
  return type;
}




$cat wifi.php
<?php
$file = fopen("/var/www/html/wifi.txt", "a+") or die("Unable to open file!");
date_default_timezone_set("America/New_York");
$time = date('Y-m-d_H:i:s');
$read = $_POST["WiFi"];
$data = "{$time} - {$read}\n";
fwrite($file, $data);
fclose($file);
?>




Monday, November 02, 2020

Check if WiFi is still connected on rpi

 #!/bin/bash


gateway='192.168.0.1'

lockfile='/var/run/chk-wifi.pid'

wlan='wlan0'



if [ -e $lockfile ]; then

    echo `date +%F\ %T\ `$0": A lockfile exists... Lets check to see if it is still valid"

    pid=`cat $lockfile`

    if kill -0 &>1 > /dev/null $pid; then

     echo `date +%F\ %T\ `$0": Process still running, Lockfile valid."

     exit 1

    else

     echo `date +%F\ %T\ `$0": Invalid Lockfile, Removing."

     rm $lockfile

    fi

fi


#echo `date +%F\ %T\ `$0": Setting Lockfile"

echo $$ > $lockfile


#echo `date +%F\ %T\ `$0": Performing network check for $wlan"

ping -c2 $gateway 2>&1

rc=$?

if [[ $rc -eq 0 ]] ; then

        echo `date +%F\ %T\ `$0": The network is up."

else

        echo `date +%F\ %T\ `$0": Network down! Attempting reconnection."

        ifdown $wlan

#        echo `date +%F\ %T\ `$0": Cycling rpi3 onboard wifi driver"

        rmmod brcmfmac

        sleep 2

#        echo `date +%F\ %T\ `$0": Most probable cause in rpi1-2 is USB jamming, cycling the power on USB"

#        echo 0 > /sys/devices/platform/soc/20980000.usb/buspower

#        sleep 2

#        echo 1 > /sys/devices/platform/soc/20980000.usb/buspower

#        sleep 1

#        echo `date +%F\ %T\ `$0": Bringing back the WiFi"

        modprobe brcmfmac

        ifup --force $wlan

#        sleep 1

#        echo `date +%F\ %T\ `$0": New IP: $(ifconfig $wlan | grep 'inet addr')"

#        echo `date +%F\ %T\ `$0": "$(hostname -I)

fi


#echo `date +%F\ %T\ `$0": Remove lock & exit"

rm $lockfile

exit 0


Wednesday, April 08, 2020

DD-WRT on a Videotron reflashed DIR-825

The Videotron custom firmware does not allow local upgrade. On the firmware update page there is a nice "Firmware upgrade: Disabled" and that's where the update ends in the main interface.
In order to update, I've rebooted in  recovery mode browser by keeping the reset pressed white plugin the power. However, the upload process was always staying at 0% and didn't finished;
Then I've hexedited the factory-to-ddwrt_NA.bin and changed the last byte in the file from "0" to "2" - still no luck;
I've tried uploading directly from the shell: "ifconfig enp0s25 192.168.0.34 up && curl -0vF files=@factory-to-ddwrt_NA.bin http://192.168.0.1/cgi/index" - nope, still nothing;

The solution was deceivingly simple: I've put a switch between the D-Link and the computer - then the curl upload worked perfectly!

Thursday, February 13, 2020

Asterisk PAGE say time every hour

Digium D6x phones and CyberData SIP Speakers  are used to page.
The phones are also used as intercoms (bidirectional page).

To start, we need accounts for the phones/speakers added to sip.conf:



[phone1] ; Phone
type=friend
host=dynamic
context=my-context
secret=5678
mailbox=319

[speaker1]; Speaker
type=friend 
host=dynamic
context=my-context
secret=1234
mailbox=329
record_out=Adhoc
record_in=Adhoc
qualify=no


Then in extensions.conf, in the [my-context] context, add:

; Paging extensions
exten => 3319,1,GotoIf($[ ${CALLERID(number)} = 319 ]?skipself)
exten => 3319,1,SIPAddHeader(Alert-Info: info=<intercom>) ; Digium D6x require this to enable paging - search documentation for different phone models!
exten => 3319,n,Dial(SIP/phone1) ; this is the phone1 defined in sip.conf
exten => 3319,n(skipself),Noop(Not paging originator)

exten => 3329,1,GotoIf($[ ${CALLERID(number)} = 329 ]?skipself)
exten => 3329,n,Dial(SIP/speaker1,50) ; this is the speaker1 defined in sip.conf
exten => 3329,n(skipself),Noop(Not paging originator)

exten => 398,1,Page(LOCAL/3319@my-context&LOCAL/3329@my-context,di,120) ; Bidirectional PAGE - that's what the "d" does.
exten => 398,n,Hangup()

With this, we can dial 398 and the PAGE should work.

Now, in order to say the time automatically, we need a .call file, let's create /var/lib/asterisk/third-party/say-time.call

Channel: LOCAL/398@my-context
MaxRetries: 10
RetryTime: 5
WaitTime: 20
Context: page-say-time
Extension: 3310

Of course, we need to create the [page-say-time] context in extensions.conf:

[page-say-time]
exten => 3310,1,Answer()
exten => 3310,n,Wait(1)
exten => 3310,n,Playback(at-tone-time-exactly) ; this sound file is already in asterisk sounds
exten => 3310,n,Wait(1)
exten => 3310,n,SayUnixTime(,EST,IMp)
exten => 3310,n,Wait(1)
exten => 3310,n,Playback(beep) ; this sound file is already in asterisk sounds
exten => 3310,n,Wait(2)
exten => 3310,n,Hangup()

and the last step, create a crontab that copies the say-time.call to the astersk outgoing at every fix hour:

0  * *  *  * /bin/cp /var/lib/asterisk/third-party/say-time.call /var/spool/asterisk/outgoing/


Tuesday, June 04, 2019

Web Interface for Parental Control

This continues the Parental Control post from last month.

First of all, in order to protect the web page, we need an authentication method. A simple user/password will do for the moment (it's not perfect, you can bypass it by accessing directly the /cgi-bin/script.sh, but for the purpose of this exercise is OK-ish) .

Make sure that in the lighttpd.conf, mod_auth and mod_access are loaded,
server.modules += ( "mod_access" )
server.modules += ( "mod_auth" )

and the host section is protected

HTTP["url"] =~ "^/" {
auth.backend = "plain"
auth.backend.plain.userfile = "/jffs/lighttpd/.lighttpdpassword"
auth.require = ( "/" => (
"method" => "basic",
"realm" => "Password protected Parental Control",
"require" => "valid-user"
))}
(where /jffs/lighttpd/.lighttpdpassword contains the plaintext credentials, let's say parent:password)


The following index.html must be placed into the lighthttpd www root (/jffs/www/):

<html xmlns="http://www.w3.org/1999/xhtml">
 <head>
   <title>Parental Control</title>
     <form action="../cgi-bin/ai.sh" method="POST">
     <button name="name" value="value" style="background-color:lime;height:150px;width:400px"> Allow internet </button>
     </form><p><br>
     <form action="../cgi-bin/ag.sh" method="POST">
     <button name="name" value="value" style="background-color:yellowgreen;height:150px;width:400px">  Allow games  </button>
     </form><p><br>
     <form action="../cgi-bin/ay.sh" method="POST">
     <button name="name" value="value" style="background-color:khaki;height:150px;width:400px">  Allow only YouTube  </button>
     </form><p><br>
     <form action="../cgi-bin/ni.sh" method="POST">
     <button name="name" value="value" style="background-color:red;height:150px;width:400px"> No internet </button>
     </form><p><br>
     <form action="../cgi-bin/ng.sh" method="POST">
     <button name="name" value="value" style="background-color:lightcoral;height:150px;width:400px">  No games  </button>
     </form><p><br>
     <form action="../cgi-bin/lst.sh" method="POST">
     <button name="name" value="value" style="background-color:cyan;height:150px;width:400px">  Show actual  </button>
     </form>
 </head>
</html>

The following scripts will be placed into the ./cgi-bin folder:

ag.sh
#!/bin/sh
OUTPUT=$('/jffs/allow_game ; sleep 1; iptables -L FORWARD | grep DROP | grep -v "DROP       0    --  anywhere             anywhere" | if grep -q "DROP       0    --  192.168.1.128/28    anywhere"; then echo NO Internet; else echo Allow Internet; fi; if grep -qm1 "#" /tmp/yt-block.conf; then echo Allow YT; else echo NO YT; fi; if grep -qm1 "#" /tmp/games-block.conf; then echo Allow Games; else echo NO Games; fi' | awk 'BEGIN{print "<table>"} {print "<tr>";for(i=1;i<=NF;i++)print "<td>" $i"</td>";print "</tr>"} END{print "</table>"}')
echo "Content-type: text/html"
echo ""
echo "<html><head><title>Parental Control</title></head><body>"
echo "Rules are: $OUTPUT <br><p>"
echo "<form><input type='button' style='background-color:cyan;height:200px;width:400px' value='Back' onclick='history.back()'></form>"
echo "</body></html>"

ai.sh
#!/bin/sh
OUTPUT=$('/jffs/del_fw ;sleep 1; iptables -L FORWARD | grep DROP | grep -v "DROP       0    --  anywhere             anywhere" | if grep -q "DROP       0    --  192.168.1.128/28    anywhere"; then echo NO Internet; else echo Allow Internet; fi; if grep -qm1 "#" /tmp/yt-block.conf; then echo Allow YT; else echo NO YT; fi; if grep -qm1 "#" /tmp/games-block.conf; then echo Allow Games; else echo NO Games; fi' | awk 'BEGIN{print "<table>"} {print "<tr>";for(i=1;i<=NF;i++)print "<td>" $i"</td>";print "</tr>"} END{print "</table>"}')
echo "Content-type: text/html"
echo ""
echo "<html><head><title>Parental Control</title></head><body>"
echo "Rules are: $OUTPUT <br><p>"
echo "<form><input type='button' style='background-color:cyan;height:200px;width:400px' value='Back' onclick='history.back()'></form>"
echo "</body></html>"

ay.sh
#!/bin/sh
OUTPUT=$('/jffs/allow_yt ; sleep 1; iptables -L FORWARD | grep DROP | grep -v "DROP       0    --  anywhere             anywhere" | if grep -q "DROP       0    --  192.168.1.128/28    anywhere"; then echo NO Internet; else echo Allow Internet; fi; if grep -qm1 "#" /tmp/yt-block.conf; then echo Allow YT; else echo NO YT; fi; if grep -qm1 "#" /tmp/games-block.conf; then echo Allow Games; else echo NO Games; fi' | awk 'BEGIN{print "<table>"} {print "<tr>";for(i=1;i<=NF;i++)print "<td>" $i"</td>";print "</tr>"} END{print "</table>"}')
echo "Content-type: text/html"
echo ""
echo "<html><head><title>Parental Control</title></head><body>"
echo "Rules are: $OUTPUT <br><p>"
echo "<form><input type='button' style='background-color:cyan;height:200px;width:400px' value='Back' onclick='history.back()'></form>"
echo "</body></html>"

lst.sh
#!/bin/sh
OUTPUT=$('iptables -L FORWARD | grep DROP | grep -v "DROP       0    --  anywhere             anywhere" | if grep -q "DROP       0    --  192.168.1.128/28    anywhere"; then echo NO Internet; else echo Allow Internet; fi; if grep -qm1 "#" /tmp/yt-block.conf; then echo Allow YT; else echo NO YT; fi; if grep -qm1 "#" /tmp/games-block.conf; then echo Allow Games; else echo NO Games; fi;' | awk 'BEGIN{print "<table>"} {print "<tr>";for(i=1;i<=NF;i++)print "<td>" $i"</td>";print "</tr>"} END{print "</table>"}')
echo "Content-type: text/html"
echo ""
echo "<html><head><title>Parental Control</title></head><body>"
echo "Rules are: $OUTPUT <br><p>"
echo "<form><input type='button' style='background-color:cyan;height:200px;width:400px' value='Back' onclick='history.back()'></form>"
echo "</body></html>"

ng.sh
#!/bin/sh
OUTPUT=$('/jffs/disable_game && iptables -L FORWARD | grep DROP | grep -v "DROP       0    --  anywhere             anywhere" | if grep -q "DROP       0    --  192.168.1.128/28    anywhere"; then echo NO Internet; else echo Allow Internet; fi; if grep -qm1 "#" /tmp/yt-block.conf; then echo Allow YT; else echo NO YT; fi; if grep -qm1 "#" /tmp/games-block.conf; then echo Allow Games; else echo NO Games; fi' | awk 'BEGIN{print "<table>"} {print "<tr>";for(i=1;i<=NF;i++)print "<td>" $i"</td>";print "</tr>"} END{print "</table>"}')
echo "Content-type: text/html"
echo ""
echo "<html><head><title>Parental Control</title></head><body>"
echo "Rules are: $OUTPUT <br><p>"
echo "<form><input type='button' style='background-color:cyan;height:200px;width:400px' value='Back' onclick='history.back()'></form>"
echo "</body></html>"

ni.sh
#!/bin/sh
OUTPUT=$('/jffs/add_fw && iptables -L FORWARD | grep DROP | grep -v "DROP       0    --  anywhere             anywhere" | if grep -q "DROP       0    --  192.168.1.128/28    anywhere"; then echo NO Internet; else echo Allow Internet; fi; if grep -qm1 "#" /tmp/yt-block.conf; then echo Allow YT; else echo NO YT; fi; if grep -qm1 "#" /tmp/games-block.conf; then echo Allow Games; else echo NO Games; fi' | awk 'BEGIN{print "<table>"} {print "<tr>";for(i=1;i<=NF;i++)print "<td>" $i"</td>";print "</tr>"} END{print "</table>"}')
echo "Content-type: text/html"
echo ""
echo "<html><head><title>Parental Control</title></head><body>"
echo "Rules are: $OUTPUT <br><p>"
echo "<form><input type='button' style='background-color:cyan;height:200px;width:400px' value='Back' onclick='history.back()'></form>"
echo "</body></html>"

Now a very simple web page will allow you to control the kids internet from any browser: