Home | Back
ทดลองสร้างโปรแกรมเก็บ Proxy Log ของ Squid 3.3.8 ลง MySQL ด้วย Python
Wednesday, 23 October 2013
ผมได้ทดลองทำ Proxy Server ใหม่ด้วย Squid 3.3.8 และให้ส่ง Access Log ไปเก็บที่ Log Server ด้วย udp โดยใน Log Server ผมได้สร้างโปรแกรมที่ทำการรับ log จาก udp มาเก็บใน MySQL เพื่อความสะดวกในการดูแล ค้นหา และ สกัด log โดยรายละเอียดมีดังนี้ครับ
1. สร้างฐานข้อมูล
ผมได้ทำการสร้างฐานข้อมูลที่ชื่อ proxy ซึ่งประกอบด้วยตารางเพียงตารางเดียวชื่อ log ซึ่งตาราง log นี้จะมีเพียง 3 คอลัมน์ ซึ่งรายละเอียดตามนี้ครับ
CREATE TABLE IF NOT EXISTS `log` (
`proxy` varchar(200) COLLATE utf8_bin NOT NULL,
`epoch` decimal(20,3) NOT NULL,
`log` varchar(1000) COLLATE utf8_bin NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
2. โปรแกรม ProxyLog
โปรแกรมที่สร้างขึ้นจะ ทำงานโดยจะมีโปรแกรมหลักจะทำหน้าที่รับข้อมูล log จาก udp และนำข้อมูลนั้นส่งต่อให้กับโปรแกรมลูก โดยเมื่อโปรแกรมลูกรับข้อมูลมาแล้วจะทำการสร้าง Thread เพื่อรับข้อมูล log ไปเก็บไว้ที่ฐานข้อมูล MySQL อีกทีหนึ่งครับ โดยรายละเอียดโปรแกรมมีดังนี้ครับ
File : proxylog.py
import os
import socket
import prctl
import MySQLdb as mdb
from threading import Thread
from multiprocessing import Process, Queue, cpu_count
ip = "172.16.9.100"
port = 8899
dbHost = "172.16.9.100"
dbUser = "proxy"
dbPasswd = "proxy-secret-password"
dbName = "proxy"
def log(cur, data, addr):
dat = data.split()
query = "insert into log (`proxy`,`epoch`,`log`) values ('%s','%s','%s')" % (addr, dat[0], data,)
cur.execute(query)
def tworker(data, addr):
dd = data.decode(encoding='UTF-8')
d = dd.split("\n")
con = mdb.connect(dbHost, dbUser, dbPasswd, dbName, charset='utf8', use_unicode=True)
cur = con.cursor(mdb.cursors.DictCursor)
for i in d:
if i == "":
continue
log(cur, i, addr)
con.close()
def worker(q):
while True:
(data, addr) = q.get()
Thread(target=tworker, args=(data, addr, )).start()
def serve():
cpu = cpu_count()
cpu = cpu*2
q = Queue()
prctl.set_proctitle("ProxyLog")
for i in range(cpu):
Process(target=worker, args=(q,)).start()
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind((ip,port))
while True:
data, addr = s.recvfrom(10000)
q.put((data, addr[0], ))
p = os.fork()
if p == 0:
serve()
print("Fork pid = %s" % p)
จากนั้นทำการรันโปรแกรมดังนี้ครับ
3. ปรับแต่งให้ Squid 3.8 ส่ง log ผ่าน upd
เราสามารถกำหนดให้ Squid 3.8 ทำการส่ง log ผ่าน udp ได้โดยการปรับแต่งไฟล์ /etc/squid3/squid.conf ดังนี้ครับ
File : /etc/squid3/squid.conf
จากนั้นทำการสั่งให้ Squid นำการปรับแต่งตัวเองใหม่และทำงานดังนี้ครับ