SSL support for Asterisk Manager Interface ------------------------------------------------ 2006-03-27 Mahesh Karoshi Remco Treffkorn John Todd OVERVIEW -------- The Asterisk Manager Interface (AMI) has to this point operated in clear-text mode, meaning that connections to port 5038 have been without encryption. The mostly-undocumented "Challenge" action provides some security for password exchange via an MD5 hash (see bottom of this document) but it does not encrypt the actual contents of the AMI exchange between client and server, which is almost as critical as the login information itself. The reasons for why one would want encyrption are outside the scope of this document, and are assumed to be self-evident. The SSL additions to Asterisk provide an SSL wrapper around the AMI, permitting client applications to utilize SSL to encrypt their sessions. Programs like stunnel can utilize this new encryption layer transparently to client applications, or client-side programmers can incorporate the OpenSSL (or other libraries) directly into their programs to utilize the SSL encryption as an integral part of their apps. THEORY ------ An SSL-capable Asterisk server should "just work" as it did before. The "make install" process will automatically generate a server certificate, self-sign it, and install it into the correct directory (default of /var/lib/asterisk/certs) if there is no cert there already. If there is a cert, Asterisk will use it and not overwrite with a self-signed version. You can specify a pre-existing cert, or build one yourself if you wish - this new patch will not step on existing certs if they exist in the specified directory. When a client connects to the AMI port, Asterisk will wait a predetermined number of milliseconds (specified in manager.conf with the "sslclienthellotimeout=" value) and wait for an SSL Client "Hello" sequence, which indicates that the remote client has SSL capabilities. If the timer expires, and "acceptunencryptedconnection=yes" in the manager.conf file, then the standard AMI greeting will be given in an unencrypted fashion, to allow legacy applications to work without requiring new ports or other problematic conversion methods. INSTALLATION ------------ There are no special tricks to installation or activation, as long as "make install" has been run from the main Asterisk source directory. The following lines will need to be added to the manager.conf configuration file (typically in /etc/asterisk) for correct operation if you are upgrading an existing Asterisk installation: certdir = /var/lib/asterisk/certs/server.pem sslclienthellotimeout = 500 acceptencryptedconnection = yes acceptunencryptedconnection = yes FILES ----- /etc/asterisk/ssl.conf = the SSL conf file that Asterisk will use. For experts only. /var/lib/asterisk/certs/server.pem = the self-signed cert that Asterisk builds for itself, if none exists ${SRC-DIR}/client_ssl.c = a stand-alone sample for a client-side application (for developer prototpying) HINTS ----- 1) Turning off SSL: To turn off SSL support, comment out or delete the "-DAMI_WITH_SSL" portion of this line in the Makefile in the main source directory of Asterisk, and re-build: ASTCFLAGS+=-pipe -Wall -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(DEBUG) (INCLUDE) -D_REENTRANT -D_GNU_SOURCE #-DAMI_WITH_SSL #-DMAKE_VALGRIND_HAPPY 2) Testing with stunnel: The secured AMI can be tested using the stunnel client -- you need to add the /etc/stunnel/stunnel.conf file. The content of stunnel.conf is as follows: client = yes debug = 7 foreground = yes [asterisk] accept = 127.0.0.1:5111 connect = asteriskhost:port Now, run stunnel to activate the tunneled forwarding configs. For example: shell#> sudo stunnel To connect to the remote host, type: shell#> telnet localhost 5111 You should receive: Asterisk Call Manager/1.0 Type: Action: Login Username: xyz Secret: xyzz Hit Enter twice. You should see: Response: Success Message: Authentication accepted 3) Making a customized cert: To re-build your certificate with some data that is specific to your site such as company name or email addresses, edit the /etc/asterisk/ssl.conf file and modify the contents of the file to match your requirements. Then, in the Asterisk source directory, type "make certificate". Overwrite the old certificate with the new certificate. Remember, this is only used if the client application which is connecting to your server is "remembering" or expecting cert information of a specific type. Creating a more correct but still unsigned cert is probably not very useful; if you want "real" cert data, you will need to get your cert signed by a real CA, and that is beyond the scope of this document. 4) Building the client_ssl.c program: To compile the client_ssl demonstration application, use this command line: shell#> g++ -I/usr/kerberos/include -lssl -o client_ssl client_ssl.c Then, to test: shell#> ./client_ssl 127.0.0.1 5038 managerusername managerpassword 4) Using the "Challenge" method to exchange passwords. While the SSL encryption of the AMI is great, it's always a good policy to never send passwords at all if you have an alternative. The AMI has a built-in method for this, which is not part of the SSL patch set but deserves to be included somewhere in the /doc directory, so here is as good a place as any. After connecting to the AMI port, send this message: Action: Challenge AuthType: MD5 You should receive a challenge string: Response: Success Challenge: 125065091 Then, assuming that the manager username is "joebob" and the password is "yoyodyne11", perform this on a shell line of a handy UNIX system (you programmers will figure out how to do this with a library call, I'm sure): bash-3.00# md5 -s 125065091yoyodyne11 MD5 ("125065091yoyodyne11") = e83a9e59e7c8d1bb6554982275d05016 bash-3.00# Now use this key to log in, so type this to the AMI: Action: Login AuthType: MD5 Username: joebob Key: e83a9e59e7c8d1bb6554982275d05016 ...and you'll get: Response: Success Message: Authentication accepted --- END ---