PfSense supports only outbound traffic shapping so you can’t shape multiple LAN/VLAN interfaces without putting another PfSense box in front of it. The only way to shape it is to use only one physical interface LAN and tag other VLANS on that interface. You need to select only WAN and LAN interface for traffic shaping. All traffic that will pass from VLANs will go trough LAN interface where QOS traffic shaper will catch it. If you don’t do it via only one interface, traffic shaping will work, but the VLAN to VLAN traffic will be limited to the speed of a WAN download bandwidth.

For start, you can use traffic shaping wizard and modify rules after.

Go to:

Firewall -> Traffic Shaper -> Wizards -> Multiple LAN/WAN

Select one WAN connection and one LAN connection:

For interface select LAN and WAN, scheduler should be HFSC (you can choose another one if you like, but this post is about HFSC setup).

Define your WAN upload and download speed and continue wizzard till the end and save.

Go to:

Firewall -> Traffic shaper

Click on LAN and set bandwidth to your physical interface speed.

Set qLink bandwidth percentage to: ((LAN bandwidth – WAN download bandwidth) / 10)

Example:

My LAN bandwidth = 1000 Mbit

My WAN download banwidth = 200 Mbit

(1000 – 200) / 10 = 80%

The sum of parent trees has to be 100%

Save.

All you have to do now is add two more floating rules. Rules added by the wizzard are good enough to get an idea how it works. You can later add custom ports, depends on what you need.

Go to:

Firewall -> Rules -> Floating

We will add a rule to catch all traffic that does not fall under defined floating rules created by the wizzard. We will put all not defined traffic to qOtherLow queue. The important thing is to have rules added at the top of the floating rules and not at the bottom.

 

Add rule 1:

Match, interface: WAN, direction: any, protocol: TCP, source: any, destination: any, destination port range: from any to any

Advanced options: Ackqueue / Queue: qACK / qOtherLow

 

Add rule 2: 

Match, interface: WAN, direction: any, protocol: UDP, source: any, destination: any, destination port range: from any to any

Advanced options: Ackqueue / Queue: none / qOtherLow

The two created rules have to be at the top:

Basic traffic shaping should work now. It’s up to you know to fine tune the rules. Check the status of traffic shaper at Status -> Queues

qLink queue is VLAN <-> VLAN traffic while all the queues bellow +/-qInternet are VLAN <-> WAN traffic

Downsides of this setup:

  • You are limited to only one physical interface for VLAN traffic meaning your VLAN to VLAN bandwidth can suffer with multiple heavy users on a local network (like transferring a lot of files from local servers to local clients). You could probably solve that with LAN bridges but I don’t know how a QOS would behave in that case.
  • You can’t run squid proxy service because download traffic on port 80 and 443 will bypass traffic shaper (it can probably be done with some tweaking but I haven’t tested it yet).

This is useful when you can’t use peer to peer (site to site) tunnel. For example, when you don’t have administrative access to a remote network (you can’t open ports, you can only go out – egress). To bypass this and gain access to remote network devices, you can simply install a VPN client on the remote network and make it act as a gateway for your local network. I will not go trough basic OpenVPN server configuration (generating certs, adding users etc), I will only pinpoint the parts that differ from a normal VPN client server setup.

Example:

Remote network: 192.168.10.0/24 (Client side)

Local network: 192.168.1.0/24 (Server side)

1. Go to OpenVPN server settings, under advanced configuration, custom options and enter:

 push "route 192.168.1.0 255.255.255.0";

route 192.168.10.0 255.255.255.0; 

2. Go to OpenVPN client specific overrides tab and add a new rule. Select your OpenVPN server, enter common name (name of the user – VPN client), under IPv4 remote network/s enter: 192.168.10.0/24

3. If you haven’t already, you have to assign an interface to your VPN server. Go to Interfaces, Assignments, Available network ports: ovpns1, click Add and save. Click on your newly created interface, check box Enable interface and add a description: OpenVPN1 (name it however you want), save.

4. Go to System, routing, static routes.

Add a new route, destination network: 192.168.10.0/24

Gateway: OpenVPN1

5. You need to enable NAT and forwarding on a client, this example is for a linux client:

 sysctl -w net.ipv4.ip_forward=1

iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

iptables -t nat -A POSTROUTING -o tun0 -j MASQUERADE 

6. Connect your VPN client, you should be able to access devices behind the client from your local network.

I couldn’t find any manuals or schematics online about this exact board so I had to figure out where to plug the HDD LED activity light on the board. It’ should be written on the motherboard like the other front panel items (power led, turbo led, turbo switch, reset) but that wasn’t the case. HDD IDE LED pins are located at the top of the motherboard (J6 and J4 pins).

Model number of the board:

To connect via RTSP:

rtsp://camera_username:camera_password@IP:rtsp_port/live/ch00_1

Example:

rtsp://admin:admin123@192.168.30.102:554/live/ch00_1

If you are filtering outgoing connections, allow this outgoing ports to camera:

554 TCP

6970-6990 UDP

You can test RTSP stream with VLC media player.

Possible bug: When you connect to the camera with your phone, disconnect from it and then try to open rtsp stream in VLC media player, it will only load the first frame and stuck there. You need to reboot the camera, connect to rtsp with VLC media player without accessing it via mobile device.

Extra note: It’s advisable to block outgoing traffic from camera into internet. My camera is connecting to some IP with weird ports.

Quick whois showed me this IP belongs to alibaba.com. I did not sniff the traffic, so I’m not sure if the nature of it is spyware. It’s probably their cloud service or some other service.

For the extra paranoid, physically disconnect the microphone on the camera:

TL;DR:

Xerox phaser 3020 black ink percentage remaining – SNMP cacti data and graph template at the bottom of this post.

 

With some tweaks this method should also works for other brand printers.

With the help of this article: https://thwack.solarwinds.com/docs/DOC-171511 I could set up a cacti template for my Xerox 3020 printer. Some printers return ink level value in percents but in my case I got only the raw value.

1. Get SNMP toner max capacity value, OID for that is 1.3.6.1.2.1.43.11.1.1.8.1.1

root@cacti: snmpget -v2c -c public 192.168.0.251 1.3.6.1.2.1.43.11.1.1.8.1.1
SNMPv2-SMI::mib-2.43.11.1.1.8.1.1 = INTEGER: 700

700 is the raw value for 100% toner capacity.

2. Get SNMP toner current levels value, OID for that is 1.3.6.1.2.1.43.11.1.1.9.1.1

root@cacti: snmpget -v2c -c public 192.168.0.251 1.3.6.1.2.1.43.11.1.1.9.1.1
SNMPv2-SMI::mib-2.43.11.1.1.9.1.1 = INTEGER: 686

686 is the current raw value of my toner levels. To calculate toner ink percentage remaining we need to divide current raw value (686) with max raw value (700) and multiply it by 100. 686 / 700 * 100 = 98 (percentage of ink remaining). Since the max raw value is a nice number (700), we can just divide current raw value with 7, 686/7 = 98. We can use this formula for our CDEF definitions in cacti later. Remember, this is only for Xerox 3020, other brand printers can output different raw values and you need to correct this formula accordingly.

Xerox 3020 ink remaining percentage formula: raw_current_ink_level / 7

3. Login to cacti and go to Console -> Presets -> CDEFs

Click plus sign and create new CDEF and name it Xerox toner percentage

Click plus at CDEF Items.

CDEF Item Type: Special Data Source

CDEF Item Value: Current Graph Item Data Source

Click Save

Click plus at CDEF Items.

CDEF Item Type: Custom String

CDEF Item Value: 7 (this is the value cacti will use to divide raw data)

Click Save

Click plus at CDEF Items.

CDEF Item Type: Operator

CDEF Item Value: / (this will tell cacti to use a divide operation with the custom string we defined in a previous step).

Click Save

4. Go to Console -> Templates -> Data Source

Click plus to create new data source template and name it Printer – black toner current

Name: |host_description| – black toner current

Data Input Method: Get SNMP Data

Data Source Active: tick the right box

Internal Data Source Name: toner_current

Click Create

New Custom Data field will appear.

OID: 1.3.6.1.2.1.43.11.1.1.9.1.1

Click Save

5.1 Go to Console -> Templates -> Graph

Click plus sign

Name: Printer – black toner levels

Title: Printer – black toner levels

Vertical Label: percent

Tick Rigid Boundaries Mode

Upper Limit: 100

Click Create

5.2 Now click plus sign at Graph Template Items

Graph Item Type: AREA

Data Source: Printer – black toner current

Color: select what you like

Consolidation Function: AVERAGE

CDEF Function: Xerox toner percentage

Text Format: Available

Click save

Add another Graph template item

Graph Item Type: GPRINT

Data Source: Printer – black toner current

Consolidation Function: LAST

CDEF Function: Xerox toner percentage

