Evariste Workshop

Views
From Evariste Workshop
Jump to: navigation, search

Contents

Inward fax-to-email gateway with Asterisk, HylaFAX & IAXmodem

Note: The following tutorial is adapted from a post by Alex Balashov on our now-deprecated blog (which the Evariste Workshop is meant to replace) in December 2007, revised slightly in December 2008 for some content.

Introduction

I recently deployed Asterisk/IAXmodem/HylaFAX as a fairly high-volume fax-to-email gateway solution. In the process of so doing, I learned that there is a lot of good information out there -- in bits and pieces -- but not really a good, insightful tutorial to sum it all up conceptually to any degree of satisfying completeness, let alone up-front discussion of some theoretical and methodological questions, caveats, drawbacks and pitfalls that are useful in attempting a real-world deployment in a serious business environment.

It is my intent to provide something reaching in that direction here. I mean that in the most humble way possible; the open-source focused VoIP community could benefit from an involved synthesis of some of the relevant issues. By no means do I command the most comprehensive insights -- this is a new project for me, and that's why I'm eager to share what I've learned. Corrections, additions, questions and comments are absolutely welcome - please post comments or drop me a line!

This article does presume some familiarity with Asterisk and IP telephony on a technical level.

By the way, I have seen that packaged, integrated Asterisk GUI solutions such as Trixbox and FreePBX can take care of a lot of this for you automatically. If you like that, by all means, stick with it. Personally, I am one of those Asterisk enthusiasts that prefers the level of control and flexibility that comes with rolling one's own installation from scratch, writing the configuration manually, and so on. Ironically, I've found that it keeps things pretty simple. I've seen the immensely complicated and metadata-rich configs that FreePBX & co. put out; colour me several shades of not impressed. Too hard to figure out, modify, customise, or otherwise access the inner workings. But if you don't really want to roll your own solution, this article is probably not for you.

The Business Case / About Fax-to-Email

If you already know everything about your wants and needs in this area and are just looking for a tutorial on the technical nitty gritty, skip this section.

Believe it or not, much that goes in business these days still relies on analog facsmile technology, especially where signed paperwork, contracts, and financial documents bearing some measure of legally certifiable authenticity are required. If you are in business, chances are that you have a fax machine.

Fax-to-email functionality entails setting up an electronic interface that mimics the behaviour of a conventional fax machine in order to send and receive faxes from conventional fax machines. (If you are primarily receiving documents from electronic / digital sources, chances are you should be using e-mail or FTP for this.) The fax transmission is then converted to an electronic format (such as Adobe PDF) and automatically e-mailed as an attachment to the correct recipient.

This type of interface technology -- often known and branded as "electronic fax" or "e-fax" -- is about moving forward and embracing the migration to computer-based telephony1 while looking backward in acknowledgment that analog fax is likely to be around for some time yet. Until we come up with better, universal, integrated and legally/regulatorily viable ways of digitally "signing" documents at the very least, and possibly beyond that simply for reasons of lopsided technological development and acceptance, as part of the all-around division of labour in the so-called global economy.

If you are a provider of retail or wholesale end-subscriber telecommunications services, unified messaging, or play in the PSTN origination and termination space, etc. the reasons for why you may want to consider this option are fairly obvious, and in all likelyhood you already provide this service to your clients in some fashion.

For a consumer of these services, the question is almost entirely economic. You may already be a customer of one of the numerous services that pioneered this type of product some years ago, such as uReach or quite a few others. It is also a big hit with enhanced service providers participating in the "unified messaging" space (e-mail + voicemail + fax + anything else delivered to one messaging portal). If you have some type of "e-fax" service and are happy with it, the rule is the same as with other mission-critical services on which your business depends that are outside your core competency and competitive advantage: stick with it. It works well, does the job, and frees you from all the financial and technical headaches of figuring out and maintaining it yourself.

For my client, volume and ROI was the central element of this polemic. The company had a large number of employees with fax numbers, but only a small percentage of them routinely received faxes. However, the posture of the business model dictated that pretty much all of them needed to have fax numbers in principle. Also, the bulk of the employees were very low-ROI, specifically as far as that portion of their productivity that benefits from fax usage is concerned. Within the context of fax expenditures as such, marginal product of labour was incredibly, vastly lower than marginal cost. On top of that, the client had already deployed an Asterisk-based IP telephony system internally and had a large amount of PRI circuits with plenty of spare channel capacity that could be leveraged to bring fax services in-house and save money. The cost justification was clearly there.

