Image

Image

Search This Blog

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


Thursday, October 22, 2020

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, January 28, 2020

Copy standard switch port groups from one esx host to another

The below code asks for lmvap-vcs60 credentials, connects to Vcenter, and copied aesx11 vSwitch2 portgroups over to a new host called aesx05 using vSwitch1. (or so said my buddy Josh O. who wrote it) 

$vccred = get-credential
connect-viserver -server lmvap-vcs60.domain.tld -credential $vccred
$dest = get-virtualswitch -name vSwitch1 -vmhost aesx05.domain.tld
$source = get-virtualportgroup -vmhost aesx11.domain.tld -virtualswitch vSwitch2 -standard
$countvar = $source.count
for ($a=0 ; $a -le $countvar-1 ; $a++)
{
$pgname = $source[$a].name
$vlan = $source[$a].VLANID
new-virtualportgroup -virtualswitch $dest -name $pgname -VLANID $vlan
}
disconnect-viserver -server lmvap-vcs60.domain.tld -confirm:$false



Wednesday, October 16, 2019

14

and going strong!

Wednesday, July 03, 2019

DD-WRT wireless extender

Setup -> Basic Setup -> WAN Connection Type -> Connection Type ->Disabled

Network Setup -> Router IP -> Local IP Address - choose an IP outside the DHCP Range from the main router
Gateway and Local DNS - usually the IP of the main router

Wireless -> Basic Settings -> First interface (2.4GHz) -> Wireless Mode: Client Bridge (Routed)
Default GW Mode: Manual
Gateway: IP of the main router
Wireless Security: same as on main router

Wireless -> Basic Settings -> Second interface (5GHz) -> Wireless Mode: AP
Set the WiFi network the way you want - You can duplicate the 5GHz config form the main router. this way the clients will do seamless roaming.

Services -> disable all
Security -> disable all
Access Restrictions -> disable all
NAT / QoS -> disable all

Administration -> Management
802.1x: Disable
Reset Button: Disable
Routing: Disable

Administration -> Keep Alive
Enable Watchdog: Enable
Interval (in seconds): 900
IP Addresses: Ip of the main router

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:

Friday, May 03, 2019

Parental control

Because you can't let the kids on YouTube 24/7 and some games are really addictive :)

The router must run OpenWRT or DD-WRT.

The kids devices must be assigned IP's from a certain range, let's say 192.168.1.128/28 by adding some lines similar to the following one into Additional Dnsmasq Options:
dhcp-host=set:red,AA:BB:CC:00:DD:22,kids-tv,192.168.1.130,43200m


A series of scripts must be put in /jffs/ and called by a cron job:

cat add_fw
#!/bin/sh
iptables -I FORWARD 1 -s 192.168.1.128/28 -j DROP
iptables -I FORWARD 2 -s 192.168.1.128/28 -m conntrack -j DROP --ctstate RELATED,ESTABLISHED

cat del_fw
#!/bin/sh
iptables -D FORWARD -s 192.168.1.128/28 -j DROP
iptables -D FORWARD -s 192.168.1.128/28 -m conntrack -j DROP --ctstate RELATED,ESTABLISHED

cat disable_game
#!/bin/sh
# DNS Rules
sed -e 's/^#//' -i /tmp/games-block.conf
sed -e 's/^#//' -i /tmp/yt-block.conf
restart_dns
# Force kids DNS to local
iptables -t nat -A PREROUTING -i br0 -s 192.168.1.128/28 -p udp --dport 53 -j DNAT --to 192.168.1.1
iptables -t nat -A PREROUTING -i br0 -s 192.168.1.128/28 -p tcp --dport 53 -j DNAT --to 192.168.1.1
# Block all ports over :500
iptables -I FORWARD 5 -p tcp --source 192.168.1.128/28 --dport 500:65535 -j DROP

cat allow_game
#!/bin/sh
# Remove DNS rules
sed 's/^\([^#]\)/#\1/g' -i /tmp/games-block.conf
sed 's/^\([^#]\)/#\1/g' -i /tmp/yt-block.conf
restart_dns
# Remove Force kids DNS to local
iptables -t nat -D PREROUTING -i br0 -s 192.168.1.128/28 -p udp --dport 53 -j DNAT --to 192.168.1.1
iptables -t nat -D PREROUTING -i br0 -s 192.168.1.128/28 -p tcp --dport 53 -j DNAT --to 192.168.1.1
# Unblock all ports over :500
iptables -D FORWARD -p tcp --source 192.168.1.128/28 --dport 500:65535 -j DROP


I do have an extra script that allow access to YouTube, without allowing games, this one is called only from a html page that I'll explain in a later post:

cat allow_yt
#!/bin/sh
sed 's/^\([^#]\)/#\1/g' -i /tmp/yt-block.conf
restart_dns


Those scripts are called by cron jobs that makes sure we don't have internet during the sleep hours and games & YouTube are permitted only during the weekend:
00 21 * * 0-4 root /jffs/add_fw
30 22 * * 5,6 root /jffs/add_fw
00 08 * * * root /jffs/del_fw
30 17 * * 5 root /jffs/allow_game
30 17 * * 0 root /jffs/disable_game


In order to block the DNS requests, the following Additional Dnsmasq Options needs to be added:
conf-file=/tmp/yt-block.conf
conf-file=/tmp/games-block.conf


The files /tmp/yt-block.conf and /tmp/games-block.conf are created by the startup script:
stopservice dnsmasq
echo "#address=/.roblox.com/192.168.1.1
#address=/.rbxcdn.com/192.168.1.1
#address=/.epicgames.com/192.168.1.1
#address=/.fortnitegame.com/192.168.1.1
#address=/.easyanticheat.com/192.168.1.1
#address=/.pixelgunserver.com/192.168.1.1
#address=/.applovin.com/192.168.1.1
#address=/.clashroyaleapp.com/192.168.1.1
#address=/.applifier.com/192.168.1.1
#address=/.chartboost.com/192.168.1.1
#address=/.fyber.com/192.168.1.1
#address=/.twitch.tv/192.168.1.1
#address=/.ttvnw.net/192.168.1.1
#address=/.leagueoflegends.com/192.168.1.1
#address=/.pvp.net/192.168.1.1
#address=/.riotgames.com/192.168.1.1
#address=/.garenanow.com/192.168.1.1
#address=/.ea.com/192.168.1.1
#address=/.respawn.com/192.168.1.1
#address=/.origin.com/192.168.1.1" > /tmp/games-block.conf
echo "#address=/.youtube.com/192.168.1.1
#address=/youtube.googleapis.com/192.168.1.1
#address=/youtubei.googleapis.com/192.168.1.1
#address=/.ytimg.com/192.168.1.1
#address=/ytimg.l.google.com/192.168.1.1
#address=/youtube.l.google.com/192.168.1.1
#address=/.googlevideo.com/192.168.1.1
#address=/.youtube-nocookie.com/192.168.1.1
#address=/.youtu.be/192.168.1.1" > /tmp/yt-block.conf
startservice dnsmasq


An "easy" way to run those scripts besides the scheduled cron jobs, is from the DD-WRT Administration -> Commands page:

Monday, April 01, 2019

VM Management

# powershell script for VM mass management. Requires a .csv file containing the list of VMs and a name for the snapshot/ If no snapshot name is given, "Snapshot_1" is used.

 #load powercli if needed
if (!(Get-Module -Name VMware.VimAutomation.Core) -and (Get-Module -ListAvailable -Name VMware.VimAutomation.Core)) {
    Write-Output "loading the VMware Core Module..."
    if (!(Import-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {
        # Error out if loading fails
        Write-Error "`nERROR: Cannot load the VMware Module. Is the PowerCLI installed?"
     }
    $Loaded = $True
    }
 #   elseif (!(Get-Module -Name VMware.VimAutomation.Core -ErrorAction SilentlyContinue) -and !(Get-Module -Name VMware.VimAutomation.Core) -and ($Loaded -ne $True)) {
 #       Write-Output "loading the VMware Core Snapin..."
 #    if (!(Add-PSSnapin -PassThru VMware.VimAutomation.Core -ErrorAction SilentlyContinue)) {
 #    # Error out if loading fails
 #    Write-Error "`nERROR: Cannot load the VMware Snapin or Module. Is the PowerCLI installed?"
 #    }
 #   }

# Define vmConfigSpec params
$vmConfigSpec = New-Object VMware.Vim.VirtualMachineConfigSpec
$vmConfigSpec.Tools = New-Object VMware.Vim.ToolsConfigInfo
$vmConfigSpec.Tools.ToolsUpgradePolicy = "UpgradeAtPowerCycle"

# Get the command-line params
 $command = $args[0]
 $list = $args[1]
 $server = $args[2]

# define default params
if (!$list) { $list = "vm_mgmt.csv"}
if (!$server) { $server = "default.vCenter.domain.tld"}

# Start processing the command
  switch ($command) {
    default { $myname = $MyInvocation.MyCommand.Definition
    echo "`nERROR! Usage:"
    echo "$myname command [list] [server] "
    echo "`ncommand is one of the following: viewsnap, takesnap, delsnap, revertsnap, hwupd, vmtoolsupd, vmoff, vmon."
    echo " list is a .csv file containing 'VM_Name,Snapshot_name'. If no list provided, 'vm_mgmt.csv' will be used."
    echo " server is the name of the server connecting to. If no server is provided, 'default.vCenter.domain.tld' will be used.`n"
    }
 
  "viewsnap" {
    ### View Snapshot
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nView Snaphots:`n"
      get-vm -Name $_.VM_Name | get-snapshot
  } }

  "takesnap" {   
    ### Take Snapshot
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nTaking Snapshots`n"
      get-vm -Name $_.VM_Name | New-Snapshot -Name $_.Snapshot_1 -Quiesce -Memory
  } }

  "delsnap" {   
    ### Delete Snapshot
    Connect-VIServer -Server $server -Protocol https
    import-csv $list | ForEach-Object {
    $_.VM_Name
    $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
   echo "`nDelete Snapshots`n"
    get-snapshot -name $_.Snapshot_1 -vm $_.VM_Name | remove-snapshot -confirm:$false
  } }

  "revertsnap" {
    ### Revert To Snapshot
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
    echo "`nReverting Snapshots. Confirmation is required for each restore.`n"
      set-vm -VM $_.VM_Name -Snapshot $_.Snapshot_1 -whatif
    # set-vm -VM $_.VM_Name -Snapshot $_.Snapshot_1 -confirm:$false
  } }

  "hwupd" { 
    # VM Hardware upgrade
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nVM Hardware upgrade to vmx-13`n"
      $do = New-Object -TypeName VMware.Vim.VirtualMachineConfigSpec
      $do.ScheduledHardwareUpgradeInfo = New-Object -TypeName VMware.Vim.ScheduledHardwareUpgradeInfo
      $do.ScheduledHardwareUpgradeInfo.UpgradePolicy = “always”
      $do.ScheduledHardwareUpgradeInfo.VersionKey = “vmx-13”
      $vm.ExtensionData.ReconfigVM_Task($do)
  } }

  "vmtoolsupd" {
    # VM Tools update
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nUpdating VM Tools`n"
      get-vm -Name $_.VM_Name | %{$_.Extensiondata.ReconfigVM($vmConfigSpec)}
  } }

  "vmoff" {
    # VM power off
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nTurning VMs OFF`n"
      $vm = Get-VM -Name $_.VM_Name | Shutdown-VMGuest -Confirm:$false
  } }

  "vmon" {
    # VM power on
      Connect-VIServer -Server $server -Protocol https
      import-csv $list | ForEach-Object {
      $_.VM_Name
      $_.Snapshot_name
      if (!$_.Snapshot_name) { $_.Snapshot_name = "Snaphot_1"}
    echo "`nTurning VMs ON`n"
      $vm = Get-VM -Name $_.VM_Name | Start-VM -Confirm:$false
  } }

}



-----------------------------------------------
type vm_mgmt.csv

VM_NAME,Snapshot_name
some-vm-name,Snapshot_342
another-vm-name,Snapshot_temp4

Saturday, February 02, 2019

Chromium - Cast: "No Devices Found"

Starting chromium from the console you get "Component extension with id pkedcjkdefgpdelpbcmbmeomcjbeemfm not in whitelist and is not being loaded as a result."

- pkedcjkdefgpdelpbcmbmeomcjbeemfm is the Chrome Media Router, without it, you can go to chrome://flags and Enable the #load-media-router-component-extension as much as you want, no chromecast device will ever be detected.

My solution: 

1: copy pkedcjkdefgpdelpbcmbmeomcjbeemfm folder from a google-chrome profile ( ~/.config/google-chrome/Default/Extensions/pkedcjkdefgpdelpbcmbmeomcjbeemfm) to the chromium profile ~/.config/chromium/Default/Extensions/pkedcjkdefgpdelpbcmbmeomcjbeemfm
( If you copy from a windows installation, make sure the files are chmod 600, the folders are 700 and you are the right owner)

2: in Chromium, go to chrome://extensions/, enable "Developer Mode", then "Load Unpacked" and point to ~/.config/chromium/Default/Extensions/pkedcjkdefgpdelpbcmbmeomcjbeemfm

3: Now Chrome Media Router is loaded and the chromecast devices will be detected:

Wednesday, January 16, 2019

drakboot "INTERNAL ERROR: unknown device"


1: obviously, run strace drakboot > /tmp/trace 2>&1

2: less /tmp/trace, look for the missing device (in my case it was sdd):
 openat(AT_FDCWD, "/boot/grub2/install.sh", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 12
ioctl(12, TCGETS, 0xbfb7147c)           = -1 ENOTTY (Inappropriate ioctl for device)
_llseek(12, 0, [0], SEEK_CUR)           = 0
fstat64(12, {st_mode=S_IFREG|0755, st_size=22, ...}) = 0
read(12, "grub2-install /dev/sdd", 8192) = 22
read(12, "", 8192)                      = 0

3: edit /boot/grub2/install.sh and replace the wrong disk reference.

Tuesday, January 08, 2019

Push-button ON/OFF

In order to start the Peltier-based car freezer and to make sure that it turn off and stays OFF after the car stopped (a big Peltier is a huge battery drain!), I've made this 4-relay based circuit. No or "as little as possible" electronics in the car is the best approach - only the aerospace is harder for electronics than automotive - the best solution might involve some relays and, maybe, a couple of diodes, but stay away from amateurish electronics in the car! This is the diagram I draw on the back of a napkin (as usual) :)


Monday, October 15, 2018

13

All good!

Thursday, May 10, 2018

RDP Disconnected! Error Code: 2308 Error Description: Socket closed

After a windows update, a couple of Windows 2016 Servers on AWS started rejecting the RDP connections.
mRemote was giving the error "RDP Disconnected! Error Code: 2308 Error Description: Socket closed". MS RDP is giving "This computer can't connect to the remote computer. Try connecting again. If the problem continues, contact the owner of the remote computer or your network administrator."

After a bit of tinkering, I found that the problem seems to be the RDP TLS and encryption level.

To solve it:

- remote connect Registry Editor to the affected server and change the DWORD 
HKLM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\SecurityLayer from "2" to "0" 


- remote connect Services.msc to the affected server and restart TermService

Saturday, December 02, 2017

Windows could not complete the installation. To install windows on this computer restart the installation

SHIFT-F10 to bring up command prompt.
cd c:\windows\system32\oobe
msoobe.exe
Make a generic account and password. 
Hit finish (if it requests a product key and you have one, enter it now.  if OEM/No key required, just finish). 
Set time/date. 
Finish.

Thursday, November 02, 2017

Extend LVM with a new disk

partprobe 
cat /proc/partitions - note the un-partitioned drive (ex: there is a /dev/xvdX but not /dev/xvdX1) 
cfdisk /dev/xvdX - create new partition, type 8e (LVM) 
pvcreate /dev/xvdX1 
vgdisplay  - note the VG name (in my case is "vg_bkp_vol_1")
vgextend vg_bkp_vol_1 /dev/xvdX1 
pvscan 
lvdisplay  - note the LV path (here "/dev/vg_bkp_vol_1/lv_bkp_vol_1")
lvextend /dev/vg_bkp_vol_1/lv_bkp_vol_1 /dev/xvdX1 
lvdisplay 
vgdisplay 
resize2fs /dev/vg_bkp_vol_1/lv_bkp_vol_1 
df 

Monday, October 16, 2017

12

Right on time!

Tuesday, September 05, 2017

Deploy .pfx cert embedded in script (a sort of 'cat << EOF' for windows)

@echo off
::
::  
:: In order to prepare the certificate please run
:: 'certutil -encode the_pfx_cert base_64_cert`
:: then paste the base_64_cert in the section below
:: Please note that the certificate password has to be given as start paramater to this script!
:: (eq: "cert-inst.bat S3cr3tPassw0rd")

:: If the cert was already installed, exit
REG QUERY HKCU\SOFTWARE\neXt /v CertInstalled
If %errorlevel%==0 goto :eof

:: define the temp name of the extracted cert
set extractedfile=%temp%\extract-%random%.txt

:: set the password needed to decode the cert
set certpasswd=%~1

:: separate the cert from this script
call:extractembedded embeddedfile %extractedfile%

:: process the extracted file
certutil -decode %extractedfile% %extractedfile%.pfx

certutil -f -user -p %certpasswd% -importpfx %extractedfile%.pfx

:: clean-up
::del %extractedfile% %extractedfile%.pfx

:: leave a trace in the registry, so the cert will not be installed again and again
REG ADD HKCU\SOFTWARE\neXt /v CertInstalled /t REG_DWORD /d 1

:: clean exit
exit /b

:: begin of the embed cert & extraction procedure
:: After the next line, please paste the "base_64_cert" created by certutil -encode
goto:embeddedfile
-----BEGIN CERTIFICATE-----
MIIMngIBAzCCDGQGCSqG
[...]
k05EzAQIFXJaGHOuxZcCAggA
-----END CERTIFICATE-----
:embeddedfile
:: before the previous line you can find the end of the "base_64_cert"

:: cert extraction procedure
:extractembedded
setlocal EnableDelayedExpansion
set embedbegin=goto:%~1
set embedend=:%~1
set embedcert=%~2
if exist %embedcert% del %embedcert%
set tmprndfile=%temp%\%random%.%random%
findstr /n ^^ "%~f0" > %tmprndfile%
call :seekembed < %tmprndfile%
del %tmprndfile%
exit /B
:seekembed
set oneline=:eof
set /P oneline=
if !oneline! == :eof goto nostart
set oneline=!oneline:*:=!
if not !oneline! == %embedbegin% goto seekembed
:getline
set oneline=:eof
set /P oneline=
if !oneline! == :eof goto nostop
set oneline=!oneline:*:=!
if !oneline! == %embedend% goto :eof
echo/!oneline!>> %embedcert%
goto getline
:nostart
echo Error finding start delimiter %embedbegin%
goto :eof
:nostop
echo Error finding stop delimiter %embedend%
goto :eof

Tuesday, August 01, 2017

Boot from grub2 rescue prompt

grub rescue> set prefix=(hd0,1)/boot/grub2
grub rescue> set root=(hd0,1)
grub rescue> insmod normal
grub rescue> normal
grub rescue> insmod linux
grub rescue> linux /boot/vmlinuz root=/dev/sda1
grub rescue> initrd /boot/initrd.img
grub rescue> boot

Friday, June 02, 2017

Phone extension that rings multiple external numbers (CCME Asterisk)

Skip to end of metadata
In this example we want to ring all the external numbers of a few people only by dialing extension 3331.
1: Connect to CCME and create a new dial-peer:
dial-peer voice 3331 voip
 description External Emergency Responders
 destination-pattern 3331$
 session protocol sipv2
 session target ipv4:192.168.0.XXX #(the Asterisk box)
 dtmf-relay rtp-nte cisco-rtp
 codec g711ulaw
 no vad
2: Connect to the asterisk server and add the extension in the default [incoming_context] in /etc/asterisk/extensions.conf: (192.168.0.YYY is the outgoing trunk)
exten => 3331,1,Dial(SIP/5145555555@192.168.0.YYY&SIP/51455555519@192.168.0.YYY&SIP/5145555552@192.168.0.YYY&SIP/5145555553@192.168.0.YYY&SIP/5145555554@192.168.0.YYY&SIP/5145555555@192.168.0.YYY)
exten => 3331,n,Hangup
3: Reload asterisk config and test the extension (smile)

Monday, May 01, 2017

Limit number of unix logins

cat .profile

#!/bin/sh
limit=3

session=`ps -ef | grep '\-sh' | grep $USER | grep -v grep`
number=`echo $session | wc -l`

if [ $number -ge $limit ]; then
echo "No more logins / Il n'y a plus de login. You are already logged as:
$session "

sleep 5
exit 0
fi




# to timeout after 15min of inactivity and forbid users to change the tmout:
echo "TMOUT=900
readonly TMOUT
export TMOUT" > /etc/profile.d/tmout.sh && chmox +x /etc/profile.d/tmout.sh

Monday, April 03, 2017

Forward all emails from one sendmail to another

- in sendmail.cf change Djdomain.tld to something like Dj_subdomain.domain.tld Do the same thing for DMdomain.tld
- in the same sendmail.cf look for Fw or Fw-o and check the file it refers to (usually /usr/lib/mail/local-host-names); in that file remove the line stating "domain.tld" (in fact, remove everything, leave just _subdomain.domain.tld there), that way sendmail will know that it is not the default destination for the @domain.tld

- if necessary, create /home/$username/.forward (chmod 600, chown $username:$group) and put the right info in it

Blog Archive