Adding some content
This commit is contained in:
parent
e7806f4fd5
commit
7212d02836
1
.control/remote-ssh-target
Normal file
1
.control/remote-ssh-target
Normal file
@ -0,0 +1 @@
|
||||
/var/www/htdocs/
|
7
.control/static-files
Normal file
7
.control/static-files
Normal file
@ -0,0 +1,7 @@
|
||||
src/assets
|
||||
src/distfiles
|
||||
src/favicon.*
|
||||
src/gpg.txt
|
||||
src/images
|
||||
src/paste
|
||||
src/smoke*
|
43
Makefile
43
Makefile
@ -1,25 +1,42 @@
|
||||
all: website fix-permissions
|
||||
all:
|
||||
make -s website
|
||||
|
||||
# Extensions:
|
||||
debug:
|
||||
make website
|
||||
|
||||
# Extensions in src/
|
||||
# th - template with html code
|
||||
# ph - page with html code
|
||||
# pm - page with markdown code
|
||||
# ps - page with shell code
|
||||
# pa - page with asciidoctor code
|
||||
# pt - page with plain text
|
||||
|
||||
PH_FILES != find src -type f -name "*.ph" | sed 's|src/||g'
|
||||
PM_FILES != find src -type f -name "*.pm" | sed 's|src/||g'
|
||||
PS_FILES != find src -type f -name "*.ps" | sed 's|src/||g'
|
||||
PA_FILES != find src -type f -name "*.pa" | sed 's|src/||g'
|
||||
PT_FILES != find src -type f -name "*.pt" | sed 's|src/||g'
|
||||
|
||||
STATIC_FILES = src/assets
|
||||
STATIC_FILES != cat .control/static-files
|
||||
REMOTE != cat .control/remote-ssh-target
|
||||
|
||||
$(PH_FILES):
|
||||
echo "Create: src/$@ => www/${@:S/ph/html/}"
|
||||
mkdir -p "$$(dirname www/${@})"
|
||||
cat src/header.th > www/${@:S/ph/html/}
|
||||
cat src/$@ >> www/${@:S/ph/html/}
|
||||
cat src/footer.th >> www/${@:S/ph/html/}
|
||||
|
||||
$(PT_FILES):
|
||||
echo "Create: src/$@ => www/${@:S/pt/html/}"
|
||||
mkdir -p "$$(dirname www/${@})"
|
||||
cat src/header.th > www/${@:S/pt/html/}
|
||||
echo "<pre>" >> www/${@:S/pt/html/}
|
||||
cat src/$@ >> www/${@:S/pt/html/}
|
||||
echo "</pre>" >> www/${@:S/pt/html/}
|
||||
cat src/footer.th >> www/${@:S/pt/html/}
|
||||
|
||||
$(PM_FILES):
|
||||
echo "Create: src/$@ => www/${@:S/pm/html/}"
|
||||
mkdir -p "$$(dirname www/${@})"
|
||||
@ -46,20 +63,26 @@ $(PA_FILES):
|
||||
-o - src/$@ >> www/${@:S/pa/html/}
|
||||
cat src/footer.th >> www/${@:S/pa/html/}
|
||||
|
||||
website: prepare copy-static-files $(PH_FILES) $(PM_FILES) $(PS_FILES) $(PA_FILES)
|
||||
website: prepare copy-static-files $(PH_FILES) $(PM_FILES) $(PS_FILES) $(PA_FILES) $(PT_FILES)
|
||||
|
||||
prepare:
|
||||
echo "Mkdir: www"
|
||||
mkdir -p www
|
||||
|
||||
copy-static-files: prepare
|
||||
rsync -r --partial --delete --out-format="Copy: src/%f => www/%f" $(STATIC_FILES) www/
|
||||
rsync -a --partial --delete --no-p --no-o --no-g --out-format="Copy: %f => www/" $(STATIC_FILES) www/
|
||||
|
||||
clean:
|
||||
make -s _clean
|
||||
_clean:
|
||||
echo "Delete: www"
|
||||
rm -rf www
|
||||
|
||||
fix-permissions: website
|
||||
chown -R sdk:www www
|
||||
chmod -R ug+Xrw www
|
||||
|
||||
|
||||
install:
|
||||
make -s _install
|
||||
_install: website
|
||||
echo "Fixing Permissions in www/"
|
||||
doas chown -R sdk:www www
|
||||
doas chmod -R ugo+Xrw www
|
||||
echo "Deploy: www/ => /var/www/htdocs/"
|
||||
cd www && doas rsync -a --partial --delete --exclude "*/cache/*" --out-format="Deploy: %f => /var/www/htdocs/%f" * $(REMOTE)
|
||||
|
@ -19,11 +19,13 @@ src/footer.th gets appended to every file.
|
||||
.pm files contain markdown source.
|
||||
.ph files contain plain html.
|
||||
.ps files contain ksh shell script (the scripts must output html to stdout).
|
||||
.pt files contain plain text.
|
||||
|
||||
Everything in src/assets is copied as is.
|
||||
Everything in `.control/static-files` is copied as is.
|
||||
|
||||
Execute `make` to create the website with debug output.
|
||||
Execute `make -s` to hide the debug output.
|
||||
Execute `make debug` to create the website with debug output.
|
||||
Execute `make` to hide the debug output.
|
||||
Execute `make install` to copy the page to the remote in `.control/remote-ssh-target`.
|
||||
|
||||
The generated website will be in the directory `www`.
|
||||
|
||||
|
BIN
src/assets/bungee.ttf
Normal file
BIN
src/assets/bungee.ttf
Normal file
Binary file not shown.
1540
src/assets/style.css
1540
src/assets/style.css
File diff suppressed because it is too large
Load Diff
@ -1,2 +1,5 @@
|
||||
</article>
|
||||
<div style="text-align:left">-- <br>Proudly made with vim.<br></div></html>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -1,6 +1,21 @@
|
||||
<html>
|
||||
<html lang="en,de">
|
||||
<head>
|
||||
<title>My Homepage</title>
|
||||
<link rel="stylesheet" href="https://classless.de/classless.css">
|
||||
<title>CODEVOID</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="generator" content="selfmade">
|
||||
<link rel="stylesheet" href="/assets/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<div class="header-title">
|
||||
<a href="/">codevoid</a>
|
||||
</div>
|
||||
</header>
|
||||
<div class="header-row">
|
||||
<a class="header-item" href="/distfiles">Distfiles</a>
|
||||
<a class="header-item" href="/paste">Pastebin</a>
|
||||
<a class="header-item" href="/smoke">Smokeping</a>
|
||||
</div>
|
||||
<div class="header-line"></div>
|
||||
<article>
|
||||
|
||||
|
18
src/index.ps
18
src/index.ps
@ -1,18 +1,22 @@
|
||||
#!/bin/ksh
|
||||
|
||||
echo "<h1>CODEVOID</h1>
|
||||
echo "<h1>Welcome!</h1>"
|
||||
|
||||
<h2>Posts</h2>
|
||||
echo "
|
||||
<p>Welcome to my little place on the web. It may not been the pretties you've seen today, but it's all self made.</p>
|
||||
|
||||
<ol>"
|
||||
"
|
||||
|
||||
echo "<h2>Posts</h2>"
|
||||
|
||||
echo "<ol>"
|
||||
cd src/posts
|
||||
ls -1 | while read line
|
||||
ls -r1 | while read line
|
||||
do
|
||||
echo "<li><a href=\"posts/${line%%.*}.html\">${line%%.*}</a></li>"
|
||||
T="$(echo "${line%%.*}" | tr '_' ' ')"
|
||||
L="posts/${line%%.*}.html"
|
||||
echo "<li><a href=\"$L\">$T</a></li>"
|
||||
done
|
||||
|
||||
|
||||
echo "</ol>"
|
||||
|
||||
|
||||
|
92
src/posts/2019-04-27_Manage_dotfiles_with_git.pm
Normal file
92
src/posts/2019-04-27_Manage_dotfiles_with_git.pm
Normal file
@ -0,0 +1,92 @@
|
||||
# Manage Dotfiles With Git
|
||||
|
||||
I'm managing my dotfiles with git. My method serves me well for a few
|
||||
years already and so I think it's time to write it down.
|
||||
|
||||
If you think git, you might think of a dotfile repository and dozens of
|
||||
symlinks into the home directory. This is precisely what kept me from
|
||||
using git until I discovered bare repositories.
|
||||
|
||||
Create your dotfile repository with the `--bare` parameter
|
||||
|
||||
```
|
||||
git init --bare $HOME/.cfg
|
||||
```
|
||||
|
||||
This creates only a folder for git control files, which normally reside
|
||||
inside the .git folder within the repository.
|
||||
|
||||
You can now tell git to use $HOME as your work-tree directory. This
|
||||
makes git handle your home directory like all the files would be within
|
||||
the git repository. Now you can:
|
||||
|
||||
```
|
||||
git --git-dir=$HOME/.cfg/ --work-tree=$HOME add .vimrc
|
||||
git --git-dir=$HOME/.cfg/ --work-tree=$HOME commit -m "my .vimrc"
|
||||
```
|
||||
|
||||
If course it is silly to type out such a long command every time you
|
||||
want to interract with your dotfiles. So why not create an alias?
|
||||
|
||||
```
|
||||
alias config='git --git-dir=$HOME/.cfg/ --work-tree=$HOME'
|
||||
```
|
||||
|
||||
Put this in your .bashrc or .kshrc and you can now use the command
|
||||
"config" in the same way you usually use git.
|
||||
|
||||
```
|
||||
config add .vimrc
|
||||
config commit -m "my vimrc"
|
||||
```
|
||||
|
||||
Maybe you were brave and typed config status already. This will list
|
||||
the content of your whole home directory as "untracked files". This is
|
||||
not what we want. We can run git config and tell it to stop doing
|
||||
this. But of course we must run our git, which is called `config`.
|
||||
|
||||
```
|
||||
config config --local status.showUntrackedFiles no
|
||||
```
|
||||
|
||||
Now git status will only check what's being tracked. So if you add your
|
||||
vimrc file and later change it, "config status" will show it, "config
|
||||
diff" will diff it...
|
||||
|
||||
You can now use the power of git with your new "config" command.
|
||||
|
||||
Well okay, and because I'm lazy and don't want to think about git commit
|
||||
messages, I'm using this to push my changes:
|
||||
|
||||
```
|
||||
dotfiles_autoupdate() {
|
||||
config add -u && \
|
||||
config commit -m "Update $(date +"%Y-%m-%d %H:%M") \
|
||||
$(uname -s)/$(uname -m)-$(hostname -s)" && config push
|
||||
}
|
||||
```
|
||||
|
||||
This command takes all changed files and commits them with the date and
|
||||
some machine information. Not creative, but I don't care. YMMV.
|
||||
|
||||
Setting up the dotfiles on a new system can also be automated with this
|
||||
function:
|
||||
|
||||
```
|
||||
dotfiles_init() {
|
||||
git --no-replace-objects clone --bare --depth 1 \
|
||||
sdk@git.server.de:dotfiles.git $HOME/.cfg;
|
||||
config config --local status.showUntrackedFiles no;
|
||||
config checkout -f
|
||||
}
|
||||
```
|
||||
|
||||
There you have it. Now you can use the full power of git directly in your home
|
||||
directory by using the new "config" command instead of git. You can "config
|
||||
status/add/rm/branch/rebase/pull/push" as you wish and there's no additional logic
|
||||
necessary (like symlinks to watch out for).
|
||||
|
||||
I'm maintaining a "work branch" on top of my "main" (private) branch.
|
||||
This work branch even has a different upstream (corporate git repository
|
||||
at work). But I'm still able to access changes I made to my private git
|
||||
repository and merge them as I like (or vise versa).
|
81
src/posts/2019-05-19_No_plaintext_passwords.pm
Normal file
81
src/posts/2019-05-19_No_plaintext_passwords.pm
Normal file
@ -0,0 +1,81 @@
|
||||
# No plaintext passwords, please!
|
||||
|
||||
Try to keep your passwords out of your dotfiles. In many
|
||||
cases, this can be done with gpg (or a command line based [password manager](https://www.passwordstore.org)).
|
||||
|
||||
Here are some examples:
|
||||
|
||||
## MSMTP
|
||||
|
||||
In the `.msmtprc` you can use `passwordeval` instead of `password` and make
|
||||
it retrieve the password using a command.
|
||||
|
||||
```
|
||||
passwordeval "gpg -d $HOME/.msmtp-pw.gpg"
|
||||
```
|
||||
|
||||
## OfflineIMAP
|
||||
|
||||
Offlineimap supports to retrieve the password using a python program
|
||||
that implements a "get_pass" function. We can use this by writing a
|
||||
little python script that calls gpg or the password manager.
|
||||
|
||||
In the `.offlineimaprc` set the python file and remotepasseval. The
|
||||
get_pass function takes 3 arguments, which are used to select the
|
||||
correct password from the file.
|
||||
|
||||
```
|
||||
pythonfile=~/.offlineimap.py
|
||||
remotepasseval=get_pass("mail","user","993")
|
||||
```
|
||||
|
||||
Create a file `~/.offlineimap.py` with the following content:
|
||||
|
||||
```
|
||||
#!/usr/bin/python3
|
||||
import re, os
|
||||
def get_pass(machine, login, port):
|
||||
s = 'machine %s login %s port %s password ([^ ]*)\n' % (machine, login, port)
|
||||
p = re.compile(s)
|
||||
authinfo = os.popen("gpg -d /home/sdk/.offlineimap-pw.gpg").read()
|
||||
return p.search(authinfo).group(1)
|
||||
```
|
||||
|
||||
The password file needs to contain entries like below. More than one
|
||||
entry is supported. So if you have more than one account configured, you
|
||||
can call `get_pass(...)` multiple times and select different passwords
|
||||
for each account.
|
||||
|
||||
```
|
||||
machine mail login sdk port 993 password securepassword
|
||||
```
|
||||
|
||||
## Mutt
|
||||
|
||||
In `~/.muttrc`, we can use the `source` command to read configuration entries.
|
||||
|
||||
```
|
||||
source "gpg -d $HOME/.mutt-pw.gpg |"
|
||||
```
|
||||
|
||||
The password file needs to contain valid mutt configuration options:
|
||||
|
||||
```
|
||||
set imap_pass=supersecurepassword
|
||||
set imap_user=sdk
|
||||
```
|
||||
|
||||
## Vim can help...
|
||||
|
||||
Vim does not need a password, but it can help with those gpg files.
|
||||
Instead of decrypting/changing/encrypting these password files, you can
|
||||
use the [vim-gpg plugin](https://github.com/jamessan/vim-gnupg), which does
|
||||
that for you. Once it's installed, you can edit `.gpg` files directly and it
|
||||
takes over the cumbersome de/encryption.
|
||||
|
||||
## password-store
|
||||
|
||||
I'm using password-store for the task instead of gpg. This works by replacing
|
||||
all the "gpg -d $file" commands with the corresponding "pass $folder/$account"
|
||||
command. It works the same way, but password-store takes care of editing the
|
||||
files and also versions and syncs them across devices (using git).
|
34
src/posts/2019-10-17-LineageOS-on-Motorola-Z2-Force.pm
Normal file
34
src/posts/2019-10-17-LineageOS-on-Motorola-Z2-Force.pm
Normal file
@ -0,0 +1,34 @@
|
||||
# LineageOS on Motorola Z2 Force
|
||||
|
||||
Whenever there is a major LineageOS Update, chances are that I forgot
|
||||
the flashing process. So here are the notes.
|
||||
|
||||
Disclaimer: Due to the missing tools to flash from OpenBSD, I use my
|
||||
work computer, which runs windows.
|
||||
|
||||
Required Downloads:
|
||||
* [Android Platform Tools](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) (contains adb and fastboot)
|
||||
* [Motorola Smart Assistant](https://support.lenovo.com/us/en/downloads/ds101291) (contains USB drivers for fastboot)
|
||||
|
||||
Prepare:
|
||||
- Install motorola smart assistant
|
||||
- Extract platform-tools make sure you're in the platform tools
|
||||
directory or that they are in your $PATH.
|
||||
|
||||
Update steps:
|
||||
- p[hone]: Boot into bootloader (power+down)
|
||||
- c[omputer]: fastboot flash boot_a \<lineageos_recovery\>.img
|
||||
- c: fastboot flash boot_b \<lineageos_recovery\>.img
|
||||
- p: Boot into bootloader (power+down) -\> Boot Recovery
|
||||
- p: Factory Reset -\> Wipe data / factory reset + Wipe System
|
||||
- p: Apply update -\> adb sideload
|
||||
- c: adb sideload \<lineageos\>.zip
|
||||
- c: adb sideload \<addons\>.zip
|
||||
- p: Reboot
|
||||
|
||||
Notes:
|
||||
* "adb devices" works without USB drivers
|
||||
* "fastboot devices" shows nothing if USB drivers are not installed
|
||||
* This phone has two boot areas and therefore "fastboot flash boot" will
|
||||
fail. The areas "boot_a" and "boot_b" must be used instead. If "boot_a"
|
||||
and "boot_b" are flashed differently, booting will fail.
|
42
src/posts/2019-10-24_Building_an_OpenBSD_Kernel.pm
Normal file
42
src/posts/2019-10-24_Building_an_OpenBSD_Kernel.pm
Normal file
@ -0,0 +1,42 @@
|
||||
# Building an OpenBSD Kernel
|
||||
|
||||
I'm running OpenBSD-current for a while in order to support my port.
|
||||
It's currently only one port, but that's a start, right?
|
||||
|
||||
Anyway... every once in a while I stumble over a patch on the OpenBSD
|
||||
Mailinglist I want to try and this requires me to apply the patch and
|
||||
build the custom kernel with it. But how?
|
||||
|
||||
Well, the documentation is [where you would expect it](https://www.openbsd.org/faq/faq5.html#Custom).
|
||||
|
||||
Download the kernel source
|
||||
```
|
||||
cd /usr
|
||||
cvs -qd anoncvs@anoncvs.ca.openbsd.org:/cvs checkout -P src
|
||||
```
|
||||
|
||||
Update the kernel source
|
||||
```
|
||||
cd /usr/src
|
||||
cvs -q up -Pd
|
||||
```
|
||||
|
||||
Configure Kernel
|
||||
```
|
||||
cd /usr/src/sys/arch/amd64/conf
|
||||
cp GENERIC.MP MYKERNEL
|
||||
config MYKERNEL
|
||||
```
|
||||
|
||||
Build and install kernel (amd64)
|
||||
```
|
||||
cd /sys/arch/amd64/compile/MYKERNEL
|
||||
make clean
|
||||
make
|
||||
make install # the old kernel is /obsd now
|
||||
```
|
||||
|
||||
That's it. Reboot.
|
||||
|
||||
This is ONLY the kernel. If you need to build the whole system, please
|
||||
consult the OpenBSD documentation (hint: release(8)).
|
41
src/posts/2020-05-17_browser-dark-mode.pm
Normal file
41
src/posts/2020-05-17_browser-dark-mode.pm
Normal file
@ -0,0 +1,41 @@
|
||||
# Browser Dark Mode (Chrome and Firefox)
|
||||
|
||||
Dark Mode luckily has become a thing also in the non-unix world.
|
||||
Finally browser can be used with dark interfaces and websites can have
|
||||
alternative color schemes.
|
||||
|
||||
However, in other operating systems, there is a global toggle for dark
|
||||
mode, which also switches the browser into it. This is not the case on
|
||||
linux and unix systems.
|
||||
|
||||
# Chrome / Chromium / Iridium
|
||||
|
||||
Chrome and Chromium starting with version 73 can be tought to start in
|
||||
dark mode:
|
||||
|
||||
```
|
||||
chrome --enable-features=WebUIDarkMode --force-dark-mode
|
||||
```
|
||||
|
||||
Then go to "chrome://settings/?search=themes" and switch the theme to
|
||||
"Classic".
|
||||
|
||||
# Firefox
|
||||
|
||||
Firefox got the dark mode in release 70.
|
||||
|
||||
0. Go to "about:config"
|
||||
1. Enter "ui.systemUsesDarkTheme" into the search bar
|
||||
2. Click "Number" and then "+"
|
||||
3. Enter "1" and click the check mark
|
||||
|
||||
Right click on a free spot in the icon bar and select "customize". At
|
||||
the bottom left of the screen, you can switch to a dark theme.
|
||||
|
||||
Note: If you've set privacy.resistFingerprinting to "true" the CSS dark
|
||||
mode switching won't work. Kudus to @andinus@tilde.zone for figuring
|
||||
this out.
|
||||
|
||||
There you go, both browsers are in dark mode now. The UI should be dark
|
||||
and also websites that support the "@media (prefers-color-scheme: dark)"
|
||||
directive should make use of it.
|
38
src/posts/2020-07-12_OpenBSD_Desktop_GPU.pm
Normal file
38
src/posts/2020-07-12_OpenBSD_Desktop_GPU.pm
Normal file
@ -0,0 +1,38 @@
|
||||
# OpenBSD Desktop GPU recommendation
|
||||
|
||||
OpenBSD has decent intel GPU support. So finding a laptop that works
|
||||
great is not really difficult. The story is different when you look at
|
||||
desktops. I've tested several graphic cards and there are winners.
|
||||
|
||||
## Radeon R9 390X (radeon)
|
||||
|
||||
This card is driven by the HAWAII XT chipset, which is covered by the
|
||||
radeon drivers HAWAII support. It's the latest and fastest device
|
||||
supported by this driver.
|
||||
|
||||
## Radeon HD 7790 (radeon)
|
||||
|
||||
This card is driven by the BONAIRE chipset, which is the predecessor to
|
||||
HAWAII. This card is still listed as high end card, but draws a lot less
|
||||
power than the R9. Both are fine for gaming.
|
||||
|
||||
Both cards support resolutions up to 4K. However only via display port.
|
||||
The R9 delivers 4K@30Hz via HDMI.
|
||||
|
||||
Newer AMD GPUs are supported by the amdgpu driver, which is not as
|
||||
stable as the old radeon driver.
|
||||
|
||||
## Radeon RX 450 (amdgpu)
|
||||
|
||||
My setup is HDMI based, and I had to use an active adapter from DP to
|
||||
HDMI to get to a 60Hz 4k signal. This HDMI signal is then going into
|
||||
my KVM switch and from there to the screen. With this many hops,
|
||||
I experienced some sort of jitter every once in a while.
|
||||
|
||||
There was significant progress in the amdgpu development in the last
|
||||
months, so I gave it a shot again. I'm now using an RX 450 card with
|
||||
the Polaris 12 chipset. It runs stable for me. So maybe amdgpu is
|
||||
ready for prime time? At least with this chipset I'm very pleased with
|
||||
its performance. The HDMI 4k signal is stable.
|
||||
|
||||
_Note (2023): amdgpu(4) has come a long way since I have tested these cards..._
|
33
src/posts/2020-11-14_OpenBSD_Disk_Encryption.pm
Normal file
33
src/posts/2020-11-14_OpenBSD_Disk_Encryption.pm
Normal file
@ -0,0 +1,33 @@
|
||||
# OpenBSD Full Disk Encryption Setup
|
||||
|
||||
_This post is outdated. FDE is integrated into the installer since OpenBSD 7.3_
|
||||
|
||||
This is a condensed version of OpenBSD FDE encryption FAQ.
|
||||
|
||||
Boot installer, drop to shell with "s"
|
||||
|
||||
```
|
||||
cd /dev && sh MAKEDEV sd0
|
||||
dd if=/dev/urandom of=/dev/rsd0c bs=1m
|
||||
fdisk -iy -g -b 960 sd0 # GPT / without -g and -b for MBR
|
||||
disklabel -E sd0
|
||||
```
|
||||
|
||||
Note, switch to kbd en before setting the password as this is
|
||||
what you have on the boot prompt.
|
||||
|
||||
```
|
||||
bioctl -c C -l sd0a softraid0
|
||||
dd if=/dev/zero of=/dev/rsd1c bs=1m count=1
|
||||
```
|
||||
|
||||
Ctrl+D to restart the installer. Choose sd1 as install target.
|
||||
|
||||
If sd1 is not present:
|
||||
|
||||
```
|
||||
cd /dev && sh MAKEDEV sd1
|
||||
```
|
||||
|
||||
When the installer later asks about installing with MBR or GPT layout,
|
||||
choose MBR. Even if you boot via UEFI/GPT.
|
177
src/posts/2020-11-15_OpenBSD_Video_FAQ.pm
Normal file
177
src/posts/2020-11-15_OpenBSD_Video_FAQ.pm
Normal file
@ -0,0 +1,177 @@
|
||||
# OpenBSD How to use a webcam
|
||||
|
||||
## Enabling Video Recording (OpenBSD 6.9)
|
||||
|
||||
For privacy reasons, video recording is disabled by default in OpenBSD.
|
||||
The sysctl "kern.video.record" may be used to enable it. While recording
|
||||
is disabled, a blank video will be shown.
|
||||
|
||||
```
|
||||
# sysctl kern.video.record=1
|
||||
# echo kern.video.record=1 >> /etc/sysctl.conf
|
||||
```
|
||||
|
||||
## Supported Hardware
|
||||
|
||||
Most webcams today implement the USB Video Class (UVC) specification,
|
||||
which is supported by the uvideo(4) device driver and attaches to the
|
||||
video(4) device. The manpage lists some supported devices, but there is
|
||||
a good chance that other devices work as well. For example, webcams in
|
||||
Lenovo Thinkpad laptops do usually work.
|
||||
|
||||
A supported webcam (or other video device) shows up in dmesg like this:
|
||||
|
||||
```
|
||||
uvideo0 at uhub0 port 8 configuration 1 interface 0 "Azurewave Integrated Camera"rev 2.01/69.05 addr 10
|
||||
video0 at uvideo0
|
||||
uvideo1 at uhub0 port 8 configuration 1 interface 2 "Azurewave Integrated Camera" rev 2.01/69.05 addr 10
|
||||
video1 at uvideo1
|
||||
```
|
||||
|
||||
You see that an uvideo device was detected and has been attached to
|
||||
video0. This device will be accessible through /dev/video0.
|
||||
|
||||
Modern laptops sometimes attach a second video device, which is the
|
||||
infrared camera for face recognition. The second camera does not produce
|
||||
a usable video stream.
|
||||
|
||||
You can find the usable camera with the video(1) command:
|
||||
|
||||
```
|
||||
$ video -q -f /dev/video0
|
||||
video device /dev/video0:
|
||||
encodings: yuy2
|
||||
frame sizes (width x height, in pixels) and rates (in frames per
|
||||
second):
|
||||
320x180: 30
|
||||
320x240: 30
|
||||
352x288: 30
|
||||
424x240: 30
|
||||
640x360: 30
|
||||
640x480: 30
|
||||
848x480: 20
|
||||
960x540: 15
|
||||
1280x720: 10
|
||||
controls: brightness, contrast, saturation, hue, gamma, sharpness,
|
||||
white_balance_temperature
|
||||
|
||||
$ video -q -f /dev/video1
|
||||
video: /dev/video1 has no usable YUV encodings
|
||||
```
|
||||
|
||||
The usable camera device shows supported resolutions and frameratei.
|
||||
Note that the framerates only apply to the uncompressed YUY2 stream.
|
||||
More on that in "Recording a webcam stream"
|
||||
|
||||
## Using a webcam as user
|
||||
|
||||
To use the webcam as regular user, you need to change the device
|
||||
permissions. Only root is allowed to access video devices by default.
|
||||
|
||||
One way of allowing your user to access the video devices is to change
|
||||
the permissions from ~/.xsession. You can configure doas(1) to perform
|
||||
chmod(1) as superuser without asking for a password for your user.
|
||||
|
||||
```
|
||||
$ doas chown $USER /dev/video0
|
||||
```
|
||||
|
||||
## Recoding a webcam stream
|
||||
|
||||
This section uses ffplay and ffmpeg from graphics/ffmpeg. To find out
|
||||
what your camera is capable of, run the following command:
|
||||
|
||||
```
|
||||
$ ffplay -f v4l2 -list_formats all -i /dev/video0
|
||||
[...]
|
||||
[video4linux2,v4l2 @ 0x921f8420800] Raw : yuyv422 : YUYV : 640x480 320x180 320x240 352x288 424x240 640x360 848x480 960x540 1280x720
|
||||
[video4linux2,v4l2 @ 0x921f8420800] Compressed: mjpeg : MJPEG : 1280x720 320x180 320x240 352x288 424x240 640x360 640x480 848x480
|
||||
```
|
||||
|
||||
At the end of the output, you'll find two lines similiar to the two
|
||||
above.
|
||||
|
||||
The first line shows resolutions supported in the uncompressed YUYV
|
||||
format. The frame rates in this format can be very low. The second line
|
||||
shows the supported MJPEG compressed video resolutions, which deliver
|
||||
much higher framerates (usually 30fps or 60fps).
|
||||
|
||||
Now try to play the webcam stream. Choose one of the MJPEG resolutions
|
||||
and run:
|
||||
|
||||
```
|
||||
$ ffplay -f v4l2 -input_format mjpeg -video_size 1280x720 -i /dev/video0
|
||||
[...]
|
||||
Input #0, video4linux2,v4l2, from '/dev/video0':B sq= 0B f=0/0
|
||||
Duration: N/A, start: 1599377893.546533, bitrate: N/A
|
||||
Stream #0:0: Video: mjpeg (Baseline), yuvj422p(pc, bt470bg/unknown/unknown), 1280x720, 30 fps, 30 tbr, 1000k tbn, 1000k tbc
|
||||
```
|
||||
|
||||
The webcam stream should be displayed. Ffplay also shows the used
|
||||
resolution and the framerate (fps) used.
|
||||
|
||||
If this works, you can go ahead and record the video with ffmpeg:
|
||||
|
||||
```
|
||||
$ ffmpeg -f v4l2 -input_format mjpeg -video_size 1280x720 \
|
||||
-i /dev/video0 ~/video.mkv
|
||||
```
|
||||
|
||||
## Controlling webcam settings
|
||||
|
||||
Webcams usually have brightness, contrast and other controls. Video(1)
|
||||
allows you to alter these settings.
|
||||
|
||||
First find out which supported controls your camera has:
|
||||
|
||||
```
|
||||
$ video -c
|
||||
brightness=128
|
||||
contrast=32
|
||||
saturation=64
|
||||
hue=0
|
||||
gamma=120
|
||||
sharpness=3
|
||||
white_balance_temperature=auto
|
||||
```
|
||||
|
||||
You can change for example the brightness setting to 200:
|
||||
|
||||
```
|
||||
$ video brightness=200
|
||||
brightness: 128 -> 200
|
||||
```
|
||||
|
||||
If you would like to reset all settings to their defaults, you can do so
|
||||
with:
|
||||
|
||||
```
|
||||
$ video -d
|
||||
```
|
||||
|
||||
```
|
||||
$ video -c
|
||||
brightness=128
|
||||
contrast=32
|
||||
saturation=64
|
||||
hue=0
|
||||
gamma=120
|
||||
sharpness=3
|
||||
white_balance_temperature=auto
|
||||
```
|
||||
|
||||
Some settings, like the white_balance_temperature support automatic
|
||||
adjustments. You can set them to a fixed value or set them to "auto",
|
||||
which lets the camera decide and use whatever value it thinks is best.
|
||||
|
||||
## Access webcam in chromium
|
||||
|
||||
Chromium has access to /dev/video and /dev/video0 by default. To allow
|
||||
Chromium to access other video devices, you need to add the device paths
|
||||
tto /etc/chromium/unveil.main and /etc/chromium/unveil.utility_video
|
||||
|
||||
## Access webcam in firefox
|
||||
|
||||
Firefox has access to /dev/video and /dev/video0 by default. To allow
|
||||
Firefox to access other video devices, you need to add the device paths
|
||||
to /etc/firefox/unveil.main.
|
52
src/posts/2021-01-09_Mutt_Inline-Patch_Macro.pm
Normal file
52
src/posts/2021-01-09_Mutt_Inline-Patch_Macro.pm
Normal file
@ -0,0 +1,52 @@
|
||||
# Mutt inline patch handling
|
||||
|
||||
Developers like to send diffs inline in emails. They do this, because
|
||||
it's fast and easy to read through them, comment on them and also to
|
||||
apply them. Many version control systems take over the email text into
|
||||
the patch description as well.
|
||||
|
||||
Up to now, my workflow was manual. I had to save the email somewhere,
|
||||
tthen open a terminal, cd to the direcory the patch shall be applied in
|
||||
and call the patch utility with the path to the saved email as argument.
|
||||
|
||||
No more.
|
||||
|
||||
This mutt macro takes the current visible email and copies it to a
|
||||
ttemporary file (/tmp/mutt-patch.diff). Then it executes the portpatch.sh
|
||||
shell script. All with one push on ctrl+s while looking at the email.
|
||||
|
||||
The macro must be written in one line and ^S can be entered with the
|
||||
keyboard sequence ctrl+v ctrl+s:
|
||||
|
||||
```
|
||||
macro pager ^S "<shell-escape>rm -f /tmp/mutt-patch.diff<enter><copy-message>/tmp/mutt-patch.diff<enter><enter-command>echo 'Saved as /tmp/mutt-patch.diff'<enter><shell-escape>~/.mutt/scripts/portpatch.sh /tmp/mutt-patch.diff<enter>"
|
||||
```
|
||||
|
||||
The portpatch.sh script:
|
||||
|
||||
```
|
||||
#!/bin/sh
|
||||
|
||||
printf '\n-------------------------------------------------------\n'
|
||||
cat "$1" | egrep ^Index\|^RCS\|--git
|
||||
printf '-------------------------------------------------------\n\n'
|
||||
|
||||
printf "Path for patch [/usr/ports]? "
|
||||
read _path
|
||||
|
||||
[ -z "$_path" ] && _path=/usr/ports
|
||||
|
||||
doas patch -p0 -d $_path < "$1"
|
||||
cd $_path && ksh
|
||||
```
|
||||
|
||||
The script shows some relvant bits from the email patch that are handy
|
||||
tto determine on which path the patch shall be applied.
|
||||
|
||||
Next it alles the user to enter a different path. I most use /usr/ports,
|
||||
so this is the default. Then the patch is applied and a ksh shell is
|
||||
opened for further work.
|
||||
|
||||
Quitting the shell brings me back to mutt to work on the next email.
|
||||
|
||||
This is quite friggin handy.
|
51
src/posts/2021-01-10_Port_Submission_Checklist.pm
Normal file
51
src/posts/2021-01-10_Port_Submission_Checklist.pm
Normal file
@ -0,0 +1,51 @@
|
||||
# Port Submission Checklist
|
||||
|
||||
When something is almost done, I tend to skip steps in the QA phase. So
|
||||
this is a personal checklist to help me focus and not skip steps.
|
||||
|
||||
00. Set up the _pbuild user and work with PORTS_PRIVSEP=yes.
|
||||
|
||||
Existing Port Update Checklist:
|
||||
|
||||
1. Execute portcheck
|
||||
2. Execute make port-lib-depends-check
|
||||
3. Execute make update-plist
|
||||
4. Execute make update-patches
|
||||
5. Check if shared libraries need bumping
|
||||
6. Execute make test
|
||||
7. Document (new) patches
|
||||
8. Check REVISION (remove on upstream update)
|
||||
9. Test the software
|
||||
10. Really, test the thing!
|
||||
11. Review the created patches for unnecessary cruft
|
||||
|
||||
New Port Checklist:
|
||||
|
||||
1. Execute portcheck -N
|
||||
2. Execute make port-lib-depends-check
|
||||
3. Remove -g CFLAG if present
|
||||
4. Add a test target if possible
|
||||
5. Document patches
|
||||
6. Execute make plist
|
||||
7. Make sure files are installed to the correct path
|
||||
8. Check for shared libraries and record them
|
||||
9. Execute make test
|
||||
10. Test on a bare test machine to catch all dependency issues
|
||||
11. Test the software
|
||||
12. Really, test the thing!
|
||||
13. Review the created patches for unnecessary cruft
|
||||
|
||||
When submitting a patch to the mailing list:
|
||||
|
||||
1. The patch goes inline (new ports and huge diffs go as tarball)
|
||||
2. Don't mess up tabs
|
||||
3. Mention upstream changes (or link to changelog)
|
||||
4. Mention port changes
|
||||
5. Mention carried out tests (and result)
|
||||
6. Mention tested architectures
|
||||
|
||||
Carry out all steps with full concentration. Don't assume steps could be
|
||||
skipped, just because it worked in the last version.
|
||||
|
||||
When creating patches, create fixes that can be upstreamed (and do so)
|
||||
if possible.
|
25
src/posts/2021-05-05_Linux_Presentation_Day_2021.pm
Normal file
25
src/posts/2021-05-05_Linux_Presentation_Day_2021.pm
Normal file
@ -0,0 +1,25 @@
|
||||
# Linux Presentation Day 2021 (DE)
|
||||
|
||||
This year, I decided to take part in the linux presentation day (LPD).
|
||||
While I'm not really a Linux person (anymore), I think supporting people
|
||||
tto switch to OpenSource software is a valuable thing.
|
||||
|
||||
The event is supposed to be a European wide, but it looks like it's
|
||||
mostly a German event. I recorded 3 Talks for it (in German).
|
||||
|
||||
The Linux Presentation Day is on the 15th of May 2021, but the Videos
|
||||
will be online starting from the 7th.
|
||||
|
||||
[LPD-Online 2021 Fahrplan](https://l-p-d.org/de/events/lpd_online_2021-1/fahrplan/start)
|
||||
|
||||
Once online, I'll add the videos to our Unix User Group Wiki as well.
|
||||
|
||||
- [Terminals verwalten mit TMUX](https://wiki.uugrn.org/UUGRN:LPD-Online-2021/TMUX)
|
||||
- [Shell Survival Guide I](https://wiki.uugrn.org/UUGRN:LPD-Online-2021/Shell_Survial_Guide_1)
|
||||
- [Shell Survival Guide II](https://wiki.uugrn.org/UUGRN:LPD-Online-2021/Shell_Survial_Guide_2)
|
||||
|
||||
I definitely have enough material for two more Shell Survival Guides,
|
||||
but I was not able to record them in time. Maybe I'll add them at a
|
||||
later point to our Unix User Group Wiki.
|
||||
|
||||
[Feel free to meet us at our Introduction Live Channel (DE) @ 15th of May](https://l-p-d.org/fahrplan#7ecc)
|
220
src/posts/2021-05-19_GnuPG_Quickstart.pm
Normal file
220
src/posts/2021-05-19_GnuPG_Quickstart.pm
Normal file
@ -0,0 +1,220 @@
|
||||
# GnuPG Quickstart
|
||||
|
||||
I love GPG and the way it works. I know there are many that complain
|
||||
about it because it has flaws. My stance on this is that I prefer
|
||||
battle-tested software with known flaws to something with unknown flaws.
|
||||
|
||||
Anyway, this should get you started with GnuPG
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Install gpg and pinentry.
|
||||
|
||||
```
|
||||
pkg_add gnupg pinentry
|
||||
```
|
||||
|
||||
## You need a Key
|
||||
|
||||
If you want to lock and unlock stuff, you need a key. This is how you
|
||||
get to one:
|
||||
|
||||
```
|
||||
gpg --generate-key
|
||||
```
|
||||
|
||||
Hop through the wizard until you see these lines:
|
||||
|
||||
```
|
||||
pub rsa3072 2021-05-19 [SC] [expires: 2023-05-19]
|
||||
BA696588D9A04AD9F70DA33EC54733F6DBECC2C1
|
||||
uid John Doe <j.doe@example.com>
|
||||
sub rsa3072 2021-05-19 [E] [expires: 2023-05-19]
|
||||
```
|
||||
|
||||
If you see an error like:
|
||||
|
||||
```
|
||||
gpg: agent_genkey failed: Permission denied
|
||||
```
|
||||
|
||||
Add the following entry and try again.
|
||||
|
||||
~/.gnupg/gpg-agent.conf:
|
||||
```
|
||||
allow-loopback-pinentry
|
||||
```
|
||||
|
||||
Congratulations, you got yourself a GPG Key. This long gibberish is your
|
||||
full GPG Key ID. Most of the time, you can simply use the last 8
|
||||
characters. So the short version of this GPG Key is DBECC2C1.
|
||||
|
||||
You can set it as default key, so it's used to encrypt stuff when no
|
||||
explicit key is given.
|
||||
|
||||
~/.gnupg/gpg.conf:
|
||||
```
|
||||
default-key DBECC2C1
|
||||
```
|
||||
|
||||
## Share the key with your people
|
||||
|
||||
If you want someone to be able to encrypt something for you, send him or
|
||||
her the output of:
|
||||
|
||||
```
|
||||
gpg --export -a DBECC2C1
|
||||
```
|
||||
|
||||
You can also use your email address instead of the Key ID, if you have
|
||||
only one key with it. This key is public. So put it on some webspace and
|
||||
add a link to your email header or signature.
|
||||
|
||||
## Upload the key so people can find it
|
||||
|
||||
You can also upload your key to a key server. For this, configure a
|
||||
keyserver:
|
||||
|
||||
~/.gnupg/gpg.conf:
|
||||
```
|
||||
keyserver hkp://ha.pool.sks-keyservers.net
|
||||
```
|
||||
|
||||
Then send your key to it:
|
||||
|
||||
```
|
||||
gpg --send-keys DBECC2C1
|
||||
```
|
||||
|
||||
# You got a key from someone
|
||||
|
||||
Add a key from someone else to gnupg, so you can use it to encrypt data
|
||||
for this person. If the key is on your harddrive, use:
|
||||
|
||||
```
|
||||
gpg --import <pubkeyfile.asc>
|
||||
```
|
||||
|
||||
The file ending here is kind of undefined. Some call it .asc, .gpg, .pub
|
||||
or .key. If the key is on a key server, you can import it like so:
|
||||
|
||||
```
|
||||
gpg --recv-key 52BE43BA
|
||||
```
|
||||
|
||||
This would import my key. You can look at it now with:
|
||||
|
||||
```
|
||||
gpg --list-keys 52BE43BA
|
||||
```
|
||||
|
||||
|
||||
# Encrypt a file
|
||||
|
||||
This encrypts the file plain.txt with the public key DBECC2C1.
|
||||
|
||||
```
|
||||
gpg --encrypt -r DBECC2C1 file.txt
|
||||
```
|
||||
|
||||
Now you have file.txt.gpg, which is the encrypted version
|
||||
|
||||
|
||||
## Decrypt a file
|
||||
|
||||
GnuPG automaticall figures out what key it can use to decrypt a file. So
|
||||
this will output the content of file.txt on the terminal. If you want
|
||||
to save the output in a file, add -o file.txt.
|
||||
|
||||
```
|
||||
gpg -d file.txt.gpg
|
||||
gpg -d file.txt.gpg -o file.txt
|
||||
```
|
||||
|
||||
# Choose a better password prompt
|
||||
|
||||
You can change the way gpg asks for the password:
|
||||
|
||||
~/.gnupg/gpg-agent.conf
|
||||
```
|
||||
pinentry-program /usr/local/bin/pinentry-curses
|
||||
```
|
||||
|
||||
Options are:
|
||||
- pinentry (sometimes also called pinentry-tty)
|
||||
- pinentry-curses
|
||||
- pinentry-gtk2: pkg_add pinentry-gtk2
|
||||
- pinentry-gnome3: pkg_add pinentry-gnome3
|
||||
- pinentry-dmenu: https://github.com/ritze/pinentry-dmenu
|
||||
|
||||
! Note: If you use a console pinentry program and want to use gpg with a !
|
||||
! GUI tool (like thunderbird), the password prompt will be invisible and !
|
||||
! gpg/thunderbird will freeze. "
|
||||
|
||||
Makes sense, doesn't it?
|
||||
|
||||
# Start GPG Agent for password caching
|
||||
|
||||
Put this in your .kshrc or .bashrc:
|
||||
|
||||
~/.kshrc:
|
||||
```
|
||||
export GPG_TTY=$(tty)
|
||||
gpg-connect-agent /bye
|
||||
```
|
||||
|
||||
# Make a Backup
|
||||
|
||||
There is no handholding cloud or support team you can call when you
|
||||
messed up or deleted your key. So back it up safely.
|
||||
|
||||
Either you backup your ~/.gnugp directory, or you export the secret
|
||||
keys and backup them safely.
|
||||
|
||||
```
|
||||
gpg --export-secret-keys -a DBECC2C1 > gpg_key_backup.sec
|
||||
```
|
||||
|
||||
Seriously, don't skip this step.
|
||||
|
||||
# Configure Mutt
|
||||
|
||||
Install mutt with the gpgme flavor. Gpgme is the "new way" of handling
|
||||
gpg in mutt.
|
||||
|
||||
```
|
||||
pkg_add mutt--gpgme
|
||||
```
|
||||
|
||||
If you're not on OpenBSD, check with `mutt -v` if it was compiled with
|
||||
the --enable-gpgme option. Then enable it in mutt.
|
||||
|
||||
~/.muttrc
|
||||
```
|
||||
crypt_use_gpgme = yes
|
||||
```
|
||||
|
||||
In the mutt compose view, you can now select Security Options.
|
||||
|
||||
```
|
||||
From: C0dev0id <c0@example.com>
|
||||
To: j.doe@example.com
|
||||
Cc:
|
||||
Bcc:
|
||||
Subject: Hello my friend
|
||||
Reply-To:
|
||||
Fcc: =Sent
|
||||
Security: Sign, Encrypt (PGP/MIME)
|
||||
Sign as: <default>
|
||||
```
|
||||
|
||||
You can change the setting with the key "p", which should bring up a
|
||||
selection menu.
|
||||
|
||||
```
|
||||
PGP (e)ncrypt, (s)ign, sign (a)s, (b)oth, s/(m)ime or (c)lear?
|
||||
```
|
||||
|
||||
Changelog:
|
||||
* 2021-05-17: Created
|
||||
* 2022-06-28: Gemini compatible styling :/
|
58
src/posts/2021-09-26_Virtual_Residual_Memory.pm
Normal file
58
src/posts/2021-09-26_Virtual_Residual_Memory.pm
Normal file
@ -0,0 +1,58 @@
|
||||
# Memory management, virtual and residential memory
|
||||
|
||||
Memory management is a complex topic and most can be left for the kernel
|
||||
to handle. But having a fundamental idea about where memory is
|
||||
allocated greatly helps in understanding top(1) and the memory footprint
|
||||
of applications.
|
||||
|
||||
## Process memory address space (page)
|
||||
|
||||
When a process starts up, the kernel assigns is a so called memory page.
|
||||
The page size depends on the architecture. On amd64 it's 2^64 - 1 bytes.
|
||||
|
||||
Every memory allocation this process performs, returns a pointer to some
|
||||
place within this page. Forcing a pointer outside this page, will cause
|
||||
a SEGFAULT.
|
||||
|
||||
```
|
||||
char *w = 1; // segfault
|
||||
char *w = malloc(12); // returns pointer within page
|
||||
```
|
||||
|
||||
## Memory allocation (virtual memory)
|
||||
|
||||
Let's say we allocatate 2G of memory:
|
||||
|
||||
```
|
||||
char *m = malloc(2*1073741824); // 2*1G in bytes
|
||||
```
|
||||
|
||||
This will grab 2G of consecutive address space within the process memory.
|
||||
At this point, the memory is likely available but not guaranteed. The
|
||||
allocation shows up in top(1) as "SIZE" or on linux as "VIRT"ual memory.
|
||||
This memory is not actually used. So nothing has been written to the
|
||||
physical RAM chip in your computer.
|
||||
|
||||
## Using memory (residential memory)
|
||||
|
||||
Once memory gets used, it will actually use up space on your RAM chip.
|
||||
|
||||
```
|
||||
memset(m, 'u', 1073741824);
|
||||
```
|
||||
|
||||
Now we've written the character "u" to the first 1G of our allocated
|
||||
memory. If we look at top(), we'll see something like this:
|
||||
|
||||
```
|
||||
PID TID PRI NICE SIZE RES STATE WAIT TIME CPU COMMAND
|
||||
96621 569318 3 0 2048M 1027M sleep/12 ttyin 0:01 1.66% ./a.out
|
||||
^ ^
|
||||
allocated memory -' `- used (written) memory
|
||||
```
|
||||
|
||||
Note 1: When memory is swapped to disk, it leaves the residential bucket and
|
||||
can be seen as swap->used.
|
||||
|
||||
Note 2: Stack memory will also show up as residential when used. Unused stack
|
||||
memory will *not* show up as virtual memory.
|
353
src/posts/2023-05-13_Curious_about_spam.pm
Normal file
353
src/posts/2023-05-13_Curious_about_spam.pm
Normal file
@ -0,0 +1,353 @@
|
||||
# Curious About Spam
|
||||
|
||||
# Why am I getting spam/phishing mails?
|
||||
|
||||
Let's think about the person on the other side. The one who sends you
|
||||
this mail. They're not doing so to annoy you or to entertain you. There
|
||||
are reasons:
|
||||
|
||||
1. They want your data
|
||||
2. They want to infect your device
|
||||
3. They want your money
|
||||
|
||||
And they want to do this, without disclosing their real identity.
|
||||
|
||||
## Why do they want my data?
|
||||
|
||||
Real data is valuable. Have you noticed that you need accounts
|
||||
everywhere? It was not always this way. Real data, from existing people
|
||||
is valuable. Companies use them to combine them and profile people to
|
||||
serve better ads, show you content you influences you most and sell more
|
||||
stuff and shape your beliefs.
|
||||
|
||||
But what can bad guys do? The same and a lot more! If they have real
|
||||
data, they can use it to impersonate you. They can try to reset
|
||||
passwords and gain access to your accounts, they can do stuff in your
|
||||
name. Or simply sell your data to others who have use for it.
|
||||
|
||||
## Why would they infect my device?
|
||||
|
||||
Infecting a device gives the attacker control over the device. In
|
||||
general, there are two flavors of how this can play out: noticeable and
|
||||
unnoticeable:
|
||||
|
||||
The attacker can...
|
||||
- encrypt your files and only decrypt them after you've sent them money.
|
||||
You will certainly notice this one.
|
||||
- read each keystroke on your keyboard and gain access to accounts
|
||||
you log in (or all of them, because you're using the same password,
|
||||
everywhere, right?)
|
||||
- use your network connection for their own activities, like downloading
|
||||
or distributing illegal files and porn for example.
|
||||
- use your computing power to mine bitcoins.
|
||||
- make your computer a part of a botnet to hack other computers, send
|
||||
mails etc.
|
||||
- infiltrate your home network and jump to other computers and from
|
||||
there to your work network.
|
||||
- mine data about you to blackmail you later.
|
||||
|
||||
The possibilities are endless.
|
||||
|
||||
## It's all about money and/or power to make money
|
||||
|
||||
In the end, it's all about money. And if you're not trying to keep it
|
||||
legal... well... you can do a lot:
|
||||
|
||||
- You can blackmail people (via ransomeware / or targeted)
|
||||
- You can buy stuff in the name of other people
|
||||
- You can sell other peoples (paypal) accounts
|
||||
- You can sell other peoples credit card numbers
|
||||
- You can provide hacking services
|
||||
- You can trick people to signing up for something they didn't want
|
||||
|
||||
And you can lie and fake as you like...
|
||||
|
||||
# But... how?
|
||||
|
||||
And this is the right question: Let's keep in mind, the attacker wants
|
||||
to stay anonymous. But they also want something from you. And this data
|
||||
needs to somehow get to them. Let's look at what can happen:
|
||||
|
||||
## Infecting your device via attachment
|
||||
|
||||
Ever heard to not open attachments from untrusted sources? You sure did.
|
||||
But why? Attackers know how your computer works. Most likely better than
|
||||
you do. And they are using this to their advantage.
|
||||
|
||||
### Attachment: funny\_cats.jpg
|
||||
|
||||
Maybe you were told that every file has a file extension that shows the
|
||||
system how to open it? Well, at the same time, Microsoft decided that
|
||||
file extension are a burden and they started hiding them.
|
||||
|
||||
Let's say I'm sending you an email with the attachment
|
||||
"funny\_cats.exe". Would you open it? Probably not, because ".exe" looks
|
||||
suspicious. What about "funny\_cats.jpg"? Hell yeah - everyone loves
|
||||
funny cat pictures!
|
||||
|
||||
What about "funny\_cats.jpg.exe"? No?
|
||||
|
||||
What if Windows decides to hide the extension and shows you
|
||||
"funny\_cats.jpg" instead? Boom, you just opened "funny\_cats.jpg.exe"
|
||||
without realizing it. And usually the virus-program shows you a funny
|
||||
cat picture, so you don't wonder why nothing is happening. But
|
||||
additionally, a backdoor is installed that connects to some
|
||||
other (probably hacked) computer the attacker controls already.
|
||||
Congratulations, you're now part of a bot-net.
|
||||
|
||||
### Attachment: invoice.pdf
|
||||
|
||||
Of course we can do the double-extension trick described above with
|
||||
other file types. But it may also happen that a double extension is
|
||||
not used - instead bugs in the opening program are used. This commonly
|
||||
happens with pdf, because the pdf file format is opened with the same
|
||||
program on almost every computer. If this pdf program has a bug that
|
||||
allows the attacker to gain control... well, expect e-mail
|
||||
containing this kind of pdf documents.
|
||||
|
||||
This is bad, because there's not really a way to look at it in a safe
|
||||
way. So, don't open it. And keep up with security updates!
|
||||
|
||||
## Your account needs to be verified!!!!
|
||||
|
||||
This is a classic opening for phishing. Here the attacker wants your
|
||||
data. Usually there is a link in the email that opens a website which
|
||||
wants you to enter some data. The general advice here is: Don't do it.
|
||||
If you get an email like this don't use the link in the e-mail, but
|
||||
open a browser and manually open the website of the institution the
|
||||
email claims to be. Log in there and check if your account is fine. If
|
||||
you really need to do something, you'll be notified after you logged on
|
||||
there.
|
||||
|
||||
But watch out for more clues in the email. Most of the time, the link
|
||||
doesn't actually go to the right website. It will open up a website that
|
||||
_looks_ like the original, but is not. Click right on the link, copy the
|
||||
link address, and paste it into notepad to really look at it.
|
||||
|
||||
```
|
||||
https://www.mybank.com/account/verify/d8sL3jDk/?id=23456
|
||||
'---' '-' '----' '-' '------------' '------' '------'
|
||||
| | | | | | |
|
||||
| | | | | Identifying "unique" information
|
||||
| | | | Some path (not super relevant)
|
||||
| | | Top Level Domain (watch out!)
|
||||
| | Domain (watch out!)
|
||||
| Subdomain (not super relevant here)
|
||||
Protocol (should be https)
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
https://www.mybank.com/account/verify/d8sL3jDk/?id=23456
|
||||
^^^^^
|
||||
```
|
||||
Anything important nowadays should communicate over the http*s*
|
||||
protocol. This means the the communication is encrypted. If the link is
|
||||
only a http link, don't enter any information into the website. Every
|
||||
computer between you and the target website can read the data.
|
||||
|
||||
```
|
||||
https://www.mybank.com/account/verify/d8sL3jDk/?id=23456
|
||||
^^^
|
||||
```
|
||||
This is the subdomain. It can change and look weird. Multiple
|
||||
subdomains can exist. So you might be presented with something like
|
||||
`https://foo.bar.baz.mybank.com`, which is nothing to worry about
|
||||
if `mybank.com` is correct. But: `https://www.mybank.foo.com` *is*
|
||||
something to worry about, when the usual account is on "mybank.com".
|
||||
|
||||
```
|
||||
https://www.mybank.com/account/verify/d8sL3jDk/?id=23456
|
||||
^^^^^^
|
||||
```
|
||||
This is the so called domain. This one is tight to the top level domain
|
||||
below. Nothing must be between the domain and the top level domain. And
|
||||
both must be absolutely correct, otherwise you'll not reach the website
|
||||
you think you reach.
|
||||
|
||||
```
|
||||
https://www.mybank.com/account/verify/d8sL3jDk/?id=23456
|
||||
^^^
|
||||
```
|
||||
This is the top level domain and the anchor point. You can identify it,
|
||||
because it has a dot to the left and the first / to the right: ".com/".
|
||||
The top level domain forms a union with the domain. So you can be sure
|
||||
that everything with ".mybank.com/" will actually go to your bank
|
||||
account. The following examples will *not* go to your bank account:
|
||||
- `mybank.co.com`: The domain and the top level domain must follow each
|
||||
other directly
|
||||
- `mybank.com.uk`: The top level domain here is .uk, not .com.
|
||||
- `myaccount.com/mybank.com`: "mybank.com" is behin the first / and
|
||||
therefore not part of the domain
|
||||
at all. You're connecting to domain "myaccount" with top level domain
|
||||
".com". This is not mybank.com.
|
||||
- `mybank.account.com`: Same as the first example
|
||||
|
||||
```
|
||||
https://www.mybank.com/account/verify/d8sL3jDk/?id=23456
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
```
|
||||
This is part of the URL path. This can be anything. It's generally
|
||||
nothing to worry about if it passes a sanity check. If the URL is
|
||||
"shoes/men/checkout" - then why would this exist on website of your
|
||||
credit institute...
|
||||
|
||||
|
||||
```
|
||||
https://www.mybank.com/account/verify/d8sL3jDk/?id=23456
|
||||
^^^^^^^^
|
||||
```
|
||||
The path often has generated elements of random character or numbers.
|
||||
This is sometimes part of the website functionality, but also often used
|
||||
for tracking. If you're suspicious but still want to try the URL, change
|
||||
these random numbers a bit. These tracking IDs are often used to track
|
||||
who clicked on a link. So simply by opening the link, you may valide
|
||||
your data and proof to the sender that the email has reached you.
|
||||
|
||||
```
|
||||
https://www.mybank.com/account/verify/d8sL3jDk/?id=23456
|
||||
^^^^^^^^^
|
||||
```
|
||||
Same as above. After the ?, there are key=value pairs of data. You
|
||||
may find any kind of information there. This data is send right at
|
||||
the moment when you click on the link. Watch out for identifying
|
||||
data like IDs, hashes (random stuff), emails etc. So if you read
|
||||
`?confirm=<your@mail.com>` you know what's going to happen, right?
|
||||
|
||||
# The whole email is one big image (with link)
|
||||
|
||||
Sometimes an email looks good. But technically it's one big image. And
|
||||
no matter where you click on the email, a link is opened.
|
||||
|
||||
This is usually easy to spot if you click and drag and the whole email
|
||||
moves with the cursor. Or the cursor is this "hand" symbol that usually
|
||||
only appears over links, but here it's there all the time - even over
|
||||
non-link text or free space between lines.
|
||||
|
||||
This is a 100% indication that it's spam or phishing. Having the whole
|
||||
email layout baked into a picture prevents content scanners from
|
||||
"reading" the email and blocking it based on used words. Because they
|
||||
read text, not images. Doing so, shows that the email author wants to
|
||||
do evil and evade counter measures.
|
||||
|
||||
# Psychological tricks
|
||||
|
||||
## This is urgent!
|
||||
|
||||
Your you'll loose your account / your chance to win / this awesome sale.
|
||||
|
||||
People are less careful when confronted with urgency. So spam senders
|
||||
often try to make you do something *now* to prevent you from thinking
|
||||
about your actions.
|
||||
|
||||
## Many correct URLs and Information
|
||||
|
||||
Better spam mails show a lot of correct information to gain trust. They
|
||||
may include images from the your actual bank website. They may link to
|
||||
the impressum and show correct phone numbers for customer support etc...
|
||||
|
||||
All this is there to gain your trust. Really look at the link they want
|
||||
you to click on. And don't be fooled if the link is written out in the
|
||||
email. In an HTML type email, the display text and the actual link can
|
||||
be different. In code, this looks like:
|
||||
```
|
||||
<a href="https://i.am.stealing.your.data.example.com/id/12345">mybank.com/account/verify</a>
|
||||
```
|
||||
Your email program is displaying "mybank.com/account/verify",
|
||||
but if you click on it, your browser will open
|
||||
"https://i.am.stealing.your.data.com/id/12345".
|
||||
|
||||
This is why you should right click on the link and copy it and paste it
|
||||
to notepad before opening it in the browser. And if you clicked on it
|
||||
already, check the browser bar.
|
||||
|
||||
## You won 50 Million Dollar
|
||||
|
||||
No you didn't. But they surely you need to pay some small fee so they
|
||||
can send you the money.
|
||||
|
||||
## I need someone to trust with the Millions I inherited...
|
||||
|
||||
Same as above. Proof that you're real by sending them money. Or they ask
|
||||
for personal information via email right away.
|
||||
|
||||
## Buy drugs / weapons / other stuff
|
||||
|
||||
That's just the regular kind of spam. They want you to open their
|
||||
website. Sometimes the email shows what they're selling. But sometimes
|
||||
you get an email about your bank account and the link sends you to a
|
||||
shoe shop.
|
||||
|
||||
It's weird, but appearently it works. Especially here, watch out for
|
||||
identifying information in the link. They are pretty much interested
|
||||
in who clicked on the link to curate their customer database.
|
||||
|
||||
# Email Body
|
||||
|
||||
Especially phishing mail try to show up in a style of a website. And it's
|
||||
rarely perfect (sometimes it is!). So misalinged images, Text in weird
|
||||
places, bad language and slightly off colors or fonts are indicators
|
||||
that this was not created by the companies brand team.
|
||||
|
||||
Also, often spammers only know your email address. If you're greeted in
|
||||
an anonymous fashion, like "Hello Email Receipient" or "Dear Friend",
|
||||
this indicates that they don't know your name. Which is unlikely for a
|
||||
company that you're a customer of.
|
||||
|
||||
Some spammers put your email in: "Hello you\@yourmail.com", doesn't count
|
||||
as a personal greeting.
|
||||
|
||||
If you receive an invoice from a company you're actually a customer of,
|
||||
maybe compare the email style to the last one you got. If the PDF is
|
||||
named by your actual customer id is probably legit, even if the rest of
|
||||
the mail checks some spam boxes.
|
||||
|
||||
# Check the Header
|
||||
|
||||
## From Address
|
||||
|
||||
Don't believe what your email programm is showing you. Emails are easy
|
||||
to fake. Just because an email appears to be sent from "Customer Support
|
||||
Mybank", doesn't mean it actually came from there. Even the address
|
||||
"noreply\@mybank.com", which would pass the domain and top level domain
|
||||
check can be faked. So, the From address may look good, but that's no
|
||||
indication that it's not spam. However, if the From Address looks wrong,
|
||||
it's a clear indication for spam. I mean - why would your bank send you
|
||||
an email that comes from a differnt domain? That's unlikely.
|
||||
|
||||
## To Address
|
||||
|
||||
Sometimes the "To" Address is wrong. This is a indicator for spam. If
|
||||
an email is sent out to many people, this often happens as blind copy
|
||||
(BCC). Then you see either nothing, or "undisclosed receipients" or an
|
||||
unknown Email Address in the "To" header.
|
||||
|
||||
There are more header fields that could be checked. But most email
|
||||
programs are not showing them. And they are much more complicated to
|
||||
explain.
|
||||
|
||||
# There is no one size fits all approach...
|
||||
|
||||
While an email is either spam or not, it's sometimes not easy to find
|
||||
out what is what. Often it's obvious, but other times it's not. Spammers
|
||||
are getting better. Phishing websites are becoming more professional.
|
||||
|
||||
There is more that could be checked. There are more headers and there
|
||||
are SSL certificates at play, which can be checked and compared. But these
|
||||
are advanced techniques I'm explaining in the ebook below.
|
||||
|
||||
So we leave it at that. If you have understood the concepts explained here,
|
||||
you should be fairly safe and also be able to explore spam mails in a safe
|
||||
way.
|
||||
|
||||
# Download my ebook about spam for free
|
||||
|
||||
This and much more information about spam, phishing and digital self
|
||||
defence can be found in my new ebook, which will soon be available for
|
||||
39€ on Amazon. But for my dear blog readers, I can offer 200 copies for
|
||||
free. So download your copy today! (3 copies left)
|
||||
|
||||
[https://home.codevoid.de/ebooks/promotion/about_spam.pdf](https://i.am.stealing.your.data.example.com/id/12345)
|
||||
|
||||
**Be safe and thanks for reading!**
|
||||
|
@ -1,14 +0,0 @@
|
||||
# Hello World!
|
||||
|
||||
This is a test page written im Markdown. It's quite easy to write `code` examples.
|
||||
It even has code blocks
|
||||
|
||||
```
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
printf("Hello World!\n");
|
||||
return 0;
|
||||
}
|
||||
```
|
@ -1,12 +0,0 @@
|
||||
#!/bin/ksh
|
||||
|
||||
echo "<h1>Hello World (shell version)</h1>"
|
||||
echo "This page is generated by a shell script."
|
||||
echo "<br><br>"
|
||||
echo "<b>Here's a tree:</b><br>"
|
||||
echo "<pre>"
|
||||
tree | while read line
|
||||
do
|
||||
echo "$line"
|
||||
done
|
||||
echo "</pre>"
|
@ -1,34 +0,0 @@
|
||||
= Hello World, adoc version!
|
||||
|
||||
Ahh, the full blown super duper asciidoctor with diagram support.
|
||||
|
||||
So, this:
|
||||
[source,graphviz]
|
||||
----
|
||||
[graphviz, "dot_example", "svg"]
|
||||
\----
|
||||
graph ethane {
|
||||
C_0 -- H_0 [type=s];
|
||||
C_0 -- H_1 [type=s];
|
||||
C_0 -- H_2 [type=s];
|
||||
C_0 -- C_1 [type=s];
|
||||
C_1 -- H_3 [type=s];
|
||||
C_1 -- H_4 [type=s];
|
||||
C_1 -- H_5 [type=s];
|
||||
\----
|
||||
----
|
||||
|
||||
Generates this:
|
||||
[graphviz, "dot_example", "svg"]
|
||||
----
|
||||
graph ethane {
|
||||
C_0 -- H_0 [type=s];
|
||||
C_0 -- H_1 [type=s];
|
||||
C_0 -- H_2 [type=s];
|
||||
C_0 -- C_1 [type=s];
|
||||
C_1 -- H_3 [type=s];
|
||||
C_1 -- H_4 [type=s];
|
||||
C_1 -- H_5 [type=s];
|
||||
}
|
||||
----
|
||||
|
Loading…
Reference in New Issue
Block a user