Of course, you might benefit from this solution whether or not you share my client's particular cost structure and ROI dilemma. Surely you've seen what happens in, for example, a busy sales organisation when large crowds of employees assemble around a shared fax machine to wait for and collect their transmissions, whose sources are queuing behind a perenially "busy" fax line? You could be losing more than an hour a day of potential employee productivity on this waiting game, not to mention countless additional opportunities. With the right combination of technical capital, business need and fax volume, you may be better off not outsourcing your fax services, but even if you are, definitely invest in individual fax-to-email services one way or another! Keep your employees at their desks, your paper and toner costs low, and your faxes coming in quickly, expediently and simultaneously.

If fax is used in the course of your daily business operations to any significant degree whatsoever, you don't have time or money for the opportunity costs of doing things the old way.

The Concepts

In order to swing your own fax interface, you need more than just an analog telephony interface. You need something that can emulate a fax machine's DSP (Digital Signal Processor), which is essentially the same sort of DSP as in a modem. Some fax interface devices accomplish this in hardware DSP chips, the most obvious being a conventional fax machine. But it is also possible to emulate this functionality purely in software. That's the IAXmodem part of this equation. IAXmodem uses an open-source library called SpanDSP to perform its magic.

IAXmodem interfaces with Asterisk using IAX (Inter-Asterisk eXchange), a VoIP signaling and trunking protocol developed entirely in connection with Asterisk and primarily for the purpose of getting calls from one Asterisk PBX to another. It could have used SIP, or whatever -- it just happens to use IAX, and thus, by that virtue, also happens to require Asterisk to front it when interfacing with (decidedly non-IAX) PSTN call endpoints. I suppose if you have IAX trunking to a PSTN origination provider (which some offer) it is theoretically possible to use IAXmodem without Asterisk, but I wouldn't recommend it because IAXmodem by itself is pretty dumb, and does one thing. Plus, it has no measures to compensate for QoS issues such as jitter buffers for unevenly spaced media streams. From a call control standpoint, it is much wiser to pass calls through Asterisk.

IAXmodem itself is just a dumb DSP. To process and convert received fax data from whatever DSP source, you need actual fax software; that's HylaFAX.

A Quick Note about FoIP (Fax-over-IP)

You may have picked up on the fact that IAXmodem uses VoIP to provide the link between Asterisk and the actual modem DSP emulation component.

Much has been said and much has been made of the perils of running analog fax traffic encapsulated in a packetised form over an IP network, and not without reason. It generally doesn't work well. Fax terminals are extremely sensitive to the effects of delay and jitter on the encoded analog data; even slight packet loss or out-of-sequence errors in the IP leg of the transport can produce protocol errors that will cause a fax transmission to fail, or show up tragically garbled. The overall impact of the fundamental unreliability of IP -- especially over the Internet -- is much greater on fax traffic than it is on subjective perceptions of voice quality.

In order to get analog pass-thru on fax data to work, you need to use a clear-channel PCM codec whose accommodation of the analog spectrum equals the full extent of the 3.1 KHz analog bandwidth on standard analog voice lines. This means ITU-T G.711 with either μ-law (North American) or A-law (European) companding. But even then, it is generally impossible to run this traffic reliability over the Internet; too much data simply gets lost, or arrives in a manner inconsistent with the tight jitter requirements for successful pass-thru. This is the problem T.38 is intended to solve; it packetises fax data in ways more consistent with the way Internet applications usually transmit data, rather than attempting to graft high-throughput real-time voice data with extremely low packetisation durations onto an infrastructure whose QoS is not inherently designed to handle it well at present. Then, two T.30 (traditional analog fax) terminals can interface with each other over a more reliable data transport conduit that is entirely transparent to them.

Fortunately, moving fax data in an analog pass-thru format over a LAN -- not the greater Internet -- is generally reliable. It does depend on how your LAN is designed and what kind of contention exists on it. If you're moving a whole, whole lot of data across your LAN without any VoIP-oriented QoS precedence measures in place, it may still be problematic. But in general, it is possible. The IAXmodem FAQ has the following to offer:

Q1: IAX is VoIP. Isn't it bad to run fax over VoIP?
A1: Yes, generally it is. The conditions of jitter, packet loss, and other latency issues cause problems for reassembling VoIP audio streams on the receiver exactly as they were disassembled on the sender. However, these latency conditions can be controlled. For example, these conditions should not be present when communicating over the localhost address (127.0.0.1) in the case where the Asterisk server and the system running IAXmodem are the same. Other possible arrangements could be to use a dedicated network connection (e.g. a crossover cable) between the Asterisk server and the system running IAXmodem. IAXmodem should also be fine to run over a local area network (LAN) that is well-designed and controlled.
The basic point is this: if you can eliminate the mitigating factors of jitter and packet loss, then you can reliably use VoIP channels for faxing.

As this relates to the setup being discussed here, you do not have to move the fax data over an IP network at all if you don't want to. You can set up HylaFAX, IAXmodem and Asterisk on a server that has analog lines (PRI or POTS) running into it, and thus take the fax traffic in unmitigated analog form directly at the source.

The setup I deployed does decompose this assembly and frame it over an IP data plane: The client had PRIs running into Asterisk boxes with Sangoma T1 cards. These media gateways then forward the call via SIP (using G.711μ-law for the RTP) to an internal fax server on the LAN that runs Asterisk, IAXmodem and HylaFAX. Asterisk receives those calls and forwards them onto IAXmodem using IAX. This has not given us any problems. Just make sure that the you are using G.711; if you use G.729 or some other high-compression codec, the acoustic characteristics of the voice signal are mangled in ways that humans do not necessarily find objectionable, but faxes do, thus breaking the fax transmission entirely -- as it reconstructs digital data from analog sound data over a larger bandwidth and sample complexity than is necessary for subjectively acceptable human speech.

Also, do note that there is an analog interface to the PSTN somewhere on our LAN here. If you are getting your PSTN origination entirely via SIP handoff, your success may vary. If it is over the Internet, chances are it won't work at all. If you are colocated with a telco or have a dedicated point-to-point IP link to your provider, perhaps it will be okay; it just depends.

I do recommend that you run the Asterisk instance that terminates the fax calls and funnels them into IAXmodem on the same machine. But it is not strictly necessary; in fact, the reason we forward the calls via SIP internally is more for unrelated engineering reasons. We could have just as well set up IAXmodem on one machine, and had the modems register as IAX peers right on the media gateways, and I am confident it would have worked fine, especially with the jitter buffer enabled. If you have experiences to the contrary, feel free to share.

Note on DIDs

This type of setup is, much like VoIP products in general, very telephone number-intensive, but especially so because the direct fax number dialed is pretty much your only destination criterion for routing calls to particular users. Unless you plan to route faxes to particular users based on caller ID or some other common call data addressable from within HylaFAX, you're pretty much going to have order direct fax numbers for every user. Luckily, despite heavy numbering space utilisation, getting a block of DIDs for this purpose from your carrier is not particularly expensive.

The more important point is that you need to have a way to get faxes coming through the door to particular users' mailboxes, and the direct fax number dialed is the best way to do it. This ability to transmit the number dialed by the far end into the application is known in telco terminology as DNIS (Dialed Number Information Service), which has its roots in legacy terminology that covers making DID (Direct Inward Dial) work with business PBXs by transmitting the number dialed from the telco switch as a separate item of signaling data. (Think about it -- how else does a telephone endpoint receiving a call inherently "know" what number a user dialed to reach it? Traditional telephone switching was purely a matter of cross-connecting DS0 signals.)

Setting up Asterisk

I cannot give an exhaustive tutorial on every aspect of setting up Asterisk for this task. If you do not know how to use Asterisk, learn to use it first, and this article will serve you better. There are plenty of resources online and offline to get you started, plus a resourceful, helpful and abundant user community to answer your questions.

You need to get your fax-bound calls into an Asterisk instance using one of the methods mentioned above, or some other method. This will be our departure point. In my case, this is really simple; on our media gateways, we have a dial plan that forwards DID ranges associated we've chosen to allocate for fax to the internal fax server via SIP:

;;; Context for calls coming in from PSTN.

[from-pstn]

exten => 8885551212,1,Goto(from-pstn-fax,fax,1)

...

; Fax routing.

[from-pstn-fax]

exten => fax,1,Dial(SIP/${DNID}@Fax,15,r)
exten => fax,n,Busy()
exten => fax,n,Hangup()

Notice that we supply the ${DNID} (Dialed Number ID) as the extension to reach at the fax server SIP trunk ('Fax'). This is because we have a dedicated dial plan ruleset for fax, with an extension called 'fax', so if we sent ${EXTEN}, its value would be 'fax', which is not particularly useful to the fax server as it provides no DNIS. But we might as well have just done:

exten => 8885551212,1,Dial(SIP/${EXTEN}@Fax,15,r)

Purely a matter of style.

Because our fax server only accepts fax calls, we just accept any number inward in the dial plan there:


[from-sip-external]

exten => _.,1,Dial(IAX2/FaxDSP0/${EXTEN},15,r)
exten => _.,2,Dial(IAX2/FaxDSP1/${EXTEN},15,r)
exten => _.,3,Dial(IAX2/FaxDSP2/${EXTEN},15,r)
exten => _.,4,Dial(IAX2/FaxDSP3/${EXTEN},15,r)
exten => _.,5,Dial(IAX2/FaxDSP4/${EXTEN},15,r)
exten => _.,6,Dial(IAX2/FaxDSP5/${EXTEN},15,r)
exten => _.,7,Dial(IAX2/FaxDSP6/${EXTEN},15,r)
exten => _.,8,Dial(IAX2/FaxDSP7/${EXTEN},15,r)
exten => _.,9,Dial(IAX2/FaxDSP8/${EXTEN},15,r)
exten => _.,10,Dial(IAX2/FaxDSP9/${EXTEN},15,r)
exten => _.,11,Dial(IAX2/FaxDSP10/${EXTEN},15,r)
exten => _.,12,Dial(IAX2/FaxDSP11/${EXTEN},15,r)
exten => _.,13,Dial(IAX2/FaxDSP12/${EXTEN},15,r)
exten => _.,14,Dial(IAX2/FaxDSP13/${EXTEN},15,r)
exten => _.,15,Dial(IAX2/FaxDSP14/${EXTEN},15,r)
exten => _.,16,Dial(IAX2/FaxDSP15/${EXTEN},15,r)
exten => _.,17,Dial(IAX2/FaxDSP16/${EXTEN},15,r)
exten => _.,18,Dial(IAX2/FaxDSP17/${EXTEN},15,r)
exten => _.,19,Dial(IAX2/FaxDSP18/${EXTEN},15,r)
exten => _.,20,Dial(IAX2/FaxDSP19/${EXTEN},15,r)
exten => _.,n,Congestion()
exten => _.,n,Hangup

The 'FaxDSPX[X]' destinations are registered IAX peers provided by IAXmodem. We have twenty inward fax channels (distinct IAXmodem entities) configured separately. As you can see above, we just cycle through them like a rollover hunt group; if the first fax DSP is busy, we go on the next, and so on. Remember that the Dial() application returns the execution scope from the context if the call is successful and does not continue to execute subsequent priorities.

Setting up IAXmodem

Download IAXmodem and compile it, or install a package if your distribution supplies one. IAXmodem comes with the SpanDSP library.

Next, you need to decide how many "modems" you want to configure. We configured 20 in our case. Despite the high-volume fax environment, the need for more than five or so is not in evidence, but your oversubscription ratios may vary significantly. The considerations relevant to computing power and system dimensioning notwithstanding, I know of no theoretical limit to the amount of virtual IAXmodems one can configure, so if you expect to need three PRIs worth of capacity, have at it.

IAXmodems are defined in /etc/iaxmodem/ttyIAXy, where 'y' is the number of the serial device. They can start at 0 and are numbered upward, e.g. ttyIAX0 through ttyIAX20. The file is plain text and contains a stanza like so:

device /dev/ttyIAX0
owner uucp:uucp
mode 660
port 4570
refresh 60
server 66.1.1.1
peername FaxDSP0
secret FaxDSP0
cidname Evariste Systems
cidnumber 6789540670
codec ulaw

Each IAXmodem you configure creates a self-contained serial device (used by HylaFAX the same way a real serial port would be, by way of the same low-level serial I/O APIs) and a distinct registered IAX peer. This means that if you plan to have more than one IAXmodem, the IAX peers need to be registered from unique UDP ports in order to be uniquely reachable. So, if you define more than one ttyIAX, make sure to give them unique port numbers. I just started numbering mine one above the standard IAX port (4569) at 4570, 4571, 4572, and so on.

Also, the 'cidnumber' and others above are for outbound purposes and should not particularly concern you.

Now you need to create dedicated IAXmodem 'listeners' on each of these serial devices; this is what provides for something actually picking up when it gets a call. The listener daemons are started by running:

iaxmodem ttyIAXnn

The easiest way to ensure a listener is always running on each IAXmodem "port" is to put them in '/etc/inittab' as parts of a runlevel:

i0:2345:respawn:/usr/sbin/iaxmodem ttyIAX0
i1:2345:respawn:/usr/sbin/iaxmodem ttyIAX1
i2:2345:respawn:/usr/sbin/iaxmodem ttyIAX2
i3:2345:respawn:/usr/sbin/iaxmodem ttyIAX3
i4:2345:respawn:/usr/sbin/iaxmodem ttyIAX4
i5:2345:respawn:/usr/sbin/iaxmodem ttyIAX5
i6:2345:respawn:/usr/sbin/iaxmodem ttyIAX6
i7:2345:respawn:/usr/sbin/iaxmodem ttyIAX7
i8:2345:respawn:/usr/sbin/iaxmodem ttyIAX8
i9:2345:respawn:/usr/sbin/iaxmodem ttyIAX9
i10:2345:respawn:/usr/sbin/iaxmodem ttyIAX10
i11:2345:respawn:/usr/sbin/iaxmodem ttyIAX11
i12:2345:respawn:/usr/sbin/iaxmodem ttyIAX12
i13:2345:respawn:/usr/sbin/iaxmodem ttyIAX13
i14:2345:respawn:/usr/sbin/iaxmodem ttyIAX14
i15:2345:respawn:/usr/sbin/iaxmodem ttyIAX15
i16:2345:respawn:/usr/sbin/iaxmodem ttyIAX16
i17:2345:respawn:/usr/sbin/iaxmodem ttyIAX17
i18:2345:respawn:/usr/sbin/iaxmodem ttyIAX18
i19:2345:respawn:/usr/sbin/iaxmodem ttyIAX19

NOTE: Resist any temptation to give the process IDs names longer than three characters. When I had then named iax0, iax1, ... instead of ia0, ia1, ... not all of the iaxmodem processes would start. I am not sure why. Something with the way init(1) works, I suppose.

Restart init:

init q

The IAXmodem end of the setup is now complete. Remember that each IAXmodem listener is an IAX peer, and will try to register with Asterisk on the standard IAX port (4569). You will need to provide IAX peer definitions for each unique IAXmodem in '/etc/asterisk/iax.conf':

;;;
;;; IAX2 config for fax trunking to SpanDSP/IAXmodem/HylaFAX.
;;;

[general]

bindport = 4569       ; Port to bind to (IAX is 4569)
bindaddr = 0.0.0.0    ; Address to bind to (all addresses on machine)
disallow=all
allow=ulaw
allow=alaw
mailboxdetail=yes
iaxcompat=yes
jitterbuffer=yes


[FaxDSP0]

type=friend
username=FaxDSP0
secret=FaxDSP0
host=127.0.0.1
port=4570
disallow=all
allow=ulaw
qualify=yes

[FaxDSP1]

type=friend
username=FaxDSP1
secret=FaxDSP1
host=127.0.0.1
port=4571
disallow=all
allow=ulaw
qualify=yes

[ ... and so on ...]

You should now be able to dial into a fax DID and hear something resembling a modem pick up on the far end. If something seems amiss, verify that your dial plan is working correctly by running the Asterisk CLI and turning verbosity to high:

asterisk -r
set verbose 60

