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 นำการปรับแต่งตัวเองใหม่และทำงานดังนี้ครับ



Home | Back