Skip to content

miconda/sipexer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sipexer

Modern and flexible SIP (RFC3261) command line tool.

Project URL:

Table Of Content

Overview

sipexer is a cli tool that facilitates sending SIP requests to servers. It uses a flexible template system to allow defining many parts of the SIP request via command line parameters. It has support for UDP, TCP, TLS and WebSocket transport protocols, being suitable to test modern WebRTC SIP servers.

sipexer is not a SIP cli softphone, but a tool for crafting SIP requests mainly for the purpose of testing SIP signaling routing or monitoring servers.

It is written in Go, aiming to be usable from Linux, MacOS or Windows.

The meaning of the name sipexer: randomly selected to be easy to write and pronounce, quickly after thought of it as the shortening of SIP EXEcutoR.

sipexer in action sending a SIP OPTIONS request:

SIP OPTIONS Request

Features

Among features:

  • send OPTIONS request (quick SIP ping to check if server is alive)
  • do registration and un-registration with customized expires value and contact URI
  • authentication with plain or HA1 passwords
  • set custom SIP headers
  • template system for building SIP requests
  • fields in the templates can be set via command line parameters or a JSON file
  • variables for setting field values (e.g., random number, data, time, environment variables, uuid, random string, ...)
  • simulate SIP calls at signaling layer (INVITE-wait-BYE)
  • option for late-offer SDP
  • respond to requests coming during SIP calls (e.g., OPTIONS keepalives)
  • send instant messages with SIP MESSAGE requests
  • color output mode for easier troubleshooting
  • support for many transport layers: IPv4 and IPv6, UDP, TCP, TLS and WebSocket (for WebRTC)
  • send SIP requests of any type (e.g., INFO, SUBSCRIBE, NOTIFY, ...)

Installation

Compile From Sources

First install Go. Once the Go environment is configured, clone sipexer git repository:

git clone https://github.com/miconda/sipexer

Download dependencies and build:

cd sipexer
go get ./...
go build .

The binary sipexer should be generated in the current directory.

Note: On some OS distributions, it may be required to run the go build command with CGO_ENABLED=0, like:

CGO_ENABLED=0 go build .

Download Binary Release

Binary releases for Linux, MacOS and Windows are available at:

Usage

Prototype:

sipexer [options] [target]

See sipexer -h for the command line options and arguments.

Defaults:

  • target address: sip:127.0.0.1:5060
  • SIP method: OPTIONS
  • From user: alice
  • From domain: localhost
  • To user: bob
  • To domain: localhost

Examples

Send an OPTIONS request over UDP to 127.0.0.1 and port 5060 - couple of variants:

sipexer
sipexer 127.0.0.1
sipexer 127.0.0.1 5060
sipexer udp 127.0.0.1 5060
sipexer udp:127.0.0.1:5060
sipexer sip:127.0.0.1:5060
sipexer "sip:127.0.0.1:5060;transport=udp"

Specify a different R-URI:

sipexer -ruri sip:[email protected] udp:127.0.0.1:5060

Send from UDP local port 55060:

sipexer -laddr 127.0.0.1:55060 udp:127.0.0.1:5060

Send REGISTER request with generated contact, expires as well as user and password authentication:

sipexer -register -cb -ex 600 -au alice -ap test123 udp:127.0.0.1:5060

Send REGISTER request with expires 60s, wait 20000ms (20s) and then unregister:

sipexer -register -vl 3 -co -com -ex 60 -fuser alice -cb -ap "abab..." -ha1 -sd -sw 20000 udp:127.0.0.1:5060

Set fuser field to carol:

sipexer -sd -fu "carol" udp:127.0.0.1:5060
# or 
sipexer -sd -fv "fuser:carol" udp:127.0.0.1:5060

Set fuser field to carol and tuser field to david, with R-URI user same as To-user when providing proxy address destination:

sipexer -sd -fu "carol"  -tu "david" -su udp:127.0.0.1:5060
# or
sipexer -sd -fv "fuser:carol"  -fv "tuser:david" -su udp:127.0.0.1:5060

Add extra headers:

sipexer -sd -xh "X-My-Key:abcdefgh" -xh "P-Info:xyzw" udp:127.0.0.1:5060