Then try dial a fax number, and see what transpires:

   -- Executing Dial("SIP/66.1.1.1-b77103a0", "IAX2/FaxDSP0/h|15|r") in new stack    -- Called FaxDSP0/h
   -- Call accepted by 127.0.0.1 (format ulaw)
   -- Format for call is ulaw
   -- IAX2/FaxDSP0-9 is ringing
   -- IAX2/FaxDSP0-9 answered SIP/10.2.2.68-b77103a0

If IAXmodem is not working correctly, you may see something like:

    -- Executing Dial("SIP/66.1.1.1-b77057f0", "IAX2/FaxDSP0/8885551212|15|r") in new stack
    -- Called FaxDSP0/8885551212    -- IAX2/FaxDSP0-62 is circuit-busy
    -- Hungup 'IAX2/FaxDSP0-62'
  == Everyone is busy/congested at this time (1:0/1/0)

You can debug by disabling the 'iaxmodem' spawning for the current runlevel in '/etc/inittab' temporarily and run 'iaxmodem' on the terminal manually against a particular IAXmodem port (the first one in your dial plan hunting scheme):

iaxmodem ttyIAX0

If you are not sure whether the IAX registration against Asterisk is completing successfully, you can connect to the Asterisk CLI:

asterisk -r

And issue the command 'iax2 show peers':

fax*CLI> iax2 show peers
Name/Username    Host                 Mask             Port          Status
FaxDSP19/FaxDSP  127.0.0.1       (S)  255.255.255.255  4589          OK (3 ms)
FaxDSP18/FaxDSP  127.0.0.1       (S)  255.255.255.255  4588          OK (3 ms)
FaxDSP17/FaxDSP  127.0.0.1       (S)  255.255.255.255  4587          OK (1 ms)
FaxDSP16/FaxDSP  127.0.0.1       (S)  255.255.255.255  4586          OK (3 ms)
FaxDSP15/FaxDSP  127.0.0.1       (S)  255.255.255.255  4585          OK (2 ms)
FaxDSP14/FaxDSP  127.0.0.1       (S)  255.255.255.255  4584          OK (1 ms)
FaxDSP13/FaxDSP  127.0.0.1       (S)  255.255.255.255  4583          OK (3 ms)
FaxDSP12/FaxDSP  127.0.0.1       (S)  255.255.255.255  4582          OK (3 ms)
FaxDSP11/FaxDSP  127.0.0.1       (S)  255.255.255.255  4581          OK (3 ms)
FaxDSP10/FaxDSP  127.0.0.1       (S)  255.255.255.255  4580          OK (3 ms)

If you're really stuck, try turning on IAX debugging:

iax2 debug

This can give some hints:

Rx-Frame Retry[ No] -- OSeqno: 000 ISeqno: 000 Type: IAX     Subclass: REGREQ   Timestamp: 00003ms  SCall: 06029  DCall: 00000 [10.2.2.63:4570]
USERNAME        : FaxDSP0
REFRESH         : 60

If you place a call in, you can also verify that an IAXmodem DSP picked up by doing:

fax*CLI> show channels
Channel              Location             State   Application(Data)IAX2/FaxDSP0-3       (None)               Up      Bridged Call(SIP/66.1.1.1-b77 SIP/10.2.2.68-b77057 8885551212@from-sip- Up      Dial(IAX2/FaxDSP0/8885551212|1
2 active channels
1 active call

Setting up HylaFAX

HylaFAX is a complicated software package that can do many different things entirely outside the scope of this tutorial. However, if you're just wanting to push out faxes from it via e-mail, it should be relatively simple, as the stock package comes with decent pre-built configurations for dialing rules and so on.

Install HylaFAX, either from source or from a package. Start the services to make sure they all work out of the box:

[root@fax ~]# /etc/init.d/hylafax start
Starting HylaFAX queue manager (faxq):                     [  OK  ]
Starting HylaFAX server (hfaxd):                           [  OK  ]
Restarting HylaFAX modem manager (faxgetty):               [  OK  ]

Next, you will need to put up HylaFAX's 'faxgetty' listeners on the IAXmodems. Back to '/etc/inittab/':

m0:2345:respawn:/usr/sbin/faxgetty ttyIAX0
m1:2345:respawn:/usr/sbin/faxgetty ttyIAX1
m2:2345:respawn:/usr/sbin/faxgetty ttyIAX2
m3:2345:respawn:/usr/sbin/faxgetty ttyIAX3
m4:2345:respawn:/usr/sbin/faxgetty ttyIAX4
m5:2345:respawn:/usr/sbin/faxgetty ttyIAX5
m6:2345:respawn:/usr/sbin/faxgetty ttyIAX6
m7:2345:respawn:/usr/sbin/faxgetty ttyIAX7
m8:2345:respawn:/usr/sbin/faxgetty ttyIAX8
m0:2345:respawn:/usr/sbin/faxgetty ttyIAX9
m10:2345:respawn:/usr/sbin/faxgetty ttyIAX10
m11:2345:respawn:/usr/sbin/faxgetty ttyIAX11
m12:2345:respawn:/usr/sbin/faxgetty ttyIAX12
m13:2345:respawn:/usr/sbin/faxgetty ttyIAX13
m14:2345:respawn:/usr/sbin/faxgetty ttyIAX14
m15:2345:respawn:/usr/sbin/faxgetty ttyIAX15
m16:2345:respawn:/usr/sbin/faxgetty ttyIAX16
m17:2345:respawn:/usr/sbin/faxgetty ttyIAX17
m18:2345:respawn:/usr/sbin/faxgetty ttyIAX18
m19:2345:respawn:/usr/sbin/faxgetty ttyIAX19

Restart init:

init q

Verify that faxgetty is in fact running:

[root@fax ~]# ps aux | grep faxgetty
uucp     21847  0.0  0.0  5400 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX15
uucp     21848  0.0  0.0  5696 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX7
uucp     21851  0.0  0.0  4472 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX6
uucp     21852  0.0  0.0  6076 1636 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX5
uucp     21853  0.0  0.0  5792 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX16
uucp     21854  0.0  0.0  6360 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX3
uucp     21855  0.0  0.0  5368 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX17
uucp     21856  0.0  0.0  5024 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX2
uucp     21857  0.0  0.0  6236 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX18
uucp     21858  0.0  0.0  4480 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX14
uucp     21859  0.0  0.0  5376 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX1
uucp     21860  0.0  0.0  6288 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX4
uucp     21861  0.0  0.0  4736 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX19
uucp     21862  0.0  0.0  4712 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX0
uucp     21863  0.0  0.0  5664 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX13
uucp     21864  0.0  0.0  5804 1636 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX11
uucp     21865  0.0  0.0  5176 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX12
uucp     21866  0.0  0.0  6268 1636 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX8
uucp     21867  0.0  0.0  5728 1632 ?        Ss   18:54   0:00 /usr/sbin/faxgetty ttyIAX10
root     21874  0.0  0.0  4492  648 pts/3    S+   18:56   0:00 grep faxgetty

There are only two things you should need to modify. One is the inward fax distribution script. It's called 'FaxDispatch'. Where it lives is somewhat installation/distribution-dependent. On our CentOS fax server, it is in '/var/spool/hylafax/etc/'.

This is a bash shell script at heart, and controls HylaFAX's behaviour by setting two environment variables:

SENDTO - The e-mail address to which the output should be e-mailed.
FILETYPE - The format of the attachment (for instance, 'pdf')
# By default, e-mail unroutable faxes to the secretary.

SENDTO=secretary@faxes-receivable.evaristesys.com;

# In PDF format.

FILETYPE=pdf;

This script is passed numerous environment variables by HylaFAX (which invokes it internally) as well. Some of these ($SENDER, $CIDNUMBER, etc.) are mentioned in the comments in the stock file that is distributed with the package. However, if you are planning on routing by DNIS, you should know that the dialed number is passed to HylaFAX in this particular setup as $CALLID4. Not $CALLID, but $CALLID4. See the man page for faxrcvd(1) if you care.

Most information out there entreats you do something like this:

case "$CALLID4" in
        8885551212)
                 # All toll-free faxes.                 
                 SENDTO=bob@evaristesys.com;
                 FILETYPE=pdf;;
        *)

                # All others.
                SENDTO=employee@evaristesys.com;
                FILETYPE=pdf;;
esac

But remember that this is a shell script, so you can build all sorts of outboard logic into it. In our case, we have a script that dips the employee database and automatically figures out which e-mail address to route the fax to:

DEST_EMAIL=$(/usr/bin/perl /usr/local/fax_route_dip/fax_route_dip.pl $CALLID4)

echo "Routing to: $DEST_EMAIL ($CALLID4)" >> /tmp/hylafax_routing.dbg.out

if [ $DEST_EMAIL == "NIL" ];
then
        SENDTO=Faxmaster@evaristesys.com;
        FILETYPE=pdf
else
        SENDTO=$DEST_EMAIL
        FILETYPE=pdf
fi

You also need to create configuration files in the same 'etc' directory for every IAXmodem listener that contain basic fax and modem-related configuration parameters. For the most part, these are fairly unimportant, but they need to be there. The files are called 'config.ttyIAXnn', e.g. config.ttyIAX0:

[root@fax etc]# more config.ttyIAX0
CountryCode:		1
AreaCode:		800
FAXNumber:		+1.800.555.1212
LongDistancePrefix:	1
InternationalPrefix:	011
DialStringRules:	etc/dialrules
ServerTracing:		0xFFF
SessionTracing:		0xFFF
RecvFileMode:		0600
LogFileMode:		0600
DeviceMode:		0600
RingsBeforeAnswer:	1
SpeakerVolume:		off
GettyArgs:		"-h %l dx_%s"
LocalIdentifier:	"IAXmodem0"
TagLineFont:		etc/lutRS18.pcf
TagLineFormat:		"From %%l|%c|Page %%P of %%T"
MaxRecvPages:		200

#
#
# Modem-related stuff: should reflect modem command interface
# and hardware connection/cabling (e.g. flow control).
#

ModemType:      	Class1		# use this to supply a hint#

# Enabling this will use the hfaxd-protocol to set Caller*ID
#

#ModemSetOriginCmd:	AT+VSID="%s","%d"
#
# If "glare" during initialization becomes a problem then take
# the modem off-hook during initialization, and then place it
# back on-hook when done.
#

#ModemResetCmds:	"ATH1nAT+VCID=1"	# enables CallID display
#ModemReadyCmds:	ATH0
Class1AdaptRecvCmd:	AT+FAR=1
Class1TMConnectDelay:	400		# counteract quick CONNECT response

#
# If you have trouble with V.17 receiving or sending,
# you may want to enable one of these, respectively.
#
#Class1RMQueryCmd:      "!24,48,72,96"  # enable this to disable V.17 receiving
#Class1TMQueryCmd:      "!24,48,72,96"  # enable this to disable V.17 sending
#

# You'll likely want Caller*ID display (also displays DID) enabled.
#

ModemResetCmds:		AT+VCID=1	# enables CallID display

#
# The pty does not support changing parity.
#

PagerTTYParity:		none

#
# If you are "missing" Caller*ID data on some calls (but not all)
# and if you do not have adequate glare protection you may want to
# not answer based on RINGs, but rather enable the CallIDAnswerLength
# for NDID, disable AT+VCID=1 and do this:

#
#RingsBeforeAnswer: 0
#ModemRingResponse: AT+VRID=1

# Uncomment DATE and TIME if you really want them, but you probably don't.

#CallIDPattern:          "DATE="
#CallIDPattern:          "TIME="
CallIDPattern:          "NMBR="
CallIDPattern:          "NAME="
CallIDPattern:		"ANID="
#CallIDPattern:          "USER="	# username provided by call
#CallIDPattern:          "PASS="	# password provided by call
#CallIDPattern:          "CDID="	# DID context in call
CallIDPattern:          "NDID="
#CallIDAnswerLength:	4

And that's pretty much it. Now restart HylaFAX:

/etc/init.d/hylafax restart

And that should be all there is to it.

Of course, you will need to make sure you have a properly configured MTA (Mail Transfer Agent) running on the local server that can relay this mail outbound.

Happy trails!

NOTE: As of release 1.4, Asterisk has patches for native fax applications based on SpanDSP. If they work well, they should allow you to take IAXmodem and HylaFAX out of the equation. Also check out astfax for the e-mail integration portion. However, I've been told anecdotally by a number of Asterisk users that they do not work well and that the HylaFAX approach remains the most robust and stable.

Personal tools
  • Inward fax-to-email gateway with Asterisk, HylaFAX & IAXmodem