GPRINT Type: Percent(Round down to the nearest decimal)

Text format: Current:

Click Save

Add another Graph template item

Graph Item Type: LINE1

Data Source: Printer – black toner current

Consolidation function: AVERAGE

CDEF function: Xeror toner percentage

Save

Your graph is now ready to device assignment.

Final result:

Download data and graph templates for xerox phaser 3020:

xerox_3020_cacti_toner_level_template [Dropbox mirror]

 

 

1. Update system and optionally disable X Desktop, we don’t need GUI

apt-get update
apt-get upgrade
raspi-config

Select menu: 3, B1, B1

2. Install dependencies

apt-get install subversion libsigc++-2.0-dev g++ make libsigc++-1.2-dev libgsm1-dev screen \
libpopt-dev tcl8.5-dev libgcrypt-dev libspeex-dev libasound2-dev alsa-utils install qt-sdk git groff -y

3. Add a new user

adduser svxlink

4. Download svxlink source

cd /usr/src; wget https://github.com/sm0svx/svxlink/archive/15.11.tar.gz; tar xvf 15.11.tar.gz; cd svxlink-15.11/src; mkdir build; cd build

5. Compile and install svxlink

cmake -DCMAKE_INSTALL_PREFIX=/usr -DSYSCONF_INSTALL_DIR=/etc \
        -DLOCAL_STATE_DIR=/var ..
make
make doc
make install
ldconfig

6. Install sounds

cd /usr/share/svxlink/sounds; wget https://github.com/sm0svx/svxlink-sounds-en_US-heather/releases/download/14.08/svxlink-sounds-en_US-heather-16k-13.12.tar.bz2
tar xvf svxlink-sounds-en_US-heather-16k-13.12.tar.bz2
mv en_US-heather-16k en_US; rm -rf svxlink-sounds-en_US-heather-16k-13.12.tar.bz2

7. Configure sound levels

alsamixer

Press F6 and select usb soundcard.
Press F5 to show all.
Increase gain on CAPTURE, around 80 is fine, experiment otherwise.
Exit alsamixer and save the settings with:

alsactl store

8. Tweak configuration files in /etc/svxlink/svxlink.conf and /etc/svxlink/svxlink.d/ModuleEchoLink.conf

svxlink.conf: I will show you only modified lines

Uncomment LOCATION_INFO=locationInfo to show your Echolink on aprs.fi map.
MODULES=ModuleEcholink
CALLSIGN=Yoursign-L
SHORT_IDENT_INTERVAL=0
LONG_IDENT_INTERVAL=0

Under [Rx1]

AUDIO_DEV=alsa:plughw:1 #Hardware ID of the soundcard, usually 1 on rpi with usb soundcard
SQL_START_DELAY=100 #Prevent TX, RX loop
VOX_THRESH=500 #Increase if your VOX gets falsly opened

Under [Tx1]:

AUDIO_DEV=alsa:plughw:1
PTT_TYPE=SerialPin
PTT_PORT=/dev/ttyUSB0 #Depends what you have for PTT triggering, I do it with RS232 to USB converter

Under [LocationInfo]
#This is mostly self explanatory

APRS_SERVER_LIST=poland.aprs2.net:14580
STATUS_SERVER_LIST=aprs.echolink.org:5199
#Go to maps.google.com, select your location, right click, what's here
#and you'll get coordinates, for example: 45.660325, 14.291537 Go to https://rechneronline.de/winkel/degrees-minutes-seconds.php
#and convert from decimal degrees provided from maps.google.com to degrees, arc minutes, arc seconds.
#Enter converted
#coordinates.

LON_POSITION=14.17.29E
LAT_POSITION=45.39.37N
CALLSIGN=EL-yourcallsign
FREQUENCY=145.275
TX_POWER=5
ANTENNA_GAIN=0
ANTENNA_HEIGHT=5m
ANTENNA_DIR=-1
PATH=WIDE1-1
BEACON_INTERVAL=10
TONE=123
COMMENT=SvxLink by SM0SVX (svxlink.sourceforge.net)

ModuleEcholink.conf:

ALLOW_IP=192.168.0.0/24 #Depends on your home network setup,
#it could be also ALLOW_IP=192.168.1.0/24
SERVERS=europe.echolink.org
CALLSIGN=yoursign-L
PASSWORD=your echolink password
SYSOPNAME=yourname
LOCATION=[Svx] comment about your echolink
LINK_IDLE_TIMEOUT=0
AUTOCON_ECHOLINK_ID=ID of the remote repeater for example AUTOCON_ECHOLINK_ID=609569
AUTOCON_TIME=1200
DESCRIPTION=edit text to fit your needs
reboot

9. Run svxlink

svxlink

Try to transmit, usb soundcards on rpi are tricky. You will probably get a warning:
Rx1: Distorsion detected! Please lower the input volume!
Don’t worry about it.
Exit and run svxlink as daemon

svxlink --daemon

10. Start svxlink at boot
You need to wait some time after boot for Pi to initialize devices.
It will not work when you start svxlink immediately after the boot,
the process will run but there will be no access to PTT. Open
/etc/rc.local and add this two lines at the end of the file, before exit 0

sleep 120
/bin/bash -c '/usr/bin/svxlink --pidfile=/var/run/svxlink.pid --daemon'

This will start svxlink 2 minutes after boot.

#!/bin/bash

# Rtsp to youtube streaming with ffmpeg

VBR="1000k" # Bitrate of the output video, bandwidth 1000k = 1Mbit/s
QUAL="ultrafast" # Encoding speed
YOUTUBE_URL="rtmp://a.rtmp.youtube.com/live2" # RTMP youtube URL
THREADS="0" # Number of cores, insert 0 for ffmpeg to autoselect, more threads = more FPS

CAMUSER="user"
CAMPASS="password"
CAMIP="192.168.0.2"
CAMPORT="88"
VIDEOCHANNEL="videoSub" # videoMain and VideoSub for Foscam cameras

SOURCE="rtsp://${CAMUSER}:${CAMPASS}@${CAMIP}:${CAMPORT}/${VIDEOCHANNEL}" # Camera source
KEY="xxx-xxxx-xxxx-xxxx" # Youtube account key

# To download fonts
# wget -O /usr/local/share/fonts/open-sans.zip "https://www.fontsquirrel.com/fonts/download/open-sans";unzip open-sans.zip
FONT="/usr/local/share/fonts/OpenSans-Regular.ttf"
FONTSIZE="15"

# Text allingment
x="5"
y="60"

# Other
box="1" # enable box
boxcolor="black@0.5" # box background color with transparency factor
textfile="ffmpeg.txt"
reloadtext="1" # Reload textfile after each frame, usefull for overlaying changing data 
# like weather info. To update the textfile while streaming, you need to use mv command or a crash
# is going to happen when you update the textfile.
# Example:
# wget -q https://something.com/ -O - | grep somevalue > ffmpegraw.txt; mv ffmpegraw.txt ffmpeg.txt
boxborderwidth="5"

# Ffmpeg with drawtext, 
    ffmpeg -loglevel panic \
    -f lavfi -i anullsrc \
    -rtsp_transport tcp \
    -i "$SOURCE" \
    -vcodec libx264 -pix_fmt yuv420p -preset $QUAL -g 20 -b:v $VBR \
    -vf "drawtext="fontfile=${FONT}":textfile=${textfile}:x=${x}:y=${y}:reload=${reloadtext}: \
    fontcolor=white:fontsize=${FONTSIZE}:box=${box}:boxborderw=${boxborderwidth}:boxcolor=${boxcolor}" \
    -threads $THREADS -bufsize 512k \
    -f flv "$YOUTUBE_URL/$KEY"

# Copy stream only, don't encode
#ffmpeg \
#    -f lavfi -i anullsrc \
#    -rtsp_transport tcp \
#    -i "$SOURCE" \
#    -vcodec libx264 -pix_fmt yuv420p -preset $QUAL -g 20 -c:v copy -b:v $VBR \
#    -f flv "$YOUTUBE_URL/$KEY"

Overlayed data over webcam stream example:

To run the script in background you need to add nohup otherwise ffmpeg will hang.

nohup bash this_script.sh &

Ffmpeg likes to crash from time to time. Create a script to check for ffmpeg process and restart it if there is no process running.

#!/bin/bash
#
# Description: Checks for existing ffmpeg process and starts one if needed
#
script=/path/to/first_script.sh

if ! pgrep -x "ffmpeg" > /dev/null
then
    /bin/bash $script > /dev/null 2>&1 &
fi

Save script as check_ffmpeg.sh

chmod +x check_ffmpeg.sh

Run the script with crontab every minute.

crontab -e
* * * * * sudo bash /path_to_script/check_ffmpeg.sh

#!/bin/sh

# Get APRS weather data from aprs.fi

wxstation="S55MA-10"

# Basic weather data
temp="$(wget -q https://aprs.fi/weather/a/${wxstation} -O - | grep Temperature | egrep '[-+]?([0-9]*\.[0-9]+|[0-9]+)' -o)"
humidity="$(wget -q https://aprs.fi/weather/a/${wxstation} -O - | grep Humidity | egrep '[-+]?([0-9]*\.[0-9]+|[0-9]+)' -o)"
wind="$(wget -q https://aprs.fi/weather/a/${wxstation} -O - | grep Wind | egrep '[-+]?([0-9]*\.[0-9]+|[0-9]+)' -o | sed -n -e 2p)"
rain="$(wget -q https://aprs.fi/weather/a/${wxstation} -O - | grep Rain | egrep '[-+]?([0-9]*\.[0-9]+|[0-9]+)' -o | sed -n -e 1p)"

# Telemetry
radioactivity="$(wget -q https://aprs.fi/telemetry/a/${wxstation} -O - | grep Radioactivity | egrep '[-+]?([0-9]*\.[0-9]+|[0-9]+)' -o | sed -n -e 5p)"

printf "%s\n" "Temperature: ${temp}°C" "Humidity: ${humidity}%" "Wind: ${wind} m/s" "Rain: ${rain} mm/h" "Radioactivity: ${radioactivity} uSv/h"

1. Make sure .well-known and acme-challenge directories are set permissions to 755

2. Create random file test.txt in .well-known/acme-challenge/ and try to view it with browser

If all of this is good, your certificate should renew. The problem I had on my server is that even when step 1. and 2. were ok and working, I still  got permission denied message. The problem was I setup my Varnish engine to force SSL on non SSL request. When bot requested http://somedomain.com/.well-known/acme-challenge/ it was automatically redirected to https://somedomain.com/.well-known/acme-challenge/. So,

3. Make sure you disable force SSL during renewal.

Error message example:

Failed authorization procedure. s55ma.radioamater.si (http-01): urn:acme:error:unauthorized :: The client lacks sufficient authorization :: Invalid response from http://s55ma.radioamater.si/.well-known/acme-challenge/i825k_Mk8YGTTD1GOsZvMCkZ0KaRFdext04LfQdelQs: "<!DOCTYPE html>
<html>
<head>
<title>403 Forbidden</title>
</head>
<body>
<h1>Error 403 Forbidden</h1>
<p>Forb"

Enable server ports on Xastir. We need to use the command line binary xastir_udp_client which is part of Xastir. To send the data over RF, you need to have Xastir configured with your transmitter already.

More info about the mail APRS service: http://www.aprs-is.net/email.aspx

The basic string is:

xastir_udp_client XastirIP port callsing passcode -to_rf 'callsign>APRS::EMAIL    :EmailOfReceiver@something.com message'

Real example:

xastir_udp_client 192.168.0.140 2023 S55MA-10 22222 -to_rf 'S55MA-10>APRS::EMAIL    :s55ma@radioamater.si hello'

Note: You may only send one line messages of 64 total characters maximum for the message even though the documentation is saying 67. You have to put 4 white spaces between EMAIL and EmailOfReceiver, so the total lenght of EMAIL+white spaces is 9 characters.

This post is about Xastir, but on the side note, most APRS capable handhelds stations are not able of sending email messages through APRS. One portable station that’s able to do it is Kenwood TH-D72. I found this post about it. Too bad other portables are not able to do that where this feature is the most usefull, I mean, it’s not like I’m going to need aprs to email service from my home station, I’d likely need it outdoors for emergency situations or to send an email when I’m abroad and without cellular data service.

Quick script for sending messages:

#!/bin/bash

#APRS to Email script using Xastir
#Define variables
#Xastir server and port
server=192.168.0.140
port=2023

#Authentication info
user=S55MA
passcode=22222

echo "Enter sender (yours or some others callsign)"
read sender
sendercapital="$(echo $sender | awk '{print toupper($0)}')"

echo "Enter destination email:"
read email

echo "Enter your message (max 64 characters):"
read message

#Count message characters
msglenght="$(echo $message | wc -c)"

#Restart script if message exceeds 64 characters.
if [ "$msglenght" -gt 64 ]; then
echo "Your message exceeded 64 characters, try again!"
exec bash "$0"
else
xastir_udp_client $server $port $user $passcode -to_rf "$sendercapital>APRS::EMAIL    :$email $message" >/dev/null 2>&1
echo "Message has been sent."
fi