Send MESSAGE request with body:

sipexer -message -mb 'Hello!' -sd -su udp:127.0.0.1:5060

Send MESSAGE request with body over tcp:

sipexer -message -mb 'Hello!' -sd -su tcp:127.0.0.1:5060

Send MESSAGE request with body over tls:

sipexer -message -mb 'Hello!' -sd -su tls:127.0.0.1:5061

Send MESSAGE request with body over wss (WebSocket Secure):

sipexer -message -mb 'Hello!' -sd -su wss://server.com:8443/sip

Send INVITE request with default From user alice and To user bob:

sipexer -invite -vl 3 -co -com -sd -su udp:server.com:5060

Initiate a call from alice to bob, with user authentication providing the password in HA1 format, waiting 10000 milliseconds before sending the BYE, with higher verbosity level (3) and color printing:

sipexer -invite -vl 3 -co -com -fuser alice -tuser bob -cb -ap "4a4a4a4a4a..." -ha1 -sw 10000 -sd -su udp:server.com:5060

Target Address

The target address can be provided as last arguments to the sipexer command. It is optional, if not provided, then the SIP message is sent over UDP to 127.0.0.1 port 5060.

The format can be:

  • SIP URI (e.g., sip:[email protected]:5080;transport=tls)
  • SIP proxy socket address in format proto:host:port (e.g., tls:server.com:5061)
  • WSS URL (e.g., wss://server.com:8442/webrtc)
  • only the server hostname or IP (e.g., server.com)
  • host:port (transport protocol is set to UDP)
  • proto:host (port is set to 5060)
  • host port (transport protocol is set to UDP)
  • proto host (port is set to 5060)
  • proto host port (same as proto:host:port)

Message Template

Template Data

The message to be sent via the SIP connection is built from a template file and a fields file.

The template file can contain any any of the directives supported by Go package text/template - for more see:

Example:

{{.method}} {{.ruri}} SIP/2.0
Via: SIP/2.0/{{.viaproto}} {{.viaaddr}}{{.rport}};branch=z9hG4bKSG.{{.viabranch}}
From: {{if .fname}}"{{.fname}}" {{end}}<sip:{{if .fuser}}{{.fuser}}@{{end}}{{.fdomain}}>;tag={{.fromtag}}
To: {{if .tname}}"{{.tname}}" {{end}}<sip:{{if .tuser}}{{.tuser}}@{{end}}{{.tdomain}}>
Call-ID: {{.callid}}
CSeq: {{.cseqnum}} {{.method}}
{{if .subject}}Subject: {{.subject}}{{else}}$rmeol{{end}}
{{if .date}}Date: {{.date}}{{else}}$rmeol{{end}}
{{if .contacturi}}Contact: {{.contacturi}}{{if .contactparams}};{{.contactparams}}{{end}}{{else}}$rmeol{{end}}
{{if .expires}}Expires: {{.expires}}{{else}}$rmeol{{end}}
{{if .useragent}}User-Agent: {{.useragent}}{{else}}$rmeol{{end}}
Content-Length: 0

Example SDP body template:

v=0{{.cr}}
o={{.sdpuser}} {{.sdpsessid}} {{.sdpsessversion}} IN {{.sdpaf}} {{.localip}}{{.cr}}
s=call{{.cr}}
c=IN {{.sdpaf}} {{.localip}}{{.cr}}
t=0 0{{.cr}}
m=audio {{.sdprtpport}} RTP 0 8 101{{.cr}}
a=rtpmap:0 pcmu/8000{{.cr}}
a=rtpmap:8 pcma/8000{{.cr}}
a=rtpmap:101 telephone-event/8000{{.cr}}
a=sendrecv{{.cr}}

The internal templates can be found at the top of sipexer.go file:

Template Fields

The fields file has to contain a JSON document with the fields to be replaced in the template file. The path to the JSON file is provided via -ff or --fields-file parameters.

When the --fields-eval of -fe cli option is provided, sipexer evaluates the values of the fields in the root structure of the JSON document. That means special tokens (expressions) are replaced if the value of the field is a string matching one of the next:

  • "$cr" - replace with \r
  • "$dateansic" - replace with output of time.Now().Format(time.ANSIC)
  • "$datefull" - replace with output of time.Now().String()
  • "$daterfc1123" - replace with output of time.Now().Format(time.RFC1123)
  • "$dateunix" - replace with output of time.Now().Format(time.UnixDate)
  • "$env(name)" - replace with the value of the environment variable name
  • "$add(name)" - return the current value associate with name plus 1 (initial value is 0)
  • "$add(name,val)" - return the current value associate with name plus val (initial value is 0)
  • "$sub(name)" - return the current value associate with name minus 1 (initial value is 0)
  • "$sub(name,val)" - return the current value associate with name minus val (initial value is 0)
  • "$mul(name,val)" - return the current value associate with name multiplied with val (initial value is 1)
  • "$div(name,val)" - return the current value associate with name divided by val (initial value is 1)
  • "$dec(name)" - return the decremented value, first to return is 999999
  • "$dec(name,val)" - return the decremented value, first to return isval - 1
  • "$inc(name)" - return the incremented value, first to return is 1
  • "$inc(name,val)" - return the incremented value, first to return isval + 1
  • "$randseq" - replace with a random number from 1 to 1 000 000
  • "$rand(max)" - replace with a random number from 0 to max
  • "$rand(min,max)" - replace with a random number from min to max
  • "$randan(len)" - random alphanumeric string of length len
  • "$randan(minlen,maxlen)" - random alphanumeric string with length from minlen to maxlen
  • "$randhex(len)" - random hexadecimal string of length len
  • "$randhex(minlen,maxlen)" - random hexadecimal string with length from minlen to maxlen
  • "$randnum(len)" - random numeric string of length len
  • "$randnum(minlen,maxlen)" - random numeric string with length from minlen to maxlen
  • "$randstr(len)" - random alphabetic string of length len
  • "$randstr(minlen,maxlen)" - random alphabetic string with length from minlen to maxlen
  • "$rmeol" - remove next end of line character \n
  • "$timestamp" - replace with output of time.Now().Unix() - time stamp in seconds
  • "$timems" - replace with output of time.Now().UnixMilli() - time stamp in milliseconds
  • "$lf" - replace with \n
  • "$uuid" - replace with a UUID (universally unique identifier) value

When internal template is used, --fields-eval is turned on.

Example fields file:

{
	"method": "OPTIONS",
	"fuser": "alice",
	"fdomain": "localhost",
	"tuser": "bob",
	"tdomain": "localhost",
	"viabranch": "$uuid",
	"rport": ";rport",
	"fromtag": "$uuid",
	"totag": "",
	"callid": "$uuid",
	"cseqnum": "$randseq",
	"date": "$daterfc1123",
	"sdpuser": "sipexer",
	"sdpsessid": "$timestamp",
	"sdpsessversion": "$timestamp",
	"sdpaf": "IP4",
	"sdprtpport": "$rand(20000,40000)"
}

The internal fields data can be found at the top of sipexer.go file.

The values for fields can be also provided using --field-val or -fv cli parameter, in format name:value, for example:

sipexer --field-val="domain:openrcs.com" ...

The value provided via --field-val overwrites the value provided in the JSON fields file.

When sending out, before the template is evaluated, the following fields are also added internally and will replace the corresponding {{.name}} (e.g., {{.proto}}) in the template:

  • afver - address family version (4 or 6)
  • localaddr - local address - ip:port
  • localip - local ip
  • localport - local port
  • proto - lower(proto) (e.g., udp, tcp, ...)
  • protoup - upper(proto) (e.g., UDP, TCP, ...)
  • sdpaf - SDP address family (IP4 or IP6)
  • targetaddr - remote address - ip:port
  • targetip - remote ip
  • targetport - remote port
  • cr - \r
  • lf - \n
  • tab - \t

Alternatives

There are several alternatives that might be useful to consider:

  • sipp - SIP testing tool using XML-based scenarios
  • sipsak - SIP swiss army knife - SIP cli testing tool
  • wsctl - WebSocket cli tool with basic support for SIP
  • baresip - cli SIP softphone
  • pjsua - cli SIP softphone

License

GPLv3

Copyright: Daniel-Constantin Mierla (Asipto)

Contributions

Contributions are welcome!

Fork and do pull requests: