IPTables untuk Asterisk Based IP PBX

Sampai saat ini masih ada rekan-rekan sysadmin yang memasang IP PBX (terutama Asterisk based) dengan menggunakan ip public langsung. Dan agak mengkhawatirkan lagi IP PBX tersebut tersambung ke jaringan telepon umum. Beberapa kali muncul kasus kebobolan yang menyebabkan mereka diharuskan membayar penggunaan telepon mencapai puluhan bahkan ratusan juta. Ada banyak alasan kenapa rekan-rekan masih harus memasang ip public langsung ke IP PBX, di antaranya karena topology dan alokasi ip address yang tidak memungkinkan DMZ, permasalahan VoIP jika harus dilewatkan NAT/port forward, dan lain sebagainya. Terlepas dari hal tersebut, sangat disarankan untuk melindungi IP PBX sebaik mungkin termasuk meletakannya di dalam IP PBX. Jika memang terpaksa harus meletakkan nya dengan ip public, maka berikut template IPTables yang bisa digunakan untuk mengurangi resiko kebobolan (tapi mohon diingat, cara ini bukan obat manjur untuk menahan penetrasi):

#!/bin/bash
# cwd=/etc/sysconfig/
#

#VARS
EXTIF="eth0"
INTIF="eth1"

# flush all existing rules and chains
iptables -F
iptables -X

# allow inbound ssh connection on external/public interface
iptables -A INPUT -p tcp --dport 22 --sport 1024:65535 -m state --state NEW,ESTABLISHED -j ACCEPT

# set default policies (allow any outbound, block inbound, restrict forwarding between interfaces)
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Allow TCP 80 and 443 
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Allow RTP traffic
iptables -A INPUT -p udp --dport 10000:20000 -j ACCEPT

# Allow SIP traffic
iptables -A INPUT -p tcp --dport 5060 -j ACCEPT
iptables -A INPUT -p udp --dport 5060 -j ACCEPT

# allow all inbound traffic coming in on loopback and the internal/private interfaces
#iptables -A INPUT -i $INTIF -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT

# allow your home / office ip
iptables -A INPUT -i $INTIF -s XXX.XXX.XXX.XXX/XX -j ACCEPT
iptables -A INPUT -i $INTIF -s XXX.XXX.XXX.XXX/XX -j ACCEPT

# allow inbound traffic for established connections on external/public interface
iptables -A INPUT -i $EXTIF -m state --state ESTABLISHED,RELATED -j ACCEPT

# block packets coming in with invalid source ips
iptables -A INPUT -i $EXTIF -s 10.0.0.0/8 -j DROP
iptables -A INPUT -i $EXTIF -s 172.16.0.0/12 -j DROP
iptables -A INPUT -i $EXTIF -s 192.168.0.0/16 -j DROP
iptables -A INPUT -i $EXTIF -s 224.0.0.0/4 -j DROP
iptables -A INPUT -i $EXTIF -s 240.0.0.0/5 -j DROP
iptables -A INPUT -i $EXTIF -s 0.0.0.0/8 -j DROP
iptables -A INPUT -i $EXTIF -s 169.254.0.0/16 -j DROP
iptables -A INPUT -i $EXTIF -s 127.0.0.0/8 -j DROP

# ICMP
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 1/sec -j ACCEPT

# SYN flood limiter
iptables -A INPUT -p tcp --syn -m limit --limit 5/s -j ACCEPT

# catch-all for end of rules
# LOG and DENY other traffic to help identify additional filters required
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level debug
iptables -A INPUT -j REJECT --reject-with icmp-host-prohibited

# Save settings
#
# On CentOS / Fedora this will output the current IPTables to the stdout, which we can pipe to a file that sets these on boot
iptables-save > /etc/sysconfig/iptables
#
# List rules
#
iptables -L -v

Edit file tersebut sesuai dengan kondisi server masing-masing. Di sini saya mengasumsikan menggunakan dua interface. Berikut ini beberapa hal yang bisa ditambahkan untuk mengurangi resiko kebobolan

  • Gunakan dua interface LAN. Satu interface terpasang ip public dan interface lain terpasang ip address private untuk ke LAN. Biasanya saya hanya memperbolehkan Web GUI, dan SSH hanya bisa diakses dari LAN. Jika saya sedang tidak berada satu lokasi dengan server tersebut, saya mengaksesnya melalui VPN yang tersambung ke jaringan LAN.
  • set PermitRootLogin=no untuk ssh, dan buat akun shell tambahan yang dimasukkan list sudo supaya bisa melakukan aktifitas administrasi server.
  • Ubah port ssh dan web UI ke port lain yang hanya kita ketahui (misal 8241, 9231, dst), dan tetap difilter dengan IPTables.
  • Menambahkan setting httpd.conf misal:

<Directory>

 

... Deny from all

Allow from 1.2.3.4

Allow from 6.7.8.0/24

Allow from 192.168.1.0/24

Allow from 10.0.0.0/24

Allow from 172.16.0.0/24

...

 

</Directory>

  • Bila perlu, block MySQL dari semua interface kecuali interface loopback/localhost.
  • Menambahkan fail2ban lebih bagus lagi.

Intinya, jadilan super paranoid jika berurusan dengan IP PBX terlebih yang tersambung ke jaringan telepon umum.

Mencoba ENUM dari E164.ID Di Elastix

Bagi yang belum paham betul apa itu ENUM (E164 Number Mapping), bisa mencari informasinya di link berikut ini:

Intinya E164.ID ini menjadi direktori nomer telepon dan bisa menjadi penghubung  semua pengelola VoIP server yang ingin bergabung membentuk komunitas VoIP. Untuk mendapatkan blok nomer telepon ini, bisa didapatkan dengan mendaftar di TELEPONRAKYAT.ID. Di web tersebut kita bisa mendaftar sebagai Gateway (jika kita memiliki VoIP server sendiri), atau cukup mendaftarkan domain/realm saja (jika kita tidak memiliki/mengelola VoIP server sendiri). Sedangkan untuk diskusi lebih lanjut mengenai E164.ID ini bisa bergabung di forum ASTERISK.ID .

Oh ya, sebelum kita berpikir bahwa blok nomer yang kita dapatkan dengan mendaftar di TELEPONRAKYAT.ID bisa berkomunikasi dengan nomer telepon regular, perlu disampaikan bahwa E164.ID belum melakukan interkoneksi ke jaringan telepon PSTN maupun PLMN. Untuk pengguna VoIPRakyat sudah bisa menikmati panggilan dengan menggunakan nomer E164.ID. Bagi yang mau coba, bisa kontak nomer demo +62520291901 (time announcement), +62520291902 (monkey), atau di +62520291903 (echo test).

Mendaftar di TELEPONRAKYAT.ID

Sebelum melanjutkan setup, kita terlebih dahulu harus mendaftar ke TELEPONRAKYAT.ID untuk mendapatkan nomer telpon/prefix dari E164.ID. Untuk cara mendaftar silahkan baca dengan mendownload file .pdf di sini. Dengan asumsi bahwa kita sudah memiliki server Elastix, maka daftar di bagian Manage Gateway. Di sini kita akan mendapatkan alokasi prefix nomer, contoh, prefix nomer yang saya dapatkan adalah +62520-364. Setelah mendaftar, tunggu sekitar 15 menit untuk bisa melakukan lookup di E164.ID. Caranya adalah dengan menjalankan perintah berikut di shell  prompt linux:

$ dig +short *.4.6.3.0.2.5.2.6.e164.id NAPTR

jika semua berjalan lancar maka outputnya seperti :

10 1 "u" "E2U+sip" "!^\\+?(.*)$!sip:\\1@sip.domain.tld!" .

Argument untuk dig di atas diambil dari digit prefix yang kita dapat, lalu hilangkan tanda ‘+’, setelah itu urutan dibalik dari depan ke belakang, dengan masing-masing digit dipisah tanda titik. Pada ujung sebelah kiri adalah wildcard (asterisk), artinya berapapun nomer berikutnya, asalkan prefixnya adalah alokasi prefix tersebut. Untuk keterangan hasil dig, digit pertama (10) adalah priority, lalu digit berikutnya adalah weight (1), baris berikutnya adalah protokol yang digunakan yaitu UDP (untuk U), dan SIP. Sedangkan yang terkakhir adalah format URI yang didapatkan dengan regular expression.

Elastix Setup

Berhubung saya setiap hari menggunakan Elastix maka contoh setup  berikut ini menggunakan distro tersebut. Karena distro tersebut pada dasarnya menggunakan FreePBX, maka setupnya tidak banyak  berbeda bila menggunakan distro FreePBX, AsteriskNow, trixbox, Briker, dkk. Stepnya adalah sebagai berikut:

  • Dari baris Tab di menu utama, pilih tanda panah paling kanan untuk memunculkan menu dropdown, lalu pilih Security -> Advanced Settings lalu aktifkan slide button untuk Enable anonymous SIP calls. 001002
  • Selanjut pilih menu PBX -> PBX Configuration -> Trunks -> Add ENUM Trunk. Beri nama Trunk di bagian Trunk Name, misal E164.ID,  lalu klik Submit Change.003
  • Pilih menu PBX -> PBX Configuration -> Outbound Routes -> Add Route. Di bagian Route Name, isikan nama untuk route ini, misal Outbound_ENUM, lalu isikan dial patterns seperti berikut:004
  • jangan lupa di bagian Trunk Sequence for Matched Routes pilih E164.ID (sesuai nama trunk yang sudah kita buat sebelumnya), dan klik Submit Changes.
  • Sebelum melanjutkan menambahkan Inbound Routes, ada baiknya kita melakukan edit file /etc/enum.conf. Saya lebih suka menghapus semua isi file tersebut dan cukup diisi dengan  :
search => e164.id
  • Lalu edit file /var/lib/asterisk/agi-bin/enumlookup.agi :
$ sudo chmod a+w /var/lib/asterisk/agi-bin/enumlookup.agi
$ sudo vi /var/lib/asterisk/agi-bin/enumlookup.agi

di bagian baris:

$enums = Array('e164.org','e164.arpa','e164.info');

menjadi:

$enums = Array('e164.id');

setelah menyimpan perubahan, jangan lupa mengembalikan mode file supaya tidak ditimpa ulang oleh system:

$ sudo chmod a-w /var/lib/asterisk/agi-bin/enumlookup.agi
  • Selanjutnya kita perlu menambahkan realm ke Elastix. Realm adalah nama domain gateway yang kita daftarkan ke TELEPONRAKYAT.ID. Sebagai awalan, ada baiknya jika nama realm sesuai dengan FQDN (contoh sip.domain.tld) server Elastix. Karena jika realm tidak sama dengan FQDN server, misal domain.tld, maka kita perlu menambahkan entry SRV ke DNS. Secara default, realm Elastix adalah “asterisk”. Untuk menggantinya, masuk ke menu PBX -> Tools -> Asterisk File Editor, lalu edit file sip_general_custom.conf dan tambahkan baris:
realm=sip.domain.tld

Klik Save lalu klik Reload Asterisk.

  • Buat satu extensi (misal 1001). Lalu registrasi melalui SIP phone (cara menambahkan extensi tidak akan dibahas di sini).
  • Pilih menu PBX -> Inbound Routes -> Add Incoming Route. Misal kita ingin mengalokasikan nomer +6252036411001 untuk bisa diterima di ext. 1001, isikan Description dengan (bebas) +6252036411001, lalu DID Number dengan pattern match: _.52036411001 (pattern ini akan sesuai dengan +62520364110016252036411001, atau 006252036411001). Dan terakhir di bagian Set Destination pilih Extensions dan 1001.
  • Test call (di contoh ini saya coba test call dari nomer VoIP Rakyat) misal tidak ada kendala akan seperti ini:005Screenshot_2016-01-23-03-40-04
  • Setup firewall supaya server VoIP/IP PBX tetap aman. Contoh setup firewall bias dibaca di sini .

[Kazoo] Problem Pergantian RabbitMQ Server

Karena sesuatu hal, saya harus mengubah topologi Kazoo, terutama server RabbitMQ yang menggunakan ip public menjadi ip private. Dan ternyata penggantian tersebut tidak mudah. Setelah dijalankan, WhistleApps masih mencari server AMQP lama, dan karena server tersebut sudah tidak ada, maka muncul error econnrefused seperti di bawah ini:

Jan 4 17:35:05 portal 2600hz[1211]: |00000000000|wh_amqp_connection:320 (<0.2180.0>) failed to connect to ‘amqp://guest:guest@1.2.3.4:5672’ will retry: econnrefused
Jan 4 17:35:06 portal 2600hz[1211]: |00000000000|wh_amqp_connection:320 (<0.2180.0>) failed to connect to ‘amqp://guest:guest@1.2.3.4:5672’ will retry: econnrefused
Jan 4 17:35:07 portal 2600hz[1211]: |00000000000|wh_amqp_connection:320 (<0.2180.0>) failed to connect to ‘amqp://guest:guest@1.2.3.4:5672’ will retry: econnrefused
Jan 4 17:35:08 portal 2600hz[1211]: |00000000000|wh_amqp_connection:320 (<0.2180.0>) failed to connect to ‘amqp://guest:guest@1.2.3.4:5672’ will retry: econnrefused
Jan 4 17:35:09 portal 2600hz[1211]: |00000000000|wh_amqp_connection:320 (<0.2180.0>) failed to connect to ‘amqp://guest:guest@1.2.3.4:5672’ will retry: econnrefused
Jan 4 17:35:10 portal 2600hz[1211]: |00000000000|wh_amqp_connection:320 (<0.2180.0>) failed to connect to ‘amqp://guest:guest@1.2.3.4:5672’ will retry: econnrefused

Untuk mengatasi hal ini, maka broker harus dihilangkan secara manual dengan perintah:

root# sup whistle_amqp_maintenance remove_broker “amqp://guest:guest@1.2.3.4:5672”

Lalu tambahkan broker baru, misal:

root# sup whistle_amqp_maintenance add_connection “amqp://guest:guest@6.7.8.9:5672”

Dengan langkah tersebut, seharusnya broker sudah terarah ke server yang baru.

4 Januari 2016, 23:17

“We leave something of ourselves behind, only leave a place, we stay there even though we go away. And there are things in us that we can find again only by going back there. We travel to ourselves when we go to a place though we have covered a stretch of our life, no matter how brief it may have been. But by traveling to ourselves we must confront our own loneliness. And isn’t it so everything we do is done out of fear of loneliness? Isn’t that why we renounce all the things we will regret at the end of our lives?”

(Amadeu Del Almeida Prado, Night Train To Lisbon, 2013)

2016

Tidak terasa sudah tanggal 1 Januari lagi. Setiap kali memulai tahun baru, banyak sekali rencana di kepala yang bermunculan dan kemudian setelah berbulan-bulan, ternyata yang tersulit adalah bagian eksekusi. Ada beberapa hal yang menjadi penghambat pewujudan keinginan, tapi yangt terbesar adalah hambatan dari diri sendiri. Jadi resolusi tahun ini saya pikir tidak perlu muluk-muluk yang berisi sekian baris item. Kali ini cukup satu hal saja yang menjadi tantangan tahun ini: mengalahkan diri sendiri.

Mengalahkan di sini adalah pengikisan ego dan rasa nyaman yang berlebihan terhadap diri sendiri, yang sampai sekarang harus saya akui masih belum dapat celahnya juga. Mungkin benar saya terlalu malas. Tapi semoga tahun ini kita (saya, khususnya) bisa melakukan hal ini.

Script BASH Untuk Mendapatkan IP Address Interface

Dalam pekerjaan sehari-hari, saya mengakses jaringan/server di kantor melalui SSL VPN. Tapi, setiap kali tersambung ke VPN tersebut, default gw saya selalu diarahkan ke tunnel VPN dan semua akses internet dibelokkan ke jaringan kantor juga. Untuk mengatasi hal ini, saya perlu menambahkan baris:

/sbin/route del -net 0.0.0.0 gw $GWVPN netmask 128.0.0.0 dev tun0

ke dalam startup script VPN. Sekarang bagaimana caranya agar variabel $GWVPN bisa berisi ip address gateway vpn?

Karena interface VPN saya hanya satu dan selalu tun0, maka untuk mendapatkan ip address gateway vpn, saya menggunakan baris script:

GWVPN=`/sbin/route -n | grep tun0 | grep ‘UG[ \t]’ | awk ‘{print $2}’ |sed ‘1!d’`

Dengan demikian variabel GWVPN akan selalu berisi ip address gateway VPN. Jika ada cara yang jauh lebih cantik, mohon masukannya dan bisa ditulis di kolom comment.

XMPP Client Kaiwa (instalasi & requirement)

Berhubung akhir-akhir ini berkutat dengan XMPP server MongooseIM dan XEP-0313, jadinya membutuhkan klien yang support MAM (Message Archive Management) tersebut. Pilihan saya ada 2, yaitu Kaiwa dan Gajim.

Untuk Kaiwa, ada requirement yang dibutuhkan ketika setup. Cuma requirement tersebut tidak dicantumkan dalam petunjuk instalasinya. Jadi saya tulis di sini supaya saya sendiri juga tidak lupa kebutuhannya apa saja. Cara setup Kaiwa adalah sebagai berikut (di Ubuntu):

  1. git clone https://github.com/digicoop/kaiwa.git
  2. cd kaiwa
  3. Jika belum memiliki package npm, install dengan: apt-get install npm
  4. npm install
  5. npm install express helmet moonboots-express getconfig templatizer ldapjs body-parser compression serve-static
  6. npm install jade backbone underscore async stanza.io notify.js sound-effect-manager human-model
  7. npm install getusermedia crypto
  8. setelah itu jalankan : node server

 

Mengganti Windows 10 Default Browser

Lagi-lagi nemu masalah ketika selesai mengupgrade Windows 7 ke Windows 10. Kali ini browser tidak mau diset default selain bawaan dari Windows (Microsoft Edge), walaupun dari browser pilihan sudah dijadikan/disetting sebagai default browser. Ternyata perlu mengubah satu setting lagi seperti berikut:

  1. Klik tombol start lalu pilih icon setting: default browser 00
  2. Pilih System:default browser 01
  3. Pilih Defailt apps -> Web browser. Jika muncul daftar browser yang sudah diinstall di Windows 10, pilih browser yang dimaksud untuk dijadikan default browser (dalam contoh ini saya memilih Google Chrome).default browser 02

Sekarang default browser sudah berubah sesuai dengan pilihan kita.

Problem Setting Brightness di Windows 10

Jika kita mengupdate ke Windows 10 dari versi sebelumnya (misal Windows 7), ada kemungkinan akan mengalami permasalahan setting brightness. Layar akan tiba-tiba terang sekali dan kita tidak bisa menurunkan brightness setting. Untuk mengatasi problem (sepele tapi nyebahi) ini, lakukan langkah berikut:

  1. Masuk ke Device Manager -> Display adapters. Klik kanan pada device driver lalu pilih Update Driver Software..windows 10 brightness 00a
  2. Pilih Search automatically for updated driver software  dan tunggu beberapa saat, Windows 10 akan secara otomatis mencarikan update software display adapter terbaru.windows 10 brightness 00bwindows 10 brightness 01
  3. Setelah selesai (harusnya) kita bisa mengubah setting brightness.windows 10 brightness 02

Mengetahui Nomer Telp PSTN di Elastix

Salah satu kebiasaan saya dalam setup Elastix adalah memasukkan konfigurasi DAHDI Chanel DIDs seusai dengan nomer telepon analog yang tersambung ke FXO. Walaupun jika semua line disetup sebagai hunting, masing-masing line pasti memiliki nomer PSTN yang berbeda dari Telkom. Selain untuk kemudahan routing inbound/outbound, juga untuk kemudahan dokumentasi jika kelak terjadi masalah di salah satu line.

Caranya?

Yang dibutuhkan adalah extension yang aktif dan sebuah handphone untuk mengetahui nomer PSTN yang muncul. Lalu jalankan langkah berikut:

  • Aktifkan extension di SIP phone/Softphone (misal extension yang akan digunakan adalah 2015).
  • Masuk ke box Elastix melalui SSH. Lalu ketikkan perintah: asterisk -vr untuk masuk ke console Asterisk.
  • Jalankan perintah:  originate DAHDI/1/0811223344 extension 2015 (artinya, sambungkan extension 2015 ke nomer handphone 0811223344 melalui channel DAHDI/1). Periksa nomer telepon PSTN yang muncul di layar handphone, dan catat di DAHDI Channel DIDs sesuai dengan channelnya (dalam contoh ini Channel 1).
  • Jika channel DAHDI lebih dari satu, ganti angka channel dengan angka/urutan lainnya (misal originate DAHDI/2/0811223344 extension 2015, originate DAHDI/3/0811223344 extension 2015originate DAHDI/4/0811223344 extension 2015, dst).
  • Jumlah channel DAHDI yang ada bisa dilihat dengan perintah dahdi show channels dari console Asterisk. Contoh output seperti berikut:

dahdi channels