Filter website negatif dengan Linux dan Powerdns.

Published by Dhani Setiawan on
Filed under: How-to Tags: , , ,

Ini how-to yang quick and dirty, bagaimana cara blokir dns situs-situs negatif dengan Powerdns dan Lua.

Di beberapa institusi, misalnya kampus, sekolah atau yang lain, situs-situs negatif seperti pornografi dan yang lain lebih baik untuk difilter. Dari sekian banyak cara blokir content negatif, salah satu cara adalah dengan blokir melalui dns. Meskipun dengan blokir dns user masih bisa dengan cara-cara lain mengakses konten negatif, tapi paling tidak blokir dns bisa mengurangi traffic ke situs-situs negatif tersebut.

Ada beberapa opsi untuk blokir situs negatif dengan dns, free service seperti Nawala atau OpenDNS bisa digunakan. Cara blokir dibawah ini bisa digunakan kalau ada server Linux lokal yang dimanfaatkan sebagai dns server.

DNS

Ada dua mode dalam dns service, yaitu recursor dan authoritative. Recursor fungsinya melakukan query ke root server untuk memetakan nama domain ke ip address. Sedangkan authoritative berfungsi sebagai nameserver. Misalnya untuk Google, free service dns recursor Google di server 8.8.8.8 dan 8.8.4.4 sedangkan untuk authoritative nameserver google.com di ns(1|2|3|4).google.com.

Powerdns

Untuk blokir melalui dns, yang diperlukan hanya dns recursor sedangkan authoritative nameserver tidak diperlukan. Ada banyak dns recursor yang bisa dipakai, beberapa yang banyak digunakan yaitu bind9, dnsmasq, dan Powerdns recursor. Di artikel ini menggunakan Powerdns recursor.

Situs-situs pornografi jumlahnya banyak, banyak sekali bahkan. Kalau kita ambil data dari situs Trust Positif Kominfo, ada lebih dari 700 ribu situs yang seharusnya diblokir. Karena itu, pilihan dns recursornya juga menyesuaikan.

Saya tidak gunakan Bind9 atau Dnsmasq dengan beberapa pertimbangan. Konfigurasi file teks Bind9 untuk 700 ribu lebih record sepertinya menyusahkan, Dnsmasq meskipun bagus untuk skala kecil, tapi untuk data sebanyak itu start-up nya jadi lebih lama.

Powerdns sangat cocok karena bisa menggunakan backend database SQL. Jadi record domain yang diblokir bisa disimpan di database. Tapi problem muncul kemudian ketika harus upgrade server atau pindah server, backup dan restore database dengan data ratusan ribu record jadi tidak efisien. Untuk itu, saya putuskan untuk kembali ke konsep KISS, Keep It Simple Stupid!, abaikan saja kata stupidnya.

Satu fitur di Powerdns yang saya manfaatkan adalah scripting dengan bahasa Lua. Jadi dengan script ini kita bisa memanipulasi hasil dns query dengan hasil script Lua, silahkan baca tentang Lua di http://www.lua.org/

Metode saya sederhana saja, nama-nama domain yang diblokir disimpan di file plaintext. Kemudian dengan script Lua, Saya eksekusi command grep. Kalau return value dari grep True, berarti domain masuk dalam list blokir dan False jika sebaliknya.

How-to

Di artikel ini, direktori Powerdns ada di /etc/powerdns dan nama file yang berisi domain-domain yang diblok ada di /etc/powerdns/blacklist, silahkan disesuaikan.

Pertama, install Powerdns dan Lua kalau belum ada

apt-get install pdns-recursor lua5.2

Command diatas untuk Debian 8, untuk distibusi lain silahkan disesuaikan. Paket Lua5.2 sebenarnya tidak diperlukan, hanya diperlukan untuk testing script.

Setelah pdns-recursor terinstall, edit file /etc/powerdns/recursor.conf.

vim /etc/powerdns/recursor.conf

Vim bisa diganti dengan editor lain, nano misalnya. Banyak parameter di recursor.conf, tapi untuk keperluan ini cukup allow-from dan lua-dns-script

Comtoh file recursor.conf

# allow-from untuk memfilter network mana saja yang boleh query ke server ini.
# Misal network internal 192.168.1.0/24, maka tambahkan network tersebut ke allow-from

allow-from=127.0.0.0/8, ::1/128, fe80::/10, 192.168.1.0/24

# lua-dns-script diisi dengan lokasi script Lua untuk Powerdns.

lua-dns-script= /etc/powerdns/script.lua

Berikutnya, kita perlu mendownload data dari server Trust Positif dan menulis script Lua.

curl "http://trustpositif.kominfo.go.id/files/index.php?download=blacklist%2Fporn%2Fdomains&share=11" > /etc/powerdns/blacklist

Setelah download dengan command diatas, di direktori /etc/powerdns sudah ada file dengan nama blacklist yang berisi nama-nama domain yang di blokir oleh Kominfo.

Selanjutnya, script Lua di /etc/powerdns/script.lua

--- function preresolve dieksekusi oleh pdns-recursor
--- sebelum query ke root server
--- kita tempatkan blacklist di function ini

function preresolve (ip, domain, qtype)
---     Kita hanya akan memeriksa query dengan tipe record A
        if qtype == pdns.A
        then
                dom = domain:match("%w+%.%w+.$")

                if dom == nil
                then
                        dom = "NXDOMAIN."
                end

---             Hilangkan tanda . (dot) dibelakang query domain
---             google.com. menjadi google.com
                dom = string.sub(domain, 1, string.len(domain) - 1)

---             File berisi nama-nama domain yang diblokir
                file = "/etc/powerdns/blacklist"

---             Eksekusi perintah grep, apabila return value == true, maka
---             situs terblokir dan hasil query akan diarahkan ke web server
---             dengan halaman blokir. IP address web server disini
---             menggunakan 192.168.1.1, apabila berbeda
---             silahkan disesuaikan.
                if os.execute(string.format("grep \"^%s$\" %s >/dev/null", dom, file)) == true     
                then
                        addr = "192.168.1.1"
                        ret={
                                {qtype=1, ttl=60,  content=addr}
                        }
                        return 0, ret
                else
                        return -1, {}
                end

        end
        return -1, {}
end

Sampai disini seharusnya dns server sudah bisa dipakai

systemctl restart pdns-recursor

Jika tidak ada error, tes query dari localhost

dig google.com @localhost

Tes juga query domain yang diblokir

dig playboy.com @localhost

Jika hasilnya seperti dibawah, maka sudah benar

;; ANSWER SECTION:
playboy.com.        60  IN  A   192.168.1.1

Update data

Problem selanjutnya yang muncul adalah bagaimana cara menambah atau menghapus data. saya pikir agak merepotkan kalau setiap kali menambah atau menghapus data harus login ke server kemudian edit file secara manual.

Untuk itu, saya membuat script sederhana dengan Python dan pop3 module. Dengan script ini, Saya bisa menambah atau mengurangi data domain yang diblokir dengan cara kirim email. Script Python ini fungsinya mengecek email setiap 10 menit sekali, kemudian jika ada email maka data akan di-update tergantung subject email, Saya gunakan subject [dns add] untuk menambah dan [dns del] untuk menghapus. Untuk nama-nama domainnya di list di body teks email, satu domain per baris.

Script ini diberi nama ckmail dan ditempatkan di /usr/local/bin. Script ini dieksekusi oleh cron setiap 10 menit.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env python

import poplib
import re
import os.path as op
from os import remove
from shutil import move

DELETE      = 0x01
ADD         = 0x02
CMD         = 0x00

DIR = "/etc/powerdns/"
FILE = "blacklist"

def checkhdr(mail):
        global CMD
        global ADD
        global DELETE

        qa = re.compile("(S|s)ubject:[ \t]+\[dns add\].*")
        qd = re.compile("(S|s)ubject:[ \t]+\[dns del\].*")
        j = 0

        for i in mail:
                if j <= 50:
                        if re.search(qa, i):
                                CMD |= ADD
                                return True
                        if re.search(qd, i):
                                CMD |= DELETE
                                return True
                j += 1

        return 0

# end chkhdr()

def addlist(domain):
        f = DIR + FILE

        fsock = open(f, "a")
        for i in domain:
                fsock.write(i + "\n")
        fsock.close()

        return True

# end addlist

def remlist(domain):
        f = DIR + FILE
        f2 = DIR + "." + FILE

        if op.isfile(f):
                move(f, f2)
        else:
                return False

        fsockr = open(f2, "r")
        fsockw = open(f, "a")

        while 1:
                i = fsockr.readline()
                if i:
                        m = 0
                        for j in domain:
                                if i == j + "\n":
                                        m = 1
                                        break

                        if m == 0:
                                fsockw.write(i)
                else:
                        break

        fsockr.close()
        fsockw.close()

        remove(f2)
        return True

# Server, username dan password
srv = "pop3.example.com"
user = "user@example.com"
passwd = "password"

POP = poplib.POP3_SSL(srv)
POP.user(user)
POP.pass_(passwd)
mailnum = POP.stat()[0]

for i in range(mailnum):
        i += 1
        mail = POP.retr(i)[1]

        if checkhdr(mail):
                q = re.compile("^[a-zA-Z0-9]+[a-zA-Z0-9-_.]+\.[a-z]{2,4}$")
                dom = []
                for j in mail:
                        if re.search(q, j):
                                dom.append(j)

                if (CMD & ADD) > 0:
                        addlist(dom)
                if (CMD & DELETE) > 0:
                        remlist(dom)

                POP.dele(i)

POP.quit()

That’s it, cara yang quick and dirty dan tentunya metode ini jauh dari kata elegan.


Sebarkan artikel ini :



Anda tidak perlu repot-repot mengunjungi blog ini.
Silahkan masukkan alamat email dan begitu ada post baru, Saya akan minta robot FeedBurner mengantarkannya ke email inbox Anda.

Delivered by FeedBurner


blog comments powered by Disqus