Emular teclas de flecha arriba y flecha abajo del teclado con arduino

Objetivo:

Emular las teclas de flecha arriba y flecha abajo con arduino.

Requerimientos:

Arduino leonardo

Arduino IDE

Desarrollo:

Utilizaremos el ejemplo que ya viene en el IDE arduino Ejemplos>Digital>Button y a partir de éste vamos a añadir la librería de keyboard que también incluye el IDE Ejemplos>USB>Keyboard.
Las conexiones serán similares al siguiente diagrama, excepto que estaremos conectando dos push button, uno a la entrada digital 2 (UP) y 3(DOWN):

Imagen tomada de: https://content.instructables.com/ORIG/FKR/XEB3/IADH24QW/FKRXEB3IADH24QW.jpg?auto=webp&frame=1&width=1024&fit=bounds&md=75168dc948daf441ec064e08a54b12aa

El siguiente código es el usado para dicha funcionalidad:

/*
  Button

  Turns on and off a light emitting diode(LED) connected to digital pin 13,
  when pressing a pushbutton attached to pin 2.

  The circuit:
  - LED attached from pin 13 to ground through 220 ohm resistor
  - pushbutton attached to pin 2 from +5V
  - 10K resistor attached to pin 2 from ground

  - Note: on most Arduinos there is already an LED on the board
    attached to pin 13.

  created 2005
  by DojoDave <http://www.0j0.org>
  modified 30 Aug 2011
  by Tom Igoe

  This example code is in the public domain.

  https://www.arduino.cc/en/Tutorial/BuiltInExamples/Button
*/

#include "Keyboard.h"

// constants won't change. They're used here to set pin numbers:
const int buttonPinArriba = 2;     // the number of the pushbutton pin
const int buttonPinAbajo = 3;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPinArriba, INPUT);
}

void loop() {
  presionarPushButton(buttonPinArriba,KEY_UP_ARROW);
  presionarPushButton(buttonPinAbajo,KEY_DOWN_ARROW);
}

void presionarPushButton(int button, uint8_t KEY)
{
  // read the state of the pushbutton value:
  buttonState = digitalRead(button);
  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
    Keyboard.press(KEY);
    Keyboard.releaseAll();
    delay(250);
  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
  }
}

Fuente:

(1) https://www.instructables.com/How-to-use-a-Push-Button-Arduino-Tutorial/

(2) https://github.com/klenov/keyboardButton

(3) https://github.com/arduino-libraries/Keyboard/blob/master/src/Keyboard.h

Firebase app: CONFIGURATION_NOT_FOUND

A veces cuando usamos firebase para ejecutar nuestras apps es necesario modificar valores dentro de nuestra cuenta en firebase console, debido a que nos puede traer errores que no permitan la correcta ejecución de la aplicación, un ejemplo de ellos es el siguiente:

{
  "error": {
    "code": 400,
    "message": "CONFIGURATION_NOT_FOUND",
    "errors": [
      {
        "message": "CONFIGURATION_NOT_FOUND",
        "domain": "global",
        "reason": "invalid"
      }
    ]
  }
}

cuyo error puede salir cuando nuestra app hace una petición hacia la url de googleapis.

Para esto es necesario darle permisos de autenticación a nuestra base de datos de firebase, precisamente en la sección de autenticación:

En la imagen anterior he habilitado el acceso por correo y contraseña, así mismo si se requiere y no hay datos sensibles, se puede habilitar hasta abajo la opción de acceso anónimo.

Una vez guardados los cambios podremos ejecutar normalmente nuestra aplicación.

Como información adicional, habrá que revisar si las reglas de los permisos de la base de datos nos permiten acceder a ella, ya sea lectura y/o escritura.

Fuente:

(1) https://stackoverflow.com/a/65734030

(2) https://stackoverflow.com/questions/38574782/google-api-identify-toolkit-returning-configuration-not-found

Nextcloud, pihole, portainer, apache en raspberry pi 4 a través de docker

Alguien en raspberrypi.stackexchange.com(1) ha preguntado cómo tener todas pihole, nextcloud y apache en la raspberry, debido a que ha tenido problema con los puertos.

La solución que le he indicado es basándome en el artículo que yo ya había escrito antes(2) de cómo poner un proxy inverso con https y nextcloud.

Requerimientos:

  • Docker
  • Docker-compose

Se puede consultar directamente mi respuesta en el sitio(1).

Aunque aqui dejaré únicamente los comandos y contenido del archivo:

$ git clone https://github.com/SensorsIot/IOTstack.git IOTstack
$ cd IOTstack
$ touch docker-compose.yml

Y el contenido del archivo docker-compose.yml:

version: '3.6'
services:
  nextcloud:
    volumes:
    - ./volumes/nextcloud/html:/var/www/html

    image: nextcloud
    container_name: nextcloud
    ports:
    - "9321:80"
    restart: unless-stopped
    depends_on:
    - nextcloud_db
    links:
    - nextcloud_db
    networks:
    - iotstack_nw
    - nextcloud_internal
    environment:
    - MYSQL_HOST=nextcloud_db
    - MYSQL_PASSWORD=mySQL_password
    - MYSQL_DATABASE=nextcloud
    - MYSQL_USER=nextcloud

  nextcloud_db:
    environment:
    - MYSQL_ROOT_PASSWORD=root_password
    - MYSQL_PASSWORD=mySQL_password
    - MYSQL_DATABASE=nextcloud
    - MYSQL_USER=nextcloud

    image: linuxserver/mariadb
    container_name: nextcloud_db
    volumes:
    - ./volumes/nextcloud/db:/config
    restart: unless-stopped
    networks:
    - nextcloud_internal

  mariadb:
    environment:
    - MYSQL_ROOT_PASSWORD=root_password
    - MYSQL_PASSWORD=mySQL_password
    - MYSQL_DATABASE=nextcloud
    - MYSQL_USER=nextcloud
    image: linuxserver/mariadb
    container_name: mariadb
    volumes:
    - ./volumes/mariadb/config:/config
    ports:
    - "3306:3306"
    restart: unless-stopped
    networks:
    - iotstack_nw
  portainer-ce:
    container_name: portainer-ce
    image: portainer/portainer-ce
    restart: unless-stopped
    ports:
    - "8000:8000"
    - "9000:9000"
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ./volumes/portainer-ce/data:/data
  pihole:
    container_name: pihole
    image: pihole/pihole:latest
    restart: unless-stopped
    ports:
    - "5053:53/udp"
    - "5053:53/tcp"
    - "9322:80"
    - "8443:443"
    environment:
    - TZ:America/Chicago
    volumes:
    - ./etc-pihole/:/etc/pihole/
    - ./etc-dnsmasq.d/:/etc/dnsmasq.d/
    dns:
    - 127.0.0.1
    - 1.1.1.1
  apacheserver:
    container_name: apache
    image: httpd:2.4
    restart: unless-stopped
    ports:
    - "9320:80"
    - "9443:443"
    volumes:
    - ./volumes/apache/:/usr/local/apache2/htdocs

networks:
  iotstack_nw: # Exposed by your host.
    # external: true
    name: IOTstack_Net
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 10.77.60.0/24
        # - gateway: 10.77.60.1

  iotstack_nw_internal: # For interservice communication. No access to outside
    name: IOTstack_Net_Internal
    driver: bridge
    internal: true
    ipam:
      driver: default
      config:
      - subnet: 10.77.76.0/24
        # - gateway: 10.77.76.1 
  nextcloud_internal: # Network for NextCloud service
    name: IOTstack_NextCloud
    driver: bridge
    internal: true

  # default:
  #   external: true
  #   name: iotstack_nw

  # hosts_nw:
  #   driver: hosts

Ejecutamos docker-compose para levantar todos los contenedores:

 docker-compose -f docker-compose.yml up -d

Los servicios se pueden consultar desde:

Portainer
http://localhost:9000 

Apache. Se necesita crear un archivo index.html en ./volumes/apache/
http://localhost:9320 

Nextcloud. Crear credenciales de adminstrador.
http://localhost:9321 

pihole. puedes saber el password escribiendo en la terminal $ docker logs pihole  
http://localhost:9322/admin/ 

Fuente:

(1) https://raspberrypi.stackexchange.com/a/121659/128103

(2) proxy-inverso-con-https-nextcloud-y-apache-en-raspberry-pi-4

Pihole dns over https en raspberry

Introducción:

Se configurará pihole para que haga su función de dns over https, es decir, las peticiones dns viajan encriptadas.

Desarrollo:

Se creará un usuario para ejecutar cloudflared, así como se descargará el ejecutable.

$ sudo useradd -s /usr/sbin/nologin -r -M cloudflared
$ wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz

Se descomprime y copia el contenido hacia la carpeta de binarios:

$ tar -xzvf cloudflared-stable-linux-arm.tgz
$ sudo cp ./cloudflared /usr/local/bin
$ sudo chmod +x /usr/local/bin/cloudflared

Se cambian los permisos para ejecutar el binario:

$ sudo chown cloudflared:cloudflared /usr/local/bin/cloudflared

Verificar que el binario se ejecuta correctamente:

$ cloudflared -v
> cloudflared version 2021.2.2 (built 2021-02-10-1802 UTC)

Crearemos las carpetas de configuración de cloudflared:

$ mkdir /etc/cloudflared/
$ nano /etc/cloudflared/config.yml

En su contenido del archivo pegamos lo siguiente:

proxy-dns: true
proxy-dns-address: 0.0.0.0
proxy-dns-port: 5053
proxy-dns-upstream:
  - https://1.1.1.1/dns-query
  - https://1.0.0.1/dns-query
  - https://[2606:4700:4700::1111]/dns-query
  - https://[2606:4700:4700::1001]/dns-query

Ahora ejecutamos el binario

$ cloudflared

Y veremos una salida similar a lo siguiente:

2021-02-22T20:39:12Z INF Version 2021.2.2
2021-02-22T20:39:12Z INF GOOS: linux, GOVersion: go1.15.7, GoArch: arm
2021-02-22T20:39:12Z INF Settings: map[proxy-dns:true proxy-dns-address:0.0.0.0 proxy-dns-port:5053]
2021-02-22T20:39:12Z INF Adding DNS upstream url=https://1.1.1.1/dns-query
2021-02-22T20:39:12Z INF Adding DNS upstream url=https://1.0.0.1/dns-query
2021-02-22T20:39:12Z INF Adding DNS upstream url=https://[2606:4700:4700::1111]/dns-query
2021-02-22T20:39:12Z INF Adding DNS upstream url=https://[2606:4700:4700::1001]/dns-query
2021-02-22T20:39:12Z INF Starting DNS over HTTPS proxy server address=dns://0.0.0.0:5053
2021-02-22T20:39:12Z INF cloudflared will not automatically update when run from the shell. To enable auto-updates, run cloudflared as a service: https://developers.cloudflare.com/argo-tunnel/reference/service/

Veremos que se ha ejecutado correctamente con la configuración que hicimos pasos atrás.

Lo detenemos, ahora se hará el binario como demonio y se ejecute al iniciarse el sistema de la rpi al encenderse.

Cambiamos de directorio:

$ cd /etc/systemd/system

Creamos un archivo con la configuración del servicio:

$ sudo touch cloudflared.service

y pegamos lo siguiente:

[Unit]
Description=cloudflared DNS over HTTPS proxy
After=syslog.target network-online.target

[Service]
Type=simple
User=cloudflared
ExecStart=cloudflared
Restart=on-failure
RestartSec=10
KillMode=process

[Install]
WantedBy=multi-user.target

Ejecutamos lo siguiente para habilitarlo e iniciarlo:

$ sudo systemctl daemon-reload
$ sudo systemctl enable cloudflared
$ sudo systemctl start cloudflared

Y podremos verificar que el servicio se haya iniciado y ejecutado correctamente:

$ sudo systemctl status cloudflared

Tendremos una salida como la siguiente:

● cloudflared.service - cloudflared DNS over HTTPS proxy
   Loaded: loaded (/etc/systemd/system/cloudflared.service; enabled; vendor preset: enabled)
   Active: active (running) since Mon 2021-02-22 14:46:06 CST; 20min ago
 Main PID: 2047 (cloudflared)
    Tasks: 9 (limit: 3860)
   CGroup: /system.slice/cloudflared.service
           └─2047 /usr/local/bin/cloudflared

feb 22 14:46:06 raspberrypi systemd[1]: Started cloudflared DNS over HTTPS proxy.
feb 22 14:46:06 raspberrypi cloudflared[2047]: 2021-02-22T20:46:06Z INF Version 2021.2.2
feb 22 14:46:06 raspberrypi cloudflared[2047]: 2021-02-22T20:46:06Z INF GOOS: linux, GOVersion: go1.15.7, GoArch: arm
feb 22 14:46:06 raspberrypi cloudflared[2047]: 2021-02-22T20:46:06Z INF Settings: map[proxy-dns:true proxy-dns-address:0.0.0.0 proxy-dns-port:5053]
feb 22 14:46:06 raspberrypi cloudflared[2047]: 2021-02-22T20:46:06Z INF Adding DNS upstream url=https://1.1.1.1/dns-query
feb 22 14:46:06 raspberrypi cloudflared[2047]: 2021-02-22T20:46:06Z INF Adding DNS upstream url=https://1.0.0.1/dns-query
feb 22 14:46:06 raspberrypi cloudflared[2047]: 2021-02-22T20:46:06Z INF Adding DNS upstream url=https://[2606:4700:4700::1111]/dns-query
feb 22 14:46:06 raspberrypi cloudflared[2047]: 2021-02-22T20:46:06Z INF Adding DNS upstream url=https://[2606:4700:4700::1001]/dns-query
feb 22 14:46:06 raspberrypi cloudflared[2047]: 2021-02-22T20:46:06Z INF Starting DNS over HTTPS proxy server address=dns://0.0.0.0:5053
feb 22 14:46:06 raspberrypi cloudflared[2047]: 2021-02-22T20:46:06Z INF Autoupdate frequency is set autoupdateFreq=86400000

También verificaremos que la salida del siguiente comando tenga algo similar a lo plasmado:

pi@raspberrypi:~ $ dig @127.0.0.1 -p 5053 google.com

; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> @127.0.0.1 -p 5053 google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12157
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 22179adb227cd67b (echoed)
;; QUESTION SECTION:
;google.com.                    IN      A

;; ANSWER SECTION:
google.com.             191     IN      A       172.217.22.14

;; Query time: 0 msec
;; SERVER: 127.0.0.1#5053(127.0.0.1)
;; WHEN: Wed Dec 04 09:29:50 EET 2019
;; MSG SIZE  rcvd: 77

Ahora se tiene que configurar este puerto 5053 en el pihole para terminar dns over https:

Imagen tomada de (2)
Imágen tomada de (2)

Una vez que tenemos todo configurado como la imagen simplemente presionamos el botón de hasta abjo a la derecha guardar.

Si no se tiene instaldo pihole, se puede instalar con el siguiente comando:

docker run -d \
    --name pihole \
    -p 53:53/tcp -p 53:53/udp \
    -p 82:80 \
    -p 8443:443 \
    -e TZ="America/Chicago" \
    -v "${PWD}/etc-pihole/:/etc/pihole/" \
    -v "${PWD}/etc-dnsmasq.d/:/etc/dnsmasq.d/" \
    --dns=127.0.0.1 --dns=1.1.1.1 \
    --restart=unless-stopped \
    pihole/pihole:latest

Y la url para el panel de administrador de pihole es:

http://localhost:82/admin

Importante:

Si se tiene activado el firewal ufw, entonces es necesario agregar unas reglas para permitir el acceso a internet, apartir de esta configuración dns. Las reglas necesarias son:

$ sudo ufw allow 53
$ sudo ufw allow 5053

Fuente:

(1) https://nathancatania.com/posts/pihole-dns-doh/

(2) https://3os.org/guides/pihole_dns/

(3) https://ilayk.com/2021/02/12/pi-hole-docker-and-cloudflared-doh.html

Volvernos Certificate Authority para propósitos de desarrollo; para acceder a Bitwarden instalado en una raspberry a través de android

Introducción:

A veces tenemos la necesidad de trabajar bajo https localmente, por lo que necesitamos acceder desde otros dispositivos por este protocolo, para lo cual se necesita un certificado y una llave para configurar en un servidor web.

Me he visto en el dilema de que ya tenía mi servidor apache corriendo bajo https, pero al querer ingresar desde la aplicación móvil de bitwarden a dicho servidor he tenido un mensaje de error, así como desde el plugin del gestor de contraseñas en firefox.

Justamente lo que le sucede al usuario de la duda de este link(1):

Exception message: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.

Objetivo:

Poder acceder desde bitwarden en android. Para ello se creará un certificado que nos convertirá localmente como CA(Certificate Authority), instalándolo en el dispositivo android donde queremos dicha operación. Así mismo se crearán los certificados que se ingresarán como configuración de apache.

Desarrollo:

Se generará la clave y certificado para ser un certificado de autoridad.

$ openssl genrsa -des3 -out myCA.key 2048

Y tendremos una salida similar a lo siguiente:

Generating RSA private key, 2048 bit long modulus
.................................................................+++
.....................................+++
e is 65537 (0x10001)
Enter pass phrase for myCA.key:
Verifying - Enter pass phrase for myCA.key:

Donde tendremos que ingresar un passoword y la confirmación.

Generaremos el denominado “root certificate”

$ openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem

Y nos pedirá los siguientes datos, lo llenaremos como el ejemplo del link (2)

Enter pass phrase for myCA.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:CA
State or Province Name (full name) [Some-State]:Nova Scotia
Locality Name (eg, city) []:Truro
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Delicious Brains Inc
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:Delicious Brains
Email Address []:noreply@deliciousbrains.com

Se generarán dos archivos myCA.key (nuestra private key) y myCA.pem (nuestro root certificate).

Y listo, ya seremos una especie de CA.

Para poder ser utilizable necesitamos introducir este certificado myCA.pem en todos los dispositivos que queremos utilizar.

Instalando el certificado en un dispositivo Android

De acuerdo a la guía de (3),

Nos tenemos que asegurar que nuestro root certificate, root CA, esta en un archivo de formato PEM o DER y tiene una extensión .crt. Dado que nuestro archivo tiene una extensión .pem procederemos a copiarlo pero con la extensión que se pide, .crt.

$ cp myCA.pem myCA.crt 

El archivo myCA.crt es el que tenemos que pasar a un dispositivo android. Pero antes nos tenemos que verificar otra información:

Ejecutamos

$ openssl x509 -in certificate.crt -text -noout 

Para ver los detalles del certificado.

“Ensure the certificate is of version X.509 v3. The certificate details must show Version 3

Ahora si tenemos que pasarlo a un dispositivo móvil.

En la página(3) nos hacen hincapié de algunas cosas:

“To download the certificate file on the device, send it as an email attachment or host it on a secure website.

Note Do not install the server certificate by accessing the protected resource directly from your browser. This action imports the certificate only into the browser space and not into the device system truststore.

Una vez que se encuentra en el dispositivo android, tenemos que darle clic, nos abrirá un diálogo en el que tendremos que darle un nombre o alias y presionaremos ok o aceptar.

Posteriormente buscaremos que se haya añadido correctamente el certificado

Settings > Security > Trusted Credentials > User

O para dispositivos Xiaomi en el 2020-2021 es Configuración>Contraseñas y seguridad>Privacidad>Encriptación y credenciales>Credenciales de confianza>Usuario>Personal y ahí debe encontrarse el certificado al cual le pusimos un nombre/alias.

Crear certificado y llave para servidor web.

Ahora tendremos que crear estos certificados, para una explicación de este proceso mayor, dirigirse a (2), tomaré directamente el script que han creado desde ahí para hacer todo el proceso rápidamente, lo llamaremos como deseemos, yo lo llamaré script.sh e ingresaré todo lo siguiente:

#!/bin/sh

if [ "$#" -ne 1 ]
then
  echo "Usage: Must supply a domain"
  exit 1
fi

DOMAIN=$1

cd ~/certs

openssl genrsa -out $DOMAIN.key 2048
openssl req -new -key $DOMAIN.key -out $DOMAIN.csr

cat > $DOMAIN.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $DOMAIN
EOF

openssl x509 -req -in $DOMAIN.csr -CA ../myCA.pem -CAkey ../myCA.key -CAcreateserial \
-out $DOMAIN.crt -days 825 -sha256 -extfile $DOMAIN.ext

Ahora le daremos permisos de ejecución:

$ chmod +x script.sh

Y lo ejecutaremos pasandole el nombre de dominio que hayamos configurado en el dns:

$ ./script.sh casa.com

Este script nos generará 4 archivos:

casa.com.crt

casa.com.csr

casa.com.ext

casa.com.key

Sin olvidar que en nuestro httpd.conf dentro de nuestro host agregar el servername, así como los certificados y clave generados por el script:

<VirtualHost *:443>
.
.
.
ServerName casa.com
SSLCertificateFile /path/casa.com.crt
SSLCertificateKeyFile /path/casa.com.key
.
.
.
</VirtualHost>

Si no hemos configurado en el dns de nuestro servidor, entonces hacer lo siguiente:

$ vim /etc/hosts

Y agregar lo que muestro a continuación:

127.0.0.1  casa.com

De igual forma el dispositivo android tiene que estar apuntando hacia un dns que tenga al servidor como casa.com. Si por ejemplo la ip de nuestro servidor web es 192.168.0.2, entonces en el servidor dns debemos tener algo similar a:

192.168.0.2  casa.com

Así el dispositivo android sabrá a quien tiene que apuntar cuando ingresemos a casa.com, o cuando tratemos de ingresar a nuestro servidor de bitwarden local.

Entrando a la aplicación de bitwarden del dispositivo de android en URL del servidor ahora si pondremos el dominio que hemos configurado antes

https://casa.com/bitwarden/

o como sea que hayamos llamado a su path.

Daremos click en guardar y listo, ingresaremos nuestras credenciales de usuario.

Fuente:

(1) https://www.synoforum.com/threads/bitwarden-andorid-app-error-trust-anchor-for-certification-path-not-found.3085/

(2) https://deliciousbrains.com/ssl-certificate-authority-for-local-https-development/

(3)https://www.ibm.com/support/knowledgecenter/en/SSHS8R_7.1.0/com.ibm.worklight.installconfig.doc/admin/t_installing_root_CA_android.html

(4) https://manuals.gfi.com/en/kerio/connect/content/server-configuration/ssl-certificates/adding-trusted-root-certificates-to-the-server-1605.html