Search This Blog

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, 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: