Tuesday, August 28, 2007

Bruter

ในที่สุดก็ไปสมัครที่ sourceforge เพื่อเขียนโปรแกรม opensource ซะแล้ว

โปรแกรมนี้ชื่อว่า Bruter การทำงานก็คล้ายๆ กับตัวโปแกรม hydra, medusa นั่นแหละ
แต่โปรแกรมนี้จะให้มัน run บน windows

ตอนนี้ที่ sourceforge ยังไม่มี source code อะไรเลย เพราะกำลังหัดใช้ SVN อยู่ ใช้คล่องเมื่อไรก็จะ upload source code ขึ้นไปเลย

เอาหน้าตาที่ยังไม่เสร็จไปดูก่อนละกัน (ยังมี bug กับ feature ที่ยังไม่ทำอีกเยอะเลย)

Sunday, August 19, 2007

SMTP command

note ไว้หน่อยกันลืม

220 mail.domain.ext ESMTP Sendmail ?version-number?; ?date+time+gmtoffset?
HELO local.domain.name
250 mail.domain.ext Hello local.domain.name [loc.al.i.p], pleased to meet you
MAIL FROM: mail@domain.ext
250 2.1.0 mail@domain.ext... Sender ok
RCPT TO: mail@otherdomain.ext
250 2.1.0 mail@otherdomain.ext... Recipient ok
DATA
354 go ahead
From: John <@domain.ext>
To: Nobody
Subject:-type subject here-

hello message here
.
250 2.0.0 ???????? Message accepted for delivery
QUIT
221 2.0.0 mail.domain.ext closing connection

ถ้าต้อง AUTH ก็จะนำ username กับ password มา encode ด้วย base64 ก่อนคือ
base64.encodestring('\000user@domain.ext\000password')
ได้เป็น 'AHVzZXJAZG9tYWluLmV4dABwYXNzd29yZA=='

แล้วทำ AUTH หลัง HELO หรือ EHLO
AUTH PLAIN
AHVzZXJAZG9tYWluLmV4dABwYXNzd29yZA==
235 ok, go ahead

reponse จาก server สำคัญที่ตัวเลข code อันแรก 200 กว่าคือพวก OK

Tuesday, August 7, 2007

TCP Connection State (Part 2)

หลังจาก Part1 เกี่ยวกับ establish TCP connection เสร็จแล้ว ระหว่างการส่งข้อมูล จะมีการ set ACK bit ใน TCP header ตลอด และสุดท้ายเมื่อส่งข้อมูลครบแล้วก็คือการปิด connection

ใน Part นี้จะพูดเกี่ยวกับ state ที่เหลือที่ค้างไว้ ซึ่งทั้งหมดจะอยู่ในช่วงของการปิด connection

Note: การปิด connection ของ TCP จะหมายถึงจะไม่ส่งข้อมูลอีกแล้ว

ในการปิดมี 3 แบบที่สำคัญใน (จาก rfc 793) แต่จะขอพูดแค่ 2 แบบ ซึ่งจะแสดงครบทุก state แล้วคือ

Case 1: มีการเริ่มปิด connection จากฝั่งหนึ่ง
    TCP A                      TCP B
0.  ESTABLISHED                ESTABLISHED
1.  FIN-WAIT-1 --> FIN,ACK --> CLOSE-WAIT
2.  FIN-WAIT-2 <--   ACK   <-- CLOSE-WAIT
3.  TIME-WAIT  <-- FIN,ACK <-- LAST-ACK
4.  TIME-WAIT  -->   ACK   --> CLOSED
5.  (2 MSL)
CLOSED
1. เครื่อง A จะส่ง packet โดย set FIN ไปยังเครื่อง B เพื่อบอกว่าจะปิด connection และจะเห็นว่า ACK bit ได้ถูก set ด้วย ซึ่ง ACK อันนี้หมายถึงตอบกลับว่าได้รับข้อมูลถึงไหนแล้ว ขณะนี้ state เครื่อง A จะเป็น FIN-WAIT-1 และเครื่อง B เป็น CLOSE-WAIT
2. เครื่อง B จะตอบด้วย ACK เมื่อเครื่อง A ได้รับ ACK จะถือว่าเครื่อง A ได้ปิด connection เสร็จแล้ว ขณะนี้เครื่อง A จะไม่มีการส่งข้อมูลอีก แต่ยังรับข้อมูลอยู่ได้ ส่วนเครื่อง B จะยังส่งและรับข้อมูลได้ เมื่อจบขั้นตอนนี้ state ของเครื่อง A จะเป็น FIN-WAIT-2 และเครื่อง B เป็น CLOSE-WAIT
3. เมื่อเครื่อง B ต้องการจะปิด connection ก็จะส่ง FIN ไปยังเครื่อง A (ACK flag เหมือนกับขั้นตอน1) โดย state ของเครื่อง A จะเป็น TIME-WAIT และเครื่อง B เป็น LAST-ACK
4. เครื่อง A ตอบกลับด้วย ACK เมื่อเครื่อง B ได้รับจะถือว่าเครื่อง B ปิด connection เสร็จแล้ว และเมื่อทั้งฝั่งปิด connection เสร็จแล้วจะถือว่าจบการ connection เมือถึงขั้นตอนนี้ state ของเครื่อง A ยังคงเป็น TIME-WAIT และเครื่อง B เป็น CLOSED
5. เครือง A หลังจากเข้าสู่ state TIME-WAIT จะคอยอีก 2 MSL (Maximum Segment Life) โดย 1 MSL ใน rfc793 จะกำหนดไว้ที่ 120 วินาที แล้วถึงเข้า state CLOSED

* สาเหตุที่ต้องคอยอีก 2 MSL หลังจาก TIME-WAIT มันต้องอธิบายเกี่ยวกับ Sequence Number ด้วย ถ้าใครสนใจก็อ่านเพิ่มได้จาก rfc

Case 2: ทั้งสองฝั่งปิด connection พร้อมกัน
   TCP A                         TCP B
0. ESTABLISHED                   ESTABLISHED
1. FIN-WAIT-1  <--> FIN,ACK <--> FIN-WAIT-1
2. CLOSING     <-->    ACK  <--> CLOSING
3. TIME-WAIT                     TIME-WAIT
(2 MSL)                          (2 MSL)
CLOSED                           CLOSED
1. เครื่อง A และ B ขอปิด connection พร้อมกัน โดยส่ง packet ที่ set FIN flag พร้อมกัน ซึ่ง state ทั้ง 2 เครื่องจะเป็น FIN-WAIT-1
2. เครื่อง A และ B จะตอบด้วย ACK เพื่อจบ connection โดยขณะที่ส่ง ACK แต่ยังไม่รับของอีกฝ่าย state จะเป็น CLOSING
3. เมื่อได้รับ ACK ทั้งสองฝั่งจะเข้าสู่ state TIME-WAIT และคอยอีก 2 MSL แล้้วเปลี่ยนเป็น state CLOSED

สรุป

จากที่กล่าวมาทั้งหมดจาก Part1 และ Part2 สามารถสรุปเป็น diagram สำหรับแสดงการเปลี่ยนแปลงของ state ดังนี้ (diagram นี้เป็นแค่สรุป ไม่ใช่ specification ทั้งหมดนะ)


Diagram จาก RFC 793

สรุปความหมายของแต่ละ state ได้ดังนี้

- LISTEN คือกำลังคอย connection request (SYN) จาก remote TCP และ port
- SYN-SENT คือกำลังคอยการตอบกลับ (SYN,ACK) หลังจากได้ส่ง connection request (SYN)
- SYN-RECEIVED คือกำลังคอยการยืนยัน connection (ACK) หลังจากตอบกลับ connection request (SYN, ACK)
- ESTABLISHED คือได้เปิด connection สมบูรณ์แล้ว และมีการส่งข้อมูลอยู่
- FIN-WAIT-1 คือกำลังคอยการปิด หลังจากส่ง connection termination request (FIN)
- FIN-WAIT-2 คือกำลังคอย connection termination request (FIN) จากอีกฝั่ง หลังจากปิด connection ของฝั่งตัวเองแล้ว
- CLOSE-WAIT คือกำลังคอยปิด connection จาก local user โดยได้รับและตอบกลับ connection termincation request (FIN และ ACK) จากอีกฝั่งแล้ว
- CLOSING คือกำลังคอยการปิด หลังจากส่ง connection termination request (FIN) และได้รับ connection termination request ด้วย (ก็คือส่ง FIN ไปแล้ว ได้รับ FIN มาก่อน แต่ยังไม่รับ ACK)
- LAST-ACK คือกำลังคอยการปิด หลังจากส่ง connection termination request (FIN) จาก state CLOSE-WAIT
- TIME-WAIT คือคอยให้เวลาผ่านไป 2MSL เพื่อให้แน่ใจว่า remote TCP ได้รับ ACK และปิด connection ไปแล้ว
- CLOSED คือ state ที่ไม่มี connection ใดๆ ทั้งสิ้น

11 August 2007

Reference:
[1] RFC 793 - Transmission Control Protocol, http://www.rfc.net/rfc793.html

Sunday, August 5, 2007

การ compile และ install kernel ของ FreeBSD 6.x

*** อันนี้เขียนไว้นานแล้ว แหละก็ไปแปะไว้ที่อื่น (ตอนนั้นยังไม่มี blog) ดังนั้นถ้าเคยเห็นอ่านแล้วก็อย่าแปลกใจนะ

ต้องบอกก่อนว่าเนื้อหาที่เขียนขึ้นมา หรืออาจจะเรียกว่าแปลก็ได้ เอามาจาก FreeBSD Handbook ทั้งหมด หัวข้อยังชื่อเหมือนกันเลย แต่จะพูดแบบสรุป และก็วิธีนี้สำหรับ FreeBSD 6.x นะ

Why Build a Custom Kernel?

โดยปกติ default kernel ที่มาจากแผ่น (GENERIC หรืออาจเป็น SMP) จะ support hardware จำนวนมาก การสร้าง kernel ของตัวเองนั้นส่วนมากจะให้ kernel ที่สร้างใหม่ support เฉพาะ hardware ที่มีอยู่ในเครื่อง ซึ่งจะมีข้อดีที่เห็นได้หลักๆ คือ
- boot เร็วขึ้น เพราะว่า kernel ทำการ probe hardware เฉพาะที่มันรู้จัก หรือเฉพาะที่อยู่ในเครื่อง
- ใช้ memory น้อยลง ซึ่งเหมาะกับระบบที่มี RAM น้อย
- ให้ support hardware เพิ่มเติมได้ เช่น sound cards, การทำ polling เป็นต้น

Building and Installing a Custom Kernel

directory ทั้งหมดที่เกี่ยวกับการสร้าง kernel นั้นจะอยู่ใน /usr/src/sys ซึ่งสามารถเข้าได้จาก /sys (เป็น soft link ชี้ไปยัง /usr/src/sys) และ subdirectories ที่สำคัญ ที่คุณต้องเข้าไปแก้ไข configuration file และ compile คือ arch/conf โดย arch คือ architecture ของเครื่องคุณ โดย FreeBSD จะมี i386, alpha, amd64, ia64, powerpc, sparc64, และ pc98

ในการสร้าง custom kernel จะสมมติว่าเครื่องของคุณเป็น i386 architecture และ default kernel คือ GENERIC ถ้าเครื่องของคุณเป็น architecture อื่น ต้องแก้ directory path ของ architecture ให้ตรงกับเครื่องของคุณ

