Linux Fax Stack using Hylafax and t38modem
Find a file
2024-08-12 12:58:08 +00:00
README.md Update README.md 2024-08-12 12:58:08 +00:00

Linux Fax Stack Setup (HylaFax & SIP)

Linux Fax Stack using Hylafax and t38modem.

THIS GUIDE IS WIP

This guide was created using information from the opalvoid wiki (http://wiki.opalvoip.org/index.php?n=Main.HomePage)

Software stack

ptlib

(legacy) library for doing a little bit of everything.

Opal

Voice codec used by e.g. mumble.

t38modem

Emulates a serial modem from SIP connection

HylaFax

Enterprise grade software, managing physical and emulated modems.

Has some problems: https://github.com/lexbailey/compilerfax/blob/main/hylafax_is_broken

Operating Systems

Unfortunately this software stack uses a lot of legacy software. Because of this, this guide was only tested on specific software versions

Debian 12 Bookworm

For Debian 12, we'll only install dependencies which are hard requirements. For this guide we'll use ptlib 2.18.6 and opal 3.18.6.

Installing Requirements

First we'll need some packages

apt-get install build-essential git wget pkg-config libssl-dev libsrtp2-dev libspandsp-dev -y

Download sourcecode

Versions:

ptlib

./configure
make
make install

opal

./configure
make -j5
make runtest
make install

t38modem

If you are getting an error about -1 not being able to be casted to a long unsigned int due to -Wnarrowing inside dle.cxx, you can add -Wno-narrowing after the CPPFLAGS in the Makefile to disable this error

git clone https://github.com/hehol/t38modem
cd t38modem
make

If running the t38modem executable, you should run these commands

cp /usr/local/lib/libpt.so.2.18.6 /lib
cp /usr/local/lib/libopal.so.3.18.6 /lib

To install t38modem run

cp ./t38modem /usr/local/bin

Ubuntu 20.04 LTS

Was tested on Ubuntu 20.04 LTS VM (VirtualBox, LXC?)

You can relies heavily on http://wiki.opalvoip.org/index.php?n=Main.HomePage

Versions:

Follow http://wiki.opalvoip.org/index.php?n=Main.BuildingPTLibUnix and http://wiki.opalvoip.org/index.php?n=Main.HomePage but

  • Don't use libavformat-dev -> Compile error in Opal
  • Configure script needs pkg-config to be installed to find ptlib install
  • On SourceForge downloads .tar.bz2 files for *nix

Build PTLib

sudo apt install \
	g++ git make autoconf libpcap-dev libexpat1-dev libssl-dev libsasl2-dev libldap2-dev \
	unixodbc-dev liblua5.3-dev libv8-dev libncurses-dev libsdl2-dev \
	libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev pkg-config
  • PTLib will be installed in the /usr/local tree -> set PKG_CONFIG_PATH to be findable (compile time)
  • Set LD_LIBRARY_PATH to find PTLib at compile and run time
  • Set PTLIBPLUGINDIR (compile and run time)
  • (To compile as static library: ./configure --disable-shared)
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig # compile time
export LD_LIBRARY_PATH=/usr/local/lib # compile and run time
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z # compile and run time
 
cd ptlib-x.y.z/
./configure
make
sudo make install

Build Opal

sudo apt install \
	libsrtp2-dev libgsm1-dev libspeex-dev libopus-dev libx264-dev \
	libvpx-dev libtheora-dev libspandsp-dev dahdi
  • (To compile as static library: ./configure --disable-shared)
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig # compile time
export LD_LIBRARY_PATH=/usr/local/lib # compile and run time
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-x.y.z:/usr/local/lib/opal-a.b.c # compile and run time

cd opal-a.b.c/
./configure
make
sudo make install

t38modem

  • https://github.com/hehol/t38modem, Version 4.6.2
  • If you are getting error about -1 not being able to be casted to a long unsigned int due to -Wnarrowing inside dle.cxx, you can add -Wno-narrowing after the CPPFLAGS in the Makefile to disable this error
cd t38modem-x.y.z/
make
sudo cp ./t38modem /usr/local/bin
  • t38modem can only find Opal if LD_LIBRARY_PATH and PTLIBPLUGINDIR are environment variables to the program

Configuring t38modem

Init script

First we'll create the configuration directory under /etc using sudo mkdir -p /etc/t38modem/bin/.

Then create a file named /etc/t38modem/bin/run using the following content. It will be the script to manage the current status of t38modem.

#!/bin/bash
# /etc/t38modem/bin/run

export LD_LIBRARY_PATH=/usr/local/lib
export PTLIBPLUGINDIR=/usr/local/lib/ptlib-2.18.6:/usr/local/lib/opal-3.18.6 # Adjust lib versions!

if [ -z "${1}" ]; then
	>&2 echo "Config file path not set! Aborting..."
	exit 1
fi

. "${1}"

command="t38modem --ptty +/dev/ttyT38-${T38MODEM_PTTY_ID} --sip-proxy ${T38MODEM_SIP_USERNAME}:${T38MODEM_SIP_PASSWORD}@${T38MODEM_SIP_SERVER} --sip-register ${T38MODEM_SIP_USERNAME}@${T38MODEM_SIP_SERVER},${T38MODEM_SIP_PASSWORD} --sip-listen udp\$:5060 --stun ${T38MODEM_STUN_SERVER} --route t38:.*=sip:<dn>@${T38MODEM_SIP_SERVER} --route sip:.*=t38:<dn>"

if [ "$T38MODEM_DISABLE_T38" = true ]; then
	command="${command} --disable-t38-mode --audio"
fi

exec $command

And then we'll have to make it executable like this.

sudo chmod +x /etc/t38modem/bin/run

Quick script overview

  • Using this script, it is possible to start t38modem with a config file as an argument
  • -t enables debugging
    • More t's is deeper debugging (e.g. -tttt)
  • If t38modem says it was able to create the virtual modem but /dev/ttyT38-1 is not available, you do not have sufficient permissions
  • Configuration is specified in /etc/t38modem/config/XX

Create the configuration file

Create a file using the following contents at /etc/t38modem/config/XX.

# /etc/t38modem/config
T38MODEM_PTTY_ID="XX" # /dev/ttyT38-XX
T38MODEM_SIP_USERNAME="USERNAME"
T38MODEM_SIP_PASSWORD="PASSWORD"
T38MODEM_SIP_SERVER="voip.example.com"
T38MODEM_STUN_SERVER="stun.example.com:1234"
T38MODEM_DISABLE_T38=false # enable if your SIP server prefers G.711

You should give only root access to the config.

sudo chown root:root -R /etc/t38modem/config/
sudo chmod 700 -R /etc/t38modem/config/

Testing your setup

  • You can now communicate with your modem /dev/ttyT38-XX, just as if it was a real Hayes compatible modem (https://www.computerhope.com/atcom.htm)
  • Test using minicom, configure it to point to our modem. Each command is initiated by a Return
    • Dial a number:
      • Get the attention of the modem: at -> OK
      • Dial: atd[NUMBER], replace '[NUMBER]' using the number, you want to call
      • If all works correctly you should be able to answer the phone and hear a single beep
    • Answer a call:
      • Get the attention of the modem: at -> OK
      • Call the number of your modem
      • -> RING
      • Answer the call: ata -> CONNECT
      • You should now hear your modem "talking" to you
  • Pitfalls:
    • If you are already connected to your SIP server it may not give proper response codes. My provider returns 500 Internal Server Error
    • Test the command before running the init script!
    • Do not try to used ATO to switch to a data connection, t38modem will return ERROR. Thats hardcoded in pmodeme.cxx in void ModemEngineBody::HandleCmdRest(PString &resp). Dont let that hodld you back.

systemd service

If you want to run a fax server, you can create a systemd service template to let your emulated fax modem start automatically on system boot. To do this you have to copy paste the following into /etc/systemd/system/t38modem@.service.

# /etc/systemd/system/t38modem@.service
[Unit]
Description=t38modem
After=network-online.target
Wants=network-online.target
AssertPathExists=/etc/t38modem/config/%i

[Service]
Type=simple
Restart=always
ExecStart=/etc/t38modem/bin/run /etc/t38modem/config/%i

[Install]
WantedBy=multi-user.target

Enable and start the service for your config file (/etc/t38modem/config/XX) using the following commands:

sudo systemctl daemon-reload
sudo systemctl enable t38modem@XX.service
sudo systemctl start t38modem@XX.service

Install HylaFax

These instructions were tested using Hylafax version 6

  • sudo apt install hylafax-server
    • Set Postfix Configuration to Local only in dpkg-reconfigure menu

Configure HylaFax

  • Run sudo faxsetup

    • Add new modem
    • Enter correct modem port (ttyT38-XX)
    • Enter dialing configuration (see Dial Rules for Eventphone EPVPN)
    • Accept default configuration for everything else
    • It should automatically detect it to be a T38FAX modem
  • Look at man sendfax to send faxes

  • fgetty (the service to receive faxes) should be enabled automatically

  • Bugs:

    • If you get some protocol errors, just let HylaFax do its thing. Fax over SIP is not stable at all in my experience
    • If your call is cleared because it Could not find common media capabilities t38modem may not have been able to load PTLib or Opal. Check your library paths!

Cron

  • Alias your fax admin account as FaxMaster (/etc/aliases)
# /etc/aliases
# [...]
# HylaFax
FaxMaster: $USER # replace with fax admin account
  • Add standard tasks to crontab file: crontab -e
0       *       *       *       *       /usr/sbin/faxqclean
25      23      *       *       *       sh /usr/sbin/faxcron | mail FaxMaster

Dial Rules for Eventphone EPVPN

If you want to use Eventhone EPVPN, you can apply the following dial settings onto your modems. You can find the config at /etc/hylafax/config.ttyT38-1. In this case ttyT38-1 is the modem block device.

# /etc/hylafax/config.ttyXX
CountryCode:	1
AreaCode:		999

FaxDispatch

TODO

  • TODO: Test on Debian / RockPi / RaspberryPi
  • TODO: Test on Eventphone Infra
  • TODO: Package t38modem with service files and config