ถ้าคุณไม่พบ /usr/src/sys ในเครื่องของคุณ แสดงว่าคุณยังไม่ได้ install kernel source ให้ install โดยทำตามขั้นตอนต่อไปนี้
- สั่ง sysinstall ด้วย root user จาก shell prompt
- เลือก Configure -> Distributions -> src
- เลือก base กับ sys
- เลือก OK ไปเรื่อยๆ แล้วเลือกว่าจะให้ลงจากที่ไหน (แนะนำให้ใช้จาก CD ที่ลง FreeBSD)
* การลง kernel source ยังมีอีกหลายวิธีนะ

ต่อไปจะเป็นการ copy configuration file ของ kernel โดยผมแนะนำให้เก็บตัวไว้ใน home directory ของคุณ ดังนี้
# cd /usr/src/sys/i386/conf
# cp GENERIC /root/MYKERNEL
# ln -s /root/MYKERNEL

โดยทั่วไป ชื่อ configuration file ของ kernel จะใช้ตัวใหญ่ทั้งหมด ซึ่งในที่นี้จะใช้ชื่อว่า MYKERNEL

ขั้นตอนต่อไป คือการแก้ไข MYKERNEL ตามที่ต้องการ โดยใน configuration file นั้นแต่ละบรรทัดจะมี keyword และค่าของมัน และอักษรที่ตามหลังเครื่องหมาย # จะหมายถึง comment

ใน configuration บรรทัดที่คุณต้องแก้ไขคือค่า ident ให้ตรงกับชื่อ kernel ที่คุณตั้ง เช่นในกรณีนี้คือ MYKERNEL ก็แก้เป็น
ident MYKERNEL

เกี่ยวกับค่าอื่นๆ และรายละเอียดเพิ่มเติมเกี่ยวกับ configuration file สามารถดูได้ที่ http://www.freebsd.org/doc/handbook/kernelconfig-config.html

หลังจากที่ได้ทำการแก้ไข configuration file ให้ทำการ compile และ install kernel ตัวใหม่ดังนี้
# cd /usr/src
# make buildkernel KERNCONF=MYKERNEL
# make installkernel KERNCONF=MYKERNEL

* ถ้าคุณตั้งชื่อ KERNEL เป็นชื่ออื่น ให้แก้ MYKERNEL ไปตามชื่อที่คุณตั้ง

หลังจาก install kernel เสร็จ kernel ตัวใหม่จะอยู่ที่ /boot/kernel และตัวเก่าจะอยู่ที่ /boot/kernel.old เนื่องจากถ้ามีการ install kernel ใหม่อีกครั้ง kernel.old จะถูกทับ แนะนำให้ทำการเก็บ kernel เก่าไว้ดังนี้
# mv /boot/kernel.old /boot/kernel.GENERIC

ต่อไป ก็คือ restart เครื่อง
# shutdown -r now

If Something Goes Wrong

ปัญหาที่พบส่วนมากจากการ compile kernel ใหม่เอง สามารถดูรายละเอียดได้จาก http://www.freebsd.org/doc/handbook/kernelconfig-trouble.html

ในที่นี้จะขอเอามาเฉพาะเมื่อไม่สามารถ boot ด้วย kernel ตัวใหม่ได้ หรืออาจจะมีปัญหากับ kernel ตัวใหม่ต้องการกลับไปใช้ตัวเก่า

เมื่อไม่สามารถ boot ด้วย kernel ตัวใหม่ให้ทำต่อไปนี้
- ที่ boot loader ให้เลือก option ที่ 6 "Escape to loader prompt"
- เมื่อได้ prompt ให้พิมพ์ unload kernel
- แล้วพิมพ์ boot /boot/kernel.old/kernel (ถ้าทำตามข้างบนคือเปลี่ยน kernel เก่าเป็น kernel.GENERIC ก็ใช้ boot /boot/kernel.GENERIC/kernel)

หลังจาก boot ด้วย kernel ตัวเก่า คุณสามารถดู error ได้จาก boot ที่ /var/log/messages แล้วแก้ไข configuration file และ compile kernel ใหม่ หรือถ้าคุณต้องการกลับมาใช้ kernel ตัวเก่า สามารถทำได้ดังนี้
# mv /boot/kernel /boot/kernel.bad
# mv /boot/kernel.good /boot/kernel

โดยแทนที่ kernel.good ด้วย kernel path ของตัวเก่าที่เก็บไว้

13 May 2007

Reference:
[1] FreeBSD Handbook :Chapter 8 Configuring the FreeBSD Kernel
, http://www.freebsd.org/

TCP Connection State (Part 1)

หลังจากที่สงสัยมานาน จากตัวโปรแกรม TCPView (หาโหลดได้ที่ http://www.microsoft.com/technet/sysinternals/Utilities/TcpView.mspx) ในช่อง state ว่า state CLOSE_WAIT, CLOSING, LAST_ACK, FIN_WAIT_1, FIN_WAIT_2 มันคือ state อะไรกันแน่ ในที่สุดก็ยอมอ่านซะที

ขอแสดง state ทั้งหมดของ TCP Connection ก่อนดีกว่า (ตาม rfc 793) มันมี LISTEN, SYN-SENT, SYN-RECEIVED, ESTABLISHED, FIN-WAIT-1, FIN-WAIT-2, CLOSING, LAST-ACK, TIME-WAIT และสุดท้าย state ที่คุณไม่มีวันเห็นก็คือ CLOSED

ก่อนจะบอกว่าแต่ละ state ทำอะไรขอพูดเรื่อง Control bit ใน TCP Header นิดนึงกับ 3-Way Handshake ก่อนละกัน

ตัว TCP Header จะมี Control bit อยู่ทั้งหมด 6 bits คือ URG, ACK, PSH, RST, SYN, FIN โดยบิท ACK, RST, SYN, FIN เป็นตัวหลักในการกำหนดการเปลี่ยนแปลงของ connection state

ในการเชื่อมต่อจากเครื่องหนึ่งไปยังอีกเครื่องหนึ่ง ด้วย TCP ฝั่ง server จะต้องเปิด port ทิ้งไว้ โดยฝั่ง server จะเรียก state ที่เปิด port ว่า LISTEN และก่อนที่จะเริ่มส่งข้อมูลกันได้ ก็จะมีการทำที่เรียกว่า 3-Way Handshake ดังนี้
    Client                         Server
0. CLOSED LISTEN
1. SYN-SENT --> SYN --> SYN-RECEIVED
2. ESTABLISHED <-- SYN,ACK <-- SYN-RECEIVED
3. ESTABLISHED --> ACK --> ESTABLISHED

1. Client จะส่ง packet โดยจะ set SYN bit ใน TCP header ไปยัง client เมื่อจบขั้นตอนนี้ state ที่ฝั่ง client จะเป็น SYN-SENT และ state ของ server จะเป็น SYN-RECEIVED
2. Server จะตอบ client โดยการ set SYN และ ACK bit ใน TCP header
เมื่อจบขั้นตอนนี้ state ที่ฝั่ง client จะเป็น ESTABLISHED และ state ของ server ยังคงเป็น SYN-RECEIVED
3. Client ตอบ server ด้วยการ set ACK bit ใน TCP header
เมื่อจบขั้นตอนนี้ state ของทั้ง client และ server จะเป็น ESTABLISHED

หลังจาก 3-Way handshake ก็จะทำการเริ่มส่งข้อมูล

เหนื่อยแหละ พอก่อน ถ้าไม่นับ CLOSED ก็อธิบายไปแล้วนะ 4 state คือ LISTEN, SYN-SENT, SYN-RECEIVED และ ESTABLISHED ที่เหลือจะอยู่ในช่วงที่จะปิด connection ต่อคราวหน้า

4 August 2007

Reference:
[1] RFC 793 - Transmission Control Protocol, http://www.rfc.net/rfc793.html

Saturday, August 4, 2007

portsnap vs cvsup

portsnap คือคำสั่งที่ใช้ update port ของ FreeBSD เช่นเดียวกับ cvsup แล้วมันต่างกันอย่างไรละ?!?

ความแตกต่างอย่างแรกคือ portsnap ใหม่กว่า cvsup เก่าแล้ว และ portsnap จะมีให้เลยใน FreeBSD 6.x --' (ไร้สาระจริงๆ เลยเรา)

ความแตกต่างคือ (เข้าประเด็นแล้ว)
1. portsnap จะ update ได้ปลอดภัยกว่า โดยมีเป็นการส่งแบบ signed compress snapshot ก็คือ ส่ง snapshot ที่มีการบีบอัด และก็ข้อมูลที่ส่งจะมี signature ทำให้แน่ใจได้ว่าข้อมูลที่ได้รับถูกต้องแน่นอน
2. portsnap จะ update เฉพาะที่มีการเปลี่ยนแปลง ซึ่งเหมาะกับการระบบที่มีการ update บ่อยๆ แต่ cvsup จะ update ทั้ง port tree ซึ่งทำให้ cvsup update port ช้ากว่าและใช้ bandwidth มากกว่า
3. portsnap ใช้ protocol HTTP ในการส่งข้อมูล แต่ cvsup เป็น custom protocol ใช้ port 5999 ซึ่งอาจมีปัญหากับพวก firewall

Note: จากที่ผมเคยลองมา ถ้าทิ้งไว้เป็นเดือนแล้วใช้ portsnap มันนานพอควรเลยแหละ (ไม่ได้จับเวลาทดสอบนะ) ดังนั้นผมก็ไม่รู้เหมือนกันว่าระบบที่ไม่ค่อย update port แบบนี้ควรใช้ cvsup หรือ portsnap

จากข้อดีของ portsnap ที่ได้บอกไปแล้ว ก็ขออธิบายสั้นๆ ละกัน เกี่ยวกับวิธีการใช้งาน portsnap (ถ้าอยากดูเต็มๆ ก็ไปดูที่ http://www.freebsd.org/doc/handbook/portsnap.html)

portsnap จะมีให้เลยใน FreeBSD version ไหนบ้างผมไม่แน่ใจ (ผมเริ่มใช้ตอนมันออก 6.1) แต่ถ้าในเครื่องของคุณไม่มีสามารถติดตั้งโดยใช้ port ports-mgmt/portsnap

snapshot ทั้งหมดของ portsnap ที่ download มาจะเก็บไว้ที่ /var/db/portsnap แต่ถ้าลงจาก port จะอยู่ที่ /usr/local/portsnap/

สำหรับการใช้ portsnap ครั้งแรก
1. ทำการดึง snapshot ทั้งหมดของ port
# portsnap fetch
2. ทำการ extract port ที่ fetch มา
# portsnap extract
Note: ถึงแม้ว่าในเครื่องจะมีการใช้ cvsup ก่อนหน้านี้ ก็ต้องใช้ 2 คำสั่งนี้ เพื่อเป็น baseline ให้ portsnap รู้ว่าครั้งต่อไปต้อง update อะไรบ้าง

การ update port tree ในครั้งต่อๆ ไป ก็ใช้คำสั่งบรรทัดเดียวคือ
# portsnap fetch update
Note: คำสั่งข้างบน เท่ากับ 2 คำสั่งแต่ไปนี้ portsnap fetch; portsnap update

การสั่งให้ portsnap update ด้วย cron ก็คือใช้คำสั่ง portsnap -I cron update โดย -I คือให้ fetch snapshot มา แต่ทำการ update เฉพาะไฟล์ INDEX ของ port ซึ่งจะเห็นว่าต้องสั่ง portsnap update อีกที (ตาม Handbook เหตุผลที่ใช้ -I คือป้องกันการ update port ขณะที่เราทำการติดตั้งโปรแกรม) สรุปก็คือเพิ่มบรรทัดต่อไปนี้ใน /etc/crontab
0 3 * * * root portsnap -I cron update && pkg_version -vIL=

3 August 2007

Reference:
[1] Secure FreeBSD ports tree updating, http://www.daemonology.net/portsnap/
[2] FreeBSD Handbook (A.6 Using Portsnap), http://www.freebsd.org/doc/handbook/portsnap.html