banner

[Rule] Rules  [Home] Main Forum  [Portal] Portal  
[Members] Member Listing  [Statistics] Statistics  [Search] Search  [Reading Room] Reading Room 
[Register] Register  
[Login] Loginhttp  | https  ]
 
Messages posted by: tranvanminh  XML
Profile for tranvanminh Messages posted by tranvanminh [ number of posts not being displayed on this page: 9 ]
 
Case 2 - iptables và máy đơn có dịch vụ
Trường hợp điển hình thứ nhì trong việc ứng dụng iptables để bảo vệ máy đơn có dịch vụ.

1. Trường hợp:
Firewall cho một máy đơn có dịch vụ.

2. Nhu cầu:
Bảo vệ máy đơn không bị thâm nhập vào những dịch vụ không dành cho công cộng và cho phép truy cập vào những dịch vụ được ấn định cụ thể.

3. Phương pháp kết nối:
Bất cứ phương tiện nào, (cách tốt nhất) nên có IP tĩnh để có thể tạo dịch vụ công cộng ổn định.

Đòi hỏi tối thiểu:
Đã hoàn tất thành công quy trình kết nối vào Internet và các dịch vụ trên máy đã có thể truy cập được từ Internet.

4. Mô hình:

eth0 là NIC tiếp diện với Internet với IP tĩnh. Mô hình này thích hợp cho các máy đơn (dedicated server) với các dịch vụ thông thường như HTTP, SMTP, POP3, DNS và SSH (quản lý từ xa).

5. Nhóm luật:


Code:
1. IF=`/sbin/route | grep -i 'default' | awk '{print$8}'`
2. IP=`/sbin/ifconfig $IF | grep "inet addr" | awk -F":" '{print$2}' | awk '{print $1}'`
3. IPT="/usr/local/sbin/iptables"
4. NET="any/0"
5. DNS="xxx.xxx.xxx.xxx yyy.yyy.yyy.yyy.yyy"
6. SERV_TCP="22 25 80 443 110"
7. SERV_UDP="53 123"
8. HI_PORTS="1024:65535"
9.
10. $IPT -F
11. $IPT -P INPUT DROP
12. $IPT -P OUTPUT DROP
13. $IPT -P FORWARD DROP
14.
15. for entry in $DNS, do
16. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $HI_PORTS -d $entry --dport 53 -m state --state NEW -j ACCEPT
17. $IPT -A INPUT -i $IF -p udp -s $entry --sport 53 -d $IP --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
18. done
19.
20. for port in $SERV_UDP; do
21. if test $port -eq 53
22. then
23. $IPT -A INPUT -i $IF -p udp -s $NET --sport $port -d $IP --dport $port -m state --state NEW,ESTABLISHED -j ACCEPT
24. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $port -m state --state ESTABLISHED -j ACCEPT
25. else
26. $IPT -A INPUT -i $IF -p udp -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT
27. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
28. fi
29. done
30.
31. for port in $ SERV_TCP; do
32. $IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT
33. $IPT -A OUTPUT -o $IF -p tcp ! --syn -s $IP --sport $port -d $NET --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
34. $IPT -A INPUT -i $IF -p tcp ! --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state ESTABLISHED -j ACCEPT
35. done
36.
37. $IPT -A INPUT -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_INPUT: "
38. $IPT -A INPUT -i $IF -d $IP -j DROP
39. $IPT -A OUTPUT -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_OUTPUT: "
40. $IPT -A OUTPUT -i $IF -d $IP -j DROP
41. $IPT -A FORWARD -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_FORWARD: "
42. $IPT -A FORWARD -i $IF -d $IP -j DROP



6. Phân tích:
- Dòng 1, 2, 3: Đã phân tích trong bài trước (case 1).

- Dòng 4: Ấn định giá trị của biến NET. Đối với iptables, việc ấn định NET=any/0 và ứng dụng trong firewall script không cần thiết (bị thừa) vì nếu không ấn định cụ thể giá trị source (-s) và destination (-d) thì được ngầm hiểu là any/0. Giá trị NET dùng ở đây với mục đích làm rõ các luật trên phương diện gói tin đến và đi.

- Dòng 5: Ấn định giá trị của biến DNS. Đây là một giá trị quan trọng cho trường hợp firewall trên máy đơn và có dịch vụ cho công cộng. Những dịch vụ cho công như web, mail... đều trực tiếp tương tác với cơ chế biên giải giữa IP và tên domain. Giá trị của biến DNS ở đây chính là các IP của một DNS server (biểu thị cho primary DNS và secondary DNS). DNS server này có thể là DNS do ISP cung cấp hoặc chính authoritative DNS -1- do bạn tạo ra. Các giá trị trong biến DNS này tách rời bởi khoảng trống (space) để tiện việc chạy lệnh sau này.

- Dòng 6: Ấn định giá trị của biến SERV_TCP. Biến SERV_TCP chứa giá trị các cổng dịch vụ ở giao thức TCP được firewall mở và kiểm soát. Các giá trị này tách rời bởi khoảng trống. Bạn có thể thêm, bớt các giá trị tùy thích. Nên lưu ý cách ấn định giá trị các cổng trong biến SERV_TCP chỉ là một cách (trong nhiều cách), bạn có thể khai triển tùy thích, miễn sao iptables "biết được" những cổng nào cần mở và cần kiểm soát. Sử dụng phương thức này chỉ thích hợp cho các cổng dịch vụ có tính chất tương tự nhau và bạn muốn kiểm soát các cổng với chế độ tương tự nhau. Cách ứng dụng khác là ấn định mỗi luật một dòng thay vì nhóm lại trong vòng lặp.

- Dòng 7: Ấn định giá trị của biến SERV_UDP. Tương tự như trên, biến SERV_UDP chứa các giá trị cổng dịch vụ ở giao thức UDP được firewall mở và kiểm soát. Riêng phần biến SERV_UDP này có chứa cổng 53 mang tính chất khá đặc biệt so với các cổng dịch vụ khác. Vấn đề này sẽ được bàn sâu hơn cho dòng 20, 21, 22. Tất nhiên bạn không phải quan tâm đến nó nếu bạn không cung cấp dịch vụ DNS từ máy chủ của mình.

- Dòng 8: Ấn định giá trị của biến HI_PORTS. Trong bài viết cho case 1, giá trị này không được nêu lên và sử dụng một cách cụ thể. Trái lại, nó được sử dụng ở đây với mục đích làm rõ các luật bảo vệ và kiểm soát những gói tin ra / vào cần được huy động tới giá trị của biến HI_PORTS này. Cần nói thêm, giá trị của biến HI_PORTS trải dài từ cổng 1024 đến cổng 65535 là các cổng thuộc chuỗi "high ports" hay "unprivileged ports". Mở một socket trong chuỗi cổng này không cần đến quyền hạn root (trên *nix nói chung) và đây là một trong những điểm quan trọng của việc áp đạt chuỗi HI_PORTS trong firewall script sau này.

- Dòng 10, 11, 12, 13: Đã phân tích trong bài trước (case 1).

- Dòng 15-18: Bốn dòng này thuộc một vòng lặp, đặc biệt dùng để xác lập các dòng luật cho phép máy đơn (ở trường hợp này) liên hệ đến các DNS servers (đã ấn định ở biến $DNS ở trên). Đây là nhóm luật hết sức quan trọng và sẽ được các chương trình cung cấp dịch vụ trên mày dùng đến thường xuyên cho nên việc xác định luật này đầu tiên là việc cần thiết.

- Diễn dịch nôm na vòng lặp của dòng 15, 16, 17 và 18 như sau: với mỗi giá trị thuộc biến $DNS, chạy hai dòng 16 và 17 cho đến khi không còn giá trị nào nữa.

- Dòng 16 có ý nghĩa như sau: cho phép các gói tin với giao thức UDP đi ra ngoài bằng IP hiện có xuyên qua IF. Các gói tin này được khởi tạo từ một socket thuộc chuỗi HI_PORTS (nguồn --sport) và đi đến các địa chỉ DNS server đã ấn định trong biến $DNS đến cổng 53 (đích --dport). Thêm vào đó, các gói tin này phải ở tình trạng NEW (trong state table được iptables quản lý). Điều này có nghĩa firewall cho phép máy chủ -2- này khởi tạo các truy cập đến các DNS server đã ấn định (xxx.xxx.xxx.xxx và yyy.yyy.yyy.yyy).

- Dòng 17 có ý nghĩa như sau: cho phép các gói tin với giao thức UDP từ các DNS server đã ấn định được đi đến IP hiện có xuyên qua IF. Các gói tin này được phép trả lời từ cổng 53 của DNS server ấy. Các gói tin ở dạng trả lời này phải ở tình trạng ESTABLISHED (trong state table được iptables quản lý). Điều này có nghĩa firewall cho phép các DNS server đã được ấn định trả lời các truy cập được khởi tạo từ máy chủ. Các gói tin ở tình trạng NEW đến từ các DNS server sẽ bị từ chối.

- Dòng 20-29: tương tự như nhóm dòng 15-18, dòng 20-29 thuộc một vòng lặp để xác lập luật cho các cổng thuộc biến $SERV_UDP cho giao thức UDP. Trong vòng lặp này chứa một một cụm điều kiện cách (if / else) để thử nghiệm và ứng dụng đúng luật thích ứng cho cổng dịch vụ.

- Diễn dịch nôm na vòng lặp 20-29 như sau: với mỗi giá trị thuộc biến $SERV_UDP, chạy các dòng lệnh 23 và 24 nếu một trong những giá trị thuộc biến $SERV_UDP là 53. Nếu không thì chạy các dòng lệnh 26 và 27 cho đến khi không còn giá trị nào nữa.

- Dòng 23 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi vào từ bất cứ nơi đâu từ cổng 53 đến cổng 53 của máy chủ. Các gói tin này phải đi đến $IP hiện có xuyên qua $IF và phải ở tình trạng NEW.

- Dòng 24 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi ra từ cổng 53 của máy chủ đến cổng 53 của máy đã đòi hỏi truy cập và đã được firewall tiếp nhận ở dòng 22. Các gói tin đi ra ngoài này phải ở tình trạng ESTABLISHED.

- Dòng 26 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi vào từ cổng nào đó thuộc dãy $HI_PORTS đến cổng đã ấn định trong biến $SERV_UDP của máy chủ. Các gói tin này phải ở tình trạng NEW.

- Dòng 27 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi ra từ cổng đã ấn định trong biến $SERV_UDP (và không phải là cổng 53) của máy chủ đến cổng nào đó thuộc dãy $HI_PORTS dùng để truy cập và đã được firewall tiếp nhận ở dòng 25. Các gói tin đi ra ngoài này phải ở tình trạng ESTABLISHED.

- Dòng 31-35: tương tự như nhóm dòng 20-29. Đây cũng là một vòng lặp dùng để xác lập luật cho các cổng thuộc biến $SERV_TCP cho giao thức TCP. Vòng lặp này không chứa cụm điều kiện cách như nhóm dòng 20-29 vì các cổng dịch vụ đã ấn định trong biến $SERV_TCP mang tính chất tương tự nhau -3-.

- Diễn dịch nôm na vòng lặp 31-35 như sau: với mỗi giá trị thuộc biến $SERV_TCP, chạy các dòng 32, 33 và 34 rồi lặp lại cho giá trị kế tiếp trong biến $SERV_TCP cho đến khi không còn giá trị nào khác.

- Dòng 32 có ý nghĩa như sau: các gói tin ở dạng TCP với cờ hiệu (TCP Flag) là SYN -4- đi vào từ bất cứ nơi nào từ một cổng ở dãy $HI_PORTS đến $IP hiện có xuyên qua $IF để đến cổng $port (giá trị hiện tại của vòng lặp) và ở tình trạng NEW thì tiếp nhận.

- Dòng 33 có ý nghĩa như sau: các gói tin ở dạng TCP không mang cờ hiệu là SYN đi từ $IP hiện có từ cổng $port (giá trị hiện tại của vòng lặp) trả lời cho gói tin yêu cầu truy cập ở trên (đi ra) và ở tình trạng ESTABLISHED thì tiếp nhận.

- Dòng 34 có ý nghĩa như sau: các gói tin ở dạng TCP với cờ hiệu không phải là SYN đi từ nơi gởi gói tin yêu cầu truy cập trên (tiếp tục) đi vào đến cổng $port của $IP hiện có và ở tình trạng ESTABLISHED thì tiếp nhận.

- Dòng 37-42: clean up rules. Đã phân tích ở case 1.


7. Tổng lượt dạng firewall trên:
Đây là dạng firewall được thiết lập cho một máy đơn hỗ trợ dịch vụ. Điểm cốt lõi và khác biệt giữa dạng này và dạng máy đơn không dịch vụ (như ở case 1) là máy đơn hỗ trợ dịch vụ tiếp nhận yêu cầu truy cập và chỉ trả lời yêu cầu truy cập khi những yêu cầu thoả mãn những luật iptables đưa ra (ngoại trừ luật tạo ra ở dòng 16 và 17). Trong khi đó, máy đơn của case 1 mang vai trò yêu cầu truy cập và các dịch vụ bên chỉ có thể trả lời nếu máy đơn này đòi hỏi.

Thử xét luật ở dòng 16 và 17 thì thấy, máy chủ này cần phải khởi tạo một xuất truy cập đến DNS server (và chỉ cụ thể những DNS server được ấn định trong biến $DNS mà thôi). Các DNS server này cũng chỉ có thể trả lời yêu cầu từ máy chủ khi máy chủ "hỏi" và tất nhiên, các DNS server khác sẽ không có cơ hội "trả lời" vì chúng không nằm trong phạm vi cho phép. Điều này cho thấy, máy chủ của chúng ta tin tưởng vào thông tin mà DNS server đã ấn định cung cấp. iptables không thể hạn chế thông tin của các DNS server này cung cấp, ngay cả khi chúng bị hư hoại (poisoned cache chẳng hạn). Ví dụ, www.mypage.net giả định được biên giải thành 123.123.123.123 nhưng DNS server ấy bị nhân nhượng nên www.mypage.net được biên giải thành 124.124.124.124 chẳng hạn thì máy chủ của chúng ta vẫn tiếp nhận gói tin chứa các thông tin này (nếu như chúng thoả mãn các điều kiện iptables đặt ra trên cấp độ ip).

Dòng 23 và 24 có vài điểm cần phân tích. Luật đưa ra ở hai dòng này dùng để kiểm soát và thoả mãn giao thức giữa dịch vụ DNS chạy trên máy chủ của chúng ta và các DNS server khác (server to server). Bởi vậy, thông tin đi và đến xuyên qua cổng 53 từ hai phía (thay vì từ một cổng thuộc $HI_PORTS đến cổng 53 và ngược lại). Đó là lý do tại sao chúng ta phải dùng đến cụm điều kiện cách if / else ở đây. Điểm cốt lõi của hai dòng lệnh này là đưa ra luật kiểm soát cho dịch vụ DNS giữa server và server. Máy chủ cung cấp dịch vụ DNS hầu hết chỉ cần "lắng nghe" và "trả lời" trên cổng 53 UDP ngoại trừ trường hợp một yêu cầu nào đó quá lớn hoặc một yêu cầu cho zone transfer thì mới cần đến cổng 53 TCP -5-

Dòng 26 và 27 tương tự như trên nhưng luật đưa ra dùng để kiểm soát gói tin giữa các clients từ bên ngoài và máy chủ (client to server). Tất nhiên các luật này không ứng dụng cho dịch vụ DNS vì đi đến hai dòng này đã thoát ra ngoài cụm điều kiện cách dùng cho DNS ở trên. Ở đây, thông tin đi xuyên qua cổng 53 của máy chủ và $HI_PORTS của máy con.

Dòng 32, 33, 34 có một số điểm lý thú cần bàn đến. Dựa trên tính "stateful" của giao thức TCP, iptables có thể kiểm soát các gói tin TCP sâu sát hơn UDP rất nhiều.

- Dòng 32 chỉ định rất cụ thể là các gói tin ở tình trạng NEW -6- và có tcp-flags là SYN,RST,ACK SYN thì mới được tiếp nhận. Điều này có nghĩa: một yêu cầu truy cập hoàn toàn mới bằng giao thức TCP thì phải có SYN bit và đối với iptables, gói tin khởi đầu cho một cuộc truy cập hoàn toàn mới vì nó chưa hề có trong bảng theo dõi của netfilter (conntrack table). Vậy nếu một gói tin muốn đi vào (truy cập) nhưng chưa hề có trong bảng theo dõi của netfilter (NEW) và không có SYN bit thì sao? Câu trả lời là tất nhiên iptables sẽ chặn nó lại như theo luật đưa ra ở dòng 32 và đây là điều tốt vì các truy cập hợp lệ (legitimate request) không thể có trường hợp một request mới mà không khởi đầu từ SYN. Trường hợp gói tin ở tình trạng NEW nhưng không có SYN bit rất hiếm thấy (ngoại trừ cố tình tạo ra gói tin ở dạng này để thử thâm nhập). Những gói tin ở trường hợp này đôi khi xuất hiện nếu bạn thiết kế hệ thống "high availability" -7- cho nhiều firewall và các firewall này vì lý do nào đó "lỡ" không chuyển giao các "state" của những gói tin hiện lưu hành xuyên qua firewall nên một gói tin nào đó đang ở tình trạng ESTABLISHED với firewall này có thể ở tình trạng NEW với firewall kia. Nếu iptables nằm trong vùng làm việc của các firewall trên thì thỉnh thoảng sẽ va phải một số gói tin như thế và đây là trường hợp (legitimate) rất ít xảy ra.

- Dòng 33 và 34 dùng để hỗ trợ dòng 32 và tiêu điểm của luật trên hai dòng này là dấu chấm thang (!) đi trước --syn. Chuyện gì sẽ xảy ra ở đây? Ở dòng 32, chúng ta ấn định các gói tin TCP đi vào mang SYN flag và ở tình trạng NEW thì được tiếp nhận, vậy sau khi được tiếp nhận thì chuyện gì tiếp tục xảy ra? Câu trả lời nằm ở dòng 33:

+ các gói tin đi ra ngoài để trả lời mà không mang SYN flag -8- và ở tình trạng ESTABLISHED thì được tiếp nhận. Điều cần nhấn mạnh ở đây là gói tin trả lời đi từ máy chủ của chúng ta không nên là gói tin mang SYN flag bởi vì không có lý do gì để máy chủ phải gởi yêu cầu truy cập đến một máy con nào đó trên Internet. Máy chủ chúng ta dùng để tiếp nhận và trả lời các yêu cầu truy cập cho nên luật ở dòng 33 ngầm chứa một quy định rất khắc khe: không những luật firewall cho máy chủ này chỉ tiếp nhận những yêu cầu đi vào một cách hợp lệ mà còn ngăn ngừa những lưu thông đi ra từ máy chủ một cách thiếu hợp lệ (thử hình dung vì lý do gì đó, máy chủ của chúng ta bị biến thành "zombie" và liên tục gởi SYN request đến các máy khác).

+ tình trạng ESTABLISHED kèm theo trong lệnh này càng nâng cao mức khắc khe. Đối với conntrack table lúc này, gói tin đi ra từ máy chủ để trả lời một yêu cầu truy cập nào đó phải thuộc dạng ESTABLISHED. --syn ở đây ứng dụng cụ thể cho gói tin thuộc giao thức TCP và --state ESTABLISHED ở đây ứng dụng cụ thể cho tính "stateful" của netfilter.

- Dòng 34 tiếp nối hai dòng lệnh trên. Ở giai đoạn này, gói tin đi vào máy chủ và thuộc xuất truy cập hiện tại phải ở tình trạng ESTABLISHED và không mang SYN flag nữa và đây chính là điều được dòng 33 áp đặt. Từ lúc này trở đi, trong suốt xuất truy cập, luật của dòng 33 và 34 điều tác và kiểm soát lưu thông giữa máy con và máy chủ của chúng ta. Cụ thể hơn:

+ nếu cũng từ một IP (cùng một client) gởi một gói tin mang SYN flag và hợp lệ thì nó sẽ được xếp loại NEW và được dòng lệnh 32 "xét xử".

+ nếu cũng từ một IP (cùng một client) gởi một gói tin mang một TCP flag nào đó thiếu hợp lệ và không nằm trong tình trạng được theo dõi bởi conntrack table thì nó bị loại trừ bởi các dòng trong nhóm 37-42 hoặc được quy chế mặc định của firewall xử (còn nhớ -P?).

8. Mở rộng:
Mở rộng? rộng thế nào? smilie. Khó có thể trả lời câu hỏi này thoả đáng vì không có sự cố hoặc nhu cầu thì khó biết được giải pháp? (no solution for unknown problem). Tuy nhiên có vài vấn đề có thể mở rộng một cách tổng quát và ứng dụng cho đa số các trường hợp.

8.1 Vấn đề chung cho mọi giao thức:
8.1.1 Vấn đề các gói tin ở tình trạng INVALID:
Như đã phân tích các tình trạng NEW,RELATED,ESTABLISHED,VALID trong bảng theo dõi của netfilter ở bị chú số 6 (bên dưới). Các gói tin ở tình trạng NEW,RELATED,ESTABLISHED có thể được tiếp nhận tùy theo hoàn cảnh. Tuy nhiên, gói tin ở tình trạng INVALID trên bình diện SPI (xem chú thích về SPI ở case 1), không thể được tiếp nhận với bất cứ lý do nào. Bởi vậy, hai dòng luật như sau có thể đưa vào phía trên dòng 15:


Code:
$IPT -A INPUT -m state --state INVALID -m limit --limit 1/s -j LOG --log-prefix "INVALID_STATE: "
$IPT -A INPUT -m state --state INVALID -j DROP


Dòng trên dùng để log và dòng kế tiếp chính thức cản các gói tin thuộc dạng này. Điểm cần chú ý ở đây là hai dòng lệnh trên không quy định cụ thể loại giao thức nào (bằng thông số -p) cho nên các luật này ứng hiệu cho mọi giao thức. Dòng trên cản phần lớn các gói tin "lạc loài" đi vào firewall với chủ đích hoặc vô tình. Cách áp đặt luật này phía trên dòng 15 không những log và cản các gói tin vi phạm cụ thể mà còn mang tính hiệu năng. Các gói tin vi phạm sẽ bị cản ngay tại vị trí này thay vì tiếp tục đi xuống cho đến khi nào trùng với một luật xử lý nào đó, nếu không thì chúng sẽ tiếp tục đi xuống đến tận chuỗi "clean-up" rule (rồi cũng sẽ bị log và cản). Để duy trì tính an toàn, chúng không nên được phép đi vào.

8.1.2 Vấn đề mạo danh IP của máy chủ:
Kỹ thuật mạo danh IP của một máy nào đó được gọi là "spoofing" theo thuật ngữ chuyên môn. "Spoofing" có nhiều dạng và nhiều mục đích nhưng ở đây chúng ta chỉ đề cập đến trường hợp "ai đó" từ Internet mạo danh địa chỉ của máy chủ chúng ta với mục đích "lừa" firewall mà lẻn vào. Thủ thuật này có độ thành công rất cao khi "thử nghiệm" trên các máy chủ và ngay cả các firewall nếu không điều chỉnh cẩn thận. Thử xét:


Code:
$IPT -A INPUT -i $IF -s $IP -d $IP -m limit --limit 1/s -j LOG --log-prefix "SPOOFING: "
$IPT -A INPUT -i $IF -s $IP -d $IP -j DROP


Các gói tin đi từ bên ngoài vào xuyên qua $IF và từ $IP không thể đến $IP được. Vả lại, làm sao có thể có gói tin được chính IP của máy chủ chúng ta tạo ra lại đi vào từ Internet? Nên nhớ, các gói tin được tạo ra ngay trên chính máy chủ cho chính máy chủ đều đi xuyên qua địa chỉ loopback (127.0.0.1) xuyên qua loopback interface (lo), cho nên, các gói tin đi từ bên ngoài mà mang IP của chính máy chủ chúng ta thì chắc chắn thuộc dạng "spoofing". Tất nhiên để có thể lẻn vào bằng phương thức "spoofing" này, kẻ muốn xâm nhập cần nhiều dữ kiện và điều kiện hơn là chỉ đơn thuần "spoofing" vì SPI là hàng rào cản đầu tiên (xem INVALID state ở trên).

8.2 Vấn đề thuộc giao thức TCP:
8.2.1 Loại trừ các truy cập mang tính thiếu hợp lệ
Thử mở rộng một vài TCP flags như đã bàn đến trong phần 7 ở trên -9-


Code:
a. $IPT -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -s $NET -j DROP

Một gói tin mang tcp flag SYN và FIN cùng một lượt không thể là một gói tin bình thường và hợp lệ. SYN-FIN chỉ thường thấy ở các thao tác rà cổng (port scan) hoặc được dùng với ý định không trong sáng. Gói tin ở dạng này nên loại trừ trước khi đi sâu vào hệ thống. Nếu cần phải log, bạn chỉ cần áp đặt một dòng luật tương tự với target là LOG ở trên.


Code:
b. $IPT -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -s $NET -j DROP

Một gói tin mang tcp flag FIN và RST cùng một lượt cũng có thể được xem bất hợp lệ. FIN flag trong một gói tin hợp lệ dùng để thông báo đầu bên kia dòng tin được chấm dứt để xuất truy cập được kết thúc đúng quy cách. Trong khi đó, RST flag dùng để "xé" ngang một xuất truy cập bất chợt. Trường hợp FIN và RST cùng trong một gói tin là điều bất thường và không nên tiếp nhận.

Trường hợp a, b và các trường hợp tương tự đều có thể tạo những tác động không tốt đến dịch vụ trên máy chủ. Chúng khiến cho hệ thống trên máy chủ phải làm việc nhiều hơn một cách không cần thiết và một số trường hợp các gói tin được "nắn ép" cẩn thận có thể dung hại nặng nề đến hệ thống. Tương tự như đã phân tích ở phần 8.1, hai dòng này nên đặt trên dòng 15 (hoặc trên các dòng lệnh bắt đầu cho phép tiếp nhận gói tin) để mang lại tính cụ thể và hiệu năng khi đưa ra các luật cụ thể.

8.2.2 Cản và log cụ thể cho TCP:
Trên dòng chúng ta cho phép các gói tin TCP đi vào phải mang SYN flag và ở tình trạng NEW. Tất nhiên, các gói tin không thoả mãn quy định trên sẽ bị log và cản ở dòng luật 37, 38. Nếu chúng ta không cần phải log chi tiết chuyện gì xảy và thì đoạn firewall script ở trên vừa đủ để hoạt động. Tuy nhiên, nếu chúng ta cần log và cản các gói tin vi phạm một cách cụ thể thì sao?


Code:
$IPT -A INPUT -p tcp ! --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -m limit --limit 1/s -j LOG --log-prefix "INVALID_SERVICE_REQUEST: "
$IPT -A INPUT -p tcp ! --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j DROP


Hai dòng trên là câu trả lời. Các gói tin TCP không mang SYN flag mà ở tình trạng NEW thì bị log và bị cản một cách cụ thể. Hai dòng này có thể được đưa vào phía trên dòng 32 (còn nhớ đến tính quan trọng với thứ tự của các luật?). Tất nhiên, tính cụ thể và hiệu năng sẽ được hình thành nếu áp đặt chúng ở đúng vị trí.

8.2.3 Loại trừ các truy cập hợp lệ nhưng nguy hại
Có lẽ bạn sẽ hỏi, tại sao các truy cập đã hợp lệ mà lại có thể nguy hại. Cho đến lúc này, chúng ta chỉ áp đặt các luật để cản những gói tin bất hợp lệ. Tuy nhiên, không nhất thiết các gói tin hợp lệ trên bình diện giao thức cũng hợp lệ trên bình diện tinh thần. Trường hợp điển hình nhất là phương thức xử dụng các gói tin hợp lệ để làm cạn kiệt tài nguyên của máy chủ. Thử hình dung trường hợp 1000 truy cập đến máy chủ trong vòng vài giây (chẳng hạn),
- liệu máy chủ đủ sức đáp ứng hay không?
- trong 1000 truy cập này, có bao nhiêu truy cập với "thiện ý" và bao nhiêu với "ác ý"?
- làm sao phân biệt và xử lý những truy cập "ác ý" trong mớ 1000 truy cập ấy?

Trên thực tế, khó có thể phân biệt một cách chính xác các truy cập thiện ý hoặc ác ý nhưng chúng ta có thể biết được những truy cập thiện ý thường có biên độ nhất định -10-

8.2.3.1 Giới hạn truy cập với "connection rate"
"Connection rate" có thể thực hiện bằng chọn lựa -m limit cho bất cứ giao thức nào. Chúng ta chỉ đề cập ở đây cho giao thức TCP và sẽ ứng dụng cho các giao thức khác theo ý muốn. Thử đổi dòng 32 từ:


Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT


trở thành:


Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m limit --limit 3/s --limit-burst 5 -m state --state NEW -j ACCEPT



Chuỗi -m limit --limit 3/s --limit-burst 3 dùng CONFIG_IP_NF_MATCH_LIMIT trên netfilter, một "match" trong gói căn bản và đã được tích hợp vào Linux kernel. "limit match" này ảnh hưởng lớn lao đến dòng lệnh trên bình diện giới hạn "connection rate". Chuỗi này ấn định các gói tin mang SYN flag từ một IP nào đó truy cập đến cổng dịch vụ của máy chủ ở tình trạng NEW. Trong chuỗi -m limit --limit 3/s --limit-burst 3 này, khi ứng dụng trong dòng lệnh, một gói tin sẽ được xử lý theo cơ chế:
--limit-burst ấn định giá trị số lần (cho phép hoặc không cho phép) một gói tin được đi đến bước kế tiếp trong luật (-j ACCEPT hoặc -j DROP hoặc bất cứ "jump to" nào). Mỗi giá trị của --limit-burst là một "giấy phép", mỗi packet trùng với luật này sẽ dùng hết một "giấy phép". Khi --limit-burst bằng 0, gói tin trùng với luật đã hết "giấy phép", thì mọi gói tin mới đi vào dù có trùng với luật quy định hay không đều sẽ không thể "jump" đến target ACCEPT (và do đó sẽ bị DROP bởi policy của firewall hoặc các luật đi theo sau). Vì lý do này, --limit 3/s chính là cơ chế "nạp" giấy phép lại cho --limit-burst. Chuỗi này có ý nghĩa là mỗi 1/3 giây, sẽ tăng --limit-burst lên 1, cho đến khi đạt giá trị tối đa ban đầu (= 3 trong trường hợp này) thì sẽ không tăng nữa.

Cụ thể hơn, tưởng tượng đang có một máy con nào đó truy cập vào máy chủ của chúng ta với tốc độ 50 packet/giây, có nghĩa là cứ 1/50 giây có một packet đi đến máy chủ. Rule trên sẽ xử lí như sau:
-Trong vòng (1/50)*5 = 1/10 giây đầu tiên, 5 giấy phép ban đầu đã được sử dụng hết, gọi thời điểm này là T1 (chẳng hạn). Từ thời điểm T1 trở đi cho đến thời điểm T1+1/3 giây, tất cả packet từ IP này truy cập vào máy chủ sẽ bị DROP.
-Tại thời điểm T1 + 1/3 giây, do qui định của chuỗi --limit 3/s, một giấy phép được nạp vào cho --limit-burst, nhưng gần như ngay tức khắc, giấy phép này được một packet của máy A sử dụng và do đó --limit-burst lại trở về 0 (tiếp tục hết "giấy phép"). Cứ tiếp tục như thế, sau 1/3 giây, sẽ có một packet được chấp nhận và chỉ 1 mà thôi nếu máy A cứ tiếp tục truy cập với tốc độ như trên vào máy chủ.

Nếu máy con ngừng truy cập vào máy chủ thì diễn biến sẽ như sau:
- Cứ sau 1/3 giây, một giấy phép sẽ được nạp vào --limit-burst, và vì bây giờ không còn packet nào được gửi đến do đó --limit-burst sẽ giữ nguyên giá trị. Cứ thể --limit-burst tăng dần cho đến khi chạm quy định ban đầu là 3 thì sẽ ngừng lại, "giấy phép" hoàn toàn ở tình trạng nguyên thuỷ. Trong thời gian --limit-burst tăng lại giá trị ban đầu, nếu máy A lại tiếp tục gửi packet thì những packet này sẽ sử dụng giấy phép trong limit-burst, và lại giảm limit-burst xuống, nếu limit-brust bằng 0 thì tất nhiên firewall sẽ tiếp tục cản các gói tin ở dạng này nếu vẫn tiếp tục vi phạm luật cho đến khi --limit-burst được giải toả (như đã giải thích).

Đây chỉ là một ví dụ minh hoạ ứng dụng -m limit. Bạn cần khảo sát số lượng truy cập đến dịch vụ nào đó trên máy chủ trước khi hình thành giá trị thích hợp cho -m limit. Nên cẩn thận trường hợp một proxy server chỉ có một IP và có thể có hàng ngàn người dùng phía sau proxy; ghi nhận yếu tố này để điều chỉnh limit rate cho hợp lý.

8.2.3.2 Giới hạn truy cập với "connection limit"
"Connection limit" cần huy động đến CONFIG_IP_NF_MATCH_CONNLIMIT có từ patch-o-matic trên website chính của iptables http://www.iptables.org). Module này cần được tải và biên dịch -11- trước khi có thể hoạt động. Ứng dụng tính năng này trên dòng 32 như sau:


Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT


trở thành:

Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -m connlimit ! --connlimit-above 2 -j ACCEPT


-m connlimit ! --connlimit-above 2 quyết định tối hậu đến số phận các gói tin đi vào ngoài các áp đặt đi trước (như gói tin TCP phải mang flag SYN và phải ở tình trạng NEW). Tính linh động nằm ở giá trị đảo (!) phía trước --connlimit-above 2. Dòng lệnh này áp đặt thêm một tầng kiểm soát: các gói tin truy cập này đến từ một IP mà không nhiều hơn 2 xuất truy cập thì tiếp nhận. 3, 4 hoặc hơn xuất truy cập không thể xảy ra từ cùng một máy con (có cùng IP) đến máy chủ. Tính chất này khác hẳn tính chất "connection rate" đã trình bày trong phần 8.2.3.1, "connection limit" dựa trên tính đồng thời (concurrent) của giao thức TCP mà điều tác -12-

8.2.4 Vấn đề độ dài của SYN packet:
Bạn có thật sự paranoid không? Nếu có thì tiếp tục theo dõi phần mở rộng này. Theo RFC 793, SYN packet không mang theo "payload" (dữ liệu) và nếu các hệ thống ứng dụng đúng theo RFC 793 thì SYN packet chỉ có chiều dài tối đa là ở khoảng 40 đến 60 bytes nếu bao gồm các tcp options. Dựa trên quy định này (hầu hết các ứng dụng trên mọi hệ điều hành đều tuân thủ theo quy định của RFC 793), chúng ta có thể hình thành một luật khác cho dòng 32 ở trên:


Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT


trở thành:


Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -m length --length 40:60 -j ACCEPT


Nếu cần, bạn vẫn có thể đưa vào một trong hai chọn lựa "connection rate" hoặc "connection limit" cho dòng lệnh trên để thắt chặt. Điều cần nói ở đây là giá trị -m length --length 40:60 ấn định chiều dài của gói tin SYN của giao thức TCP được firewall chúng ta tiếp nhận. Như đã đề cập ở trên, theo đúng quy định, gói SYN không mang dữ liệu cho nên kích thước của chúng không thể (và không nên) lớn hơn 40:60. Luật trên áp đặt một quy định rất khắc khe để loại trừ các gói SYN lại mang dữ liệu (và đặc biệt mang dữ liệu với kích thước lớn). Theo tôi thấy, những gói tin này rất hiếm thấy ngoại trừ trường hợp cố tình tạo ra hoặc thỉnh thoảng có dăm ba gói "lạc loài" ở đâu vào từ một hệ điều hành nào đó không ứng dụng đúng quy cách. Xử dụng luật này hay không là tùy mức khắc khe của bạn. Cách tốt nhất trước khi dùng, bạn nên thử capture các gói SYN cho suốt một ngày (hoặc nhiều) và mang về phân tích xem có bao nhiêu gói SYN thuộc dạng không cho phép, có bao nhiêu gói tin được xếp loại vào nhóm có chiều dài 40:60 bytes và từ đó mới đi đến quyết định cuối cùng.

8.3 Vấn đề thuộc giao thức UDP:
Giao thức UDP mang tính chất rất khác với TCP cho nên cơ chế điều hoạt và quản lý có những điểm khác biệt. Bởi UDP hoạt động trên căn bản lặp (interation) -13- nên đối với các gói tin thuộc giao thức này có hai điểm cần chú ý:

8.3.1 Vấn đề thuộc số lượng truy cập UDP
Bởi UDP là giao thức thuộc dạng "stateless" nên dịch vụ UDP trên máy chủ chỉ có thể nhận và "cố gắng" thoả mãn yêu cầu. Dịch vụ UDP trên máy chủ:
- không có cách nào kiểm tra xem nguồn truy cập có thật sự hiện hữu hay không; máy chủ cũng không thể phân biệt gói tin UDP đang đi vào là gói đang trả lời ngược lại (thuộc một xuất truy cập hiện có) hay một gói UDP hoàn toàn mới.
- chỉ đơn giản "trả lời" và không cần theo dõi xem gói tin trả lời có đi đến đích hay không.

Dựa trên tính chất này, kẻ tấn công có thể tạo hàng loạt gói tin (1000 yêu cầu trong một giây chẳng hạn) đến một dịch vụ UDP. Dịch vụ này sẽ cần mẫn đặt các yêu cầu vào hàng chờ đợi (queue) và tuần tự xử lý. Tuy nhiên, "queue" của dịch vụ có giới hạn trên căn bản tài nguyên, liệu dịch vụ UDP này chứa được bao nhiêu yêu cầu trên "queue" trước khi máy chủ bị cạn kiệt? Hơn nữa, vì tính "stateless" này mà thông tin chuyển tải xuyên qua UDP nhanh hơn TCP rất nhiều, điều này lại càng tiện lợi cho việc "dội" một dịch vụ UDP trên máy. Trong trường hợp này, -m limit của iptables trở nên hết sức tiện dụng. Thử xem hai dòng 23, 24 trở thành:


Code:
$IPT -A INPUT -i $IF -p udp -s $NET --sport $port -d $IP --dport $port -m state --state NEW,ESTABLISHED -m limit --limit 2/s --limit-burst 2 -j ACCEPT
$IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $port -m state --state ESTABLISHED -m limit --limit 2/s --limit-burst 2 -j ACCEPT


chắc chắn sẽ giúp cho dịch vụ DNS này có đủ thời gian và tài nguyên phục vụ các đòi hỏi về name một cách bình thường. Nên biết rằng, hầu hết các DNS server có thể lưu một bản "cache" cho những IP / Name đã được biên giải cho nên rất hiếm khi một DNS server nào đó đòi hỏi dịch vụ DNS trên máy chủ của chúng ta phải tiếp nhận hơn 2 yêu cầu trong một giây và liên tục 2 lần. Thật ra, giới hạn này vẫn còn rất "dễ chịu" cho một dịch vụ DNS. Tuy nhiên, với các dịch vụ khác cũng dùng giao thức UDP và phục vụ những dòng thông tin ở vận tốc cao (như streaming media chẳng hạn) thì giá trị -m limit trên cần được điều chỉnh cho thích hợp với nhu cầu này.

8.3.2 vấn đề thuộc thực tính của xuất truy cập UDP
Kiểm tra thực tính truy cập cho UDP? Chắc hẳn bạn sẽ hỏi câu này vì ở trên tôi đề cập đến khía cạnh dịch vụ UDP trên máy chủ không có cách nào kiểm tra xem nguồn truy cập có thật sự hiện hữu hay không (nguồn địa chỉ IP). Vậy, giải pháp là sao đây? Phần lớn các cuộc tấn công nghiêm trọng có thể làm tê liệt một dịch vụ bằng giao thức UDP được tạo ra từ các IP giả mạo và các IP thuộc nhóm được IANA phân bố dùng làm IP cho nội mạng -14-. Nếu các địa chỉ dùng để tấn công là các địa chỉ thuộc nhóm public IP thì bạn chỉ có thể giao phó cho -m limit và -m state ở trên. Nếu -m limit được ấn định gắt gao hơn nữa sẽ cản bớt số lượng gói UDP "flood" dịch vụ.

Riêng với các yêu cầu truy cập từ các nhóm IP nội mạng (xem chú thích 14) thì việc lượt bỏ chúng khá đơn giản. Thật ra, việc lọc bỏ này không riêng gì cho giao thức UDP mà còn có thể ứng dụng cho mọi giao thức. Đoạn lệnh sau dùng để thắt chặt vấn đề này:


Code:
NON_NET="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 224.0.0.0/4 240.0.0.0/5 169.254.0.0/16 192.0.2.0/24"
for entry in $NON_NET; do
$IPT -A INPUT -i $IF -s $entry -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_NET: "
$IPT -A INPUT -i $IF -s $entry -j DROP
done



Biến $NON_NET trên có thể đưa vào nhóm biến được ấn định ở phần trên của firewall script và đoạn lặp "for / done" có thể nằm trên dòng 15 (trước luật đầu tiên ấn định ACCEPT). Dòng luật trong đoạn lặp không ấn định cụ thể giao thức (-p) và cũng không ấn định tình trạng (-m state) nên mọi giao thức và mọi tình trạng đều có tác dụng. Lệnh này trông rất đơn giản nhưng hàm chứa tính kiểm soát rất rộng -15-. Nếu bạn thích, thử tính xem có bao nhiêu địa chỉ cả thảy trong nhóm NON_NET này để hình dung một dòng lệnh đơn giản có thể loại bỏ bao nhiêu IP.

Điều căn bản là nên xem xét kỹ lưỡng trước khi quyết định chạy một dịch vụ UDP trên máy chủ, đặc biệt cho trường hợp một máy đơn vừa là firewall, vừa phải cung cấp dịch vụ thì càng cẩn thận hơn. Nguyên tắc bảo mật không khuyến khích máy chủ cung cấp dịch vụ cũng là firewall vì kiện toàn mô hình này cực kỳ khó khăn để bảo đảm hiệu năng và bảo mật.

8.4 Vấn đề thuộc giao thức ICMP:
Giao thức ICMP là một giao thức rất tiện dụng trong các giềng mối hoạt động của mạng. Tuy nhiên, nó cũng là phương tiện căn bản dùng trong các quy trình tìm hiểu và tấn công. Có những loại ICMP không nên dùng trên mạng công cộng nếu bảo mật là vấn đề hàng đầu vì những loại ICMP này tiết lộ quá nhiều thông tin quan trọng của hệ thống chúng ta muốn bảo vệ. Hơn nữa, có những loại ICMP còn là phương tiện để đưa hệ thống chúng ta muốn bảo vệ vào tình trạng nguy hiểm. Ở đây chúng ta thử đưa ra hai vấn đề chính về việc xử lý ICMP cho máy chủ.

8.4.1 Chọn lựa và giới hạn ICMP
ICMP có 15 loại và mỗi loại có ít nhất là một code khác nhau. Riêng ICMP loại 3 có đến 15 code khác nhau. Vậy, chúng ta nên chọn và giới hạn ICMP nào? Sự chọn lựa này mang tính cá nhân vì mỗi người có cách nhìn khác nhau về ICMP. Riêng tôi, ICMP 0, 3, 4, 8 và 11 nên được dùng, số còn lại không nên cho phép ra vào vì chúng mang những tính chất ảnh hưởng đến vấn đề bảo mật cho máy chủ. Nếu đã chọn lựa cụ thể loại ICMP nào được dùng, tại sao không hình thành một luật cụ thể cho ICMP? Thử ứng dụng đoạn kế tiếp:


Code:
OK_ICMP="0 3 4 8 11"
for item in $OK_ICMP; do
$IPTABS -A INPUT -i $IF -s $NET -p icmp --icmp-type $item -j ACCEPT
$IPTABS -A OUTPUT -o $IF -s $IP -p icmp --icmp-type $item -j ACCEPT
done


Đoạn lặp trên thiết lập nhóm luật xử lý giao thức ICMP cho phép các loại ICMP trong biến $OK_ICMP. Thật ra nhóm luật trên chỉ mới giới hạn loại ICMP được dùng nhưng chưa có bất cứ cơ chế nào kiểm soát lượng lưu thông ICMP ra vào. Bởi vậy, muốn vững hơn thì nên đưa vào -m limit để tạo nên mức kiểm soát cụ thể:


Code:
$IPTABS -A INPUT -i $IF -s $NET -p icmp --icmp-type $item -m limit --limit 1/s --limit-burst 1 -j ACCEPT
$IPTABS -A OUTPUT -o $IF -s $IP -p icmp --icmp-type $item -m limit --limit 1/s --limit-burst 1 -j ACCEPT



-m limit trên áp đặt giá trị "rate" rất khắc khe: chỉ tiếp nhận một gói ICMP trong mỗi giây. Với giới hạn này, các cuộc dội ICMP (ICMP flood) gần như vô tác dụng.

8.4.2 Cản ICMP hoặc cản ICMP "một nửa"
ICMP được dùng làm bước đầu cho những cuộc khám phá một host / network. Có rất nhiều công cụ rà cổng (port scan) dựa trên hồi báo của ICMP để quyết định các bước khám phá kế tiếp. Những thủ thuật tìm hiểu "chữ ký hệ thống" (system foot-print) cũng trông cậy rất nhiều vào ICMP. Bạn có "paranoid"? Vậy thì hãy thử thắt chặt thêm xem sao.

8.4.2.1 Cản ICMP
Mức độ cản ở đây chỉ dừng lại ở mức độ cản không cho các gói ICMP khởi tạo và đi vào từ bên ngoài. Máy chủ có thể khởi tạo các gói ICMP (trong giới hạn các loại ICMP cho phép thuộc biến $OK_ICMP) và các máy bên ngoài chỉ có thể "trả lời" các gói ICMP máy chủ tạo ra. Chức năng -m state một lần nữa hữu dụng cho trường hợp này:


Code:
$IPTABS -A INPUT -i $IF -s $NET -p icmp --icmp-type $item -m state --state ESTABLISHED -m limit --limit 1/s --limit-burst 1 -j ACCEPT
$IPTABS -A OUTPUT -o $IF -s $IP -p icmp --icmp-type $item -m state --state NEW,ESTABLISHED -m limit --limit 1/s --limit-burst 1 -j ACCEPT


Bạn có thể thấy gói tin đi vào xuyên qua chuỗi INPUT chỉ có thể được tiếp nhận ở tình trạng ESTABLISHED nhưng gói tin đi ra xuyên qua chuỗi OUTPUT thì có thể được tiếp nhận ở cả tình trạng NEW và ESTABLISHED. -m state hỗ trợ cho -m limit trong trường hợp này tạo nên các luật rất khắc khe cho ICMP. Có những quan điểm cho rằng quá khắc khe với ICMP không tiện dụng cho các hoạt động mạng; lựa chọn thắt chặt hay không là do quyết định của cá nhân bạn.

8.4.2.2 Cản ICMP "một nửa"
Cản "một nửa" là sao nhỉ? Có ai đó hỏi (một là cản, hai là không, không thể có chuyện "một nửa" ở đây). Vậy mà có cách cản "một nửa" nếu bạn thích những ứng dụng "fancy". Bạn còn nhớ -m length ở phần 8.2.4? Đây chính là chìa khoá của câu trả lời:


Code:
$IPTABS -A INPUT -i $IF -s $NET -p icmp --icmp-type $item -m length 42:43 -m limit --limit 1/s --limit-burst 1 -j ACCEPT
$IPTABS -A OUTPUT -o $IF -s $IP -p icmp --icmp-type $item -m length 42:43 -m limit --limit 1/s --limit-burst 1 -j ACCEPT


Thông thường tiện dụng ping gởi đi một gói dữ liệu nào đó để host được ping theo mặc định -16- . Nếu firewall được ấn định như trên, chỉ có gói tin ICMP nào có chiều dài trong khoảng 42 đến 43 bytes thì mới tiếp nhận. Điều này có nghĩa, khi một ai đó thử ping theo mặc định trên MS-DOS prompt hoặc trên một *nix console chắc chắn sẽ không có kết quả vì không thoả mãn kích thước gói tin đã ấn định. Tính "mở một nửa" nằm ở kích thước cụ thể của gói tin. Chỉ có bạn biết kích thước gói tin là bao nhiêu để ping vào máy chủ thành công (đây chính là tính "mở"); đối với mọi người dùng khác họ sẽ không ping vào máy chủ thành công vì hầu hết họ dùng kích thước gói tin theo mặc định (đây chính là tính "đóng").

Có thể có những cá nhân kiên nhẫn ngồi "rà" từng kích thước gói tin hoặc viết một đoạn script để thực hiện quy trình "rà" này nhưng chuyện này chỉ xảy ra nếu cá nhân ấy nghi ngờ máy chủ chúng ta ấn định kích thước gói tin cụ thể. Đối với người dùng bên ngoài, khả năng cản hoàn toàn và cản "một nửa" ở hai phần 8.4.2.1 và 8.4.2.2 không khác gì nhau vì đơn giản không thể "ping" ngay từ đầu. Với các ứng dụng kiểm soát ICMP trên, mối đe doạ của các dạng tấn công dựa trên ICMP hầu như vô hiệu hoá. Tùy ý bạn mà ứng dụng.

9. Thử nghiệm:
Bài viết cho case 2 này sẽ không đưa ra cụ thể quy trình thử nghiệm. Nếu bạn đã đọc kỹ và chú ý từng chi tiết được đưa ra ở trên, bạn hẳn nhận ra có vô số điều cần và nên thử nghiệm. Tính chất phòng bị và bảo vệ máy chủ được phân tích cụ thể cho từng giao thức ở trên; hãy để tính sáng tạo của mình làm việc cho công tác thử nghiệm vậy smilie

10. Kết luận:
Bài viết phân tích case 2 này không trực tiếp phục vụ mục đích tạo một firewall script có sẵn để người dùng xử dụng ngay. Bài viết này mượn iptables firewall script như một thứ lý do để:
- đi vào tính năng của iptables / netfilter
- đi vào những tình huống có thể xảy ra
- mở rộng cách nhìn bảo mật xuyên qua tính năng và hoạt động của một số giao thức thường dùng.

Với tinh thần bảo mật, bài viết quy tụ về một điểm chính: chỉ cho phép lưu thông hợp pháp. Phần bị chú bên dưới có lẽ không chỉ đơn thuần là bị chú mà là một số phân tích mở rộng những điều được phân tích trong thân bài. Nên xem case 2 này là một phương tiện để khám phá và nên khởi đầu mọi khúc mắc bằng câu hỏi "tôi có vấn đề này" và thử hình thành câu hỏi kế tiếp "tôi có thể làm gì để giải quyết". Hay nói một cách khác, bạn cần hiểu rõ vấn đề (problem) trước khi nghĩ đến giải pháp (solution).

Bị chú:
-1- Authoritative DNS: là name server có thẩm quyền trả lời các thỉnh cầu về tên của một domain và các host trong domain này ở cấp độ chủ quyền. Xem thêm trang http://en.wikipedia.org/wiki/DNS) để tham khảo "authoritative DNS".

-2- Cách gọi "máy chủ" ở đây để chỉ cho máy đơn có hỗ trợ dịch vụ mà chúng ta đang phân tích. Đừng nhầm lẫn với một máy chủ nào khác trong case 2 này.

-3- Giao thức cho các cổng dịch vụ như 80, 443, 25, 110, 22 cho ví dụ trên mang tính chất tương tự nhau trên phương diện kết nối. Ví dụ, một client nào đó từ Internet muốn truy cập một trong các cổng dịch vụ trên, giữa client ấy và máy chủ sẽ đi xuyên qua quy trình bắt tay (3 way handshake) bình thường và thiết lập xuất truy cập (connection). Xuất truy cập này không đòi hỏi huy động thêm một hoặc nhiều cổng dịch vụ khác hoặc giao thức khác để hoàn tất xuất truy cập. Giao thức như FTP chẳng hạn, ngoài quy trình bắt tay bình thường xảy ra ở cổng 21 thuộc máy chủ còn phải huy động thêm một cổng khác cho dữ liệu (cổng 20 nếu dùng active ftp hoặc $HI_PORTS nếu dùng passive ftp). Những giao thức tương tự như FTP không có cùng tính chất như các cổng đưa ra trong ví dụ trên.

-4- --syn là cách viết tắt của --tcp-flags SYN,RST,ACK SYN. --tcp-flags là một chọn lựa trong iptables để xử lý các gói tin với giao thức TCP. Một cách tổng quát mà nói, --tcp-flags có hai giá trị tách rời bởi khoảng trống. Với ví dụ này, giá trị thứ nhất là SYN,RST,ACK và giá trị thứ hai là SYN. Giá trị thứ nhất là danh sách các TCP flags bạn muốn iptables duyệt và giá trị thứ nhì là danh sách các TCP flags được ứng hiệu (được iptables kiểm soát và quyết định cho vào hay bị cản dựa trên sự hiện diện của các flags này). Để xác định các TCP flags thích ứng, bạn cần biết rõ mục đích và kết quả của các flags này. Thông thường các truy cập hợp lệ thường khởi đầu bằng --tcp-flags SYN,RST,ACK SYN như ở đây, trong đó các TCP packets dùng để khởi tạo một xuất truy cập phải chứa SYN flag. Xem thêm tài liệu packet-filtering-HOWTO trên website http://www.iptables.org và tham khảo một cuốn sách hay về TCP/IP như cuốn TCP Illustrated I của Richard Stevens chẳng hạn.

-5- Khi có ý định cung cấp dịch vụ DNS trên máy chủ, bạn cần kiện toàn dịch vụ này để có thể đáp ứng mọi yêu cầu hợp lệ. Thông thường dịch vụ DNS lắng nghe trên cổng 53 UDP đủ phục vụ name resolution cho hầu hết các trường hợp vì hiếm khi chiều dài của gói tin (cho các request / repsond) với giao thức DNS lớn hơn 512 bytes. Nếu chiều dài gói tin này hơn 512 bytes thì dịch vụ DNS của máy chủ phải đi xuyên qua cổng 53 TCP và trường hợp này rất hiếm thấy với các thông tin hợp lệ và bình thường (ngoại trừ trường hợp zone transfer giữa DNS). iptables trong bài viết này chỉ đóng vai trò kiểm soát các gói tin đi ra và đi vào cho dịch vụ DNS đã được hoàn chỉnh. Kiện toàn bảo mật cho DNS server ở cấp độ "application layer" là vấn đề cần thiết và quan trọng. Vấn đề này nằm ngoài phạm vi bài viết về tính năng của iptables.

-6- Các tình trạng NEW,RELATED,ESTABLISHED,VALID được theo dõi trong bảng theo dõi của netfilter (hay còn được gọi là conntrack table) có ý nghĩa và ứng dụng rộng hơn các "state" của TCP socket connection (được thấy khi chạy netstat) và rất cụ thể cho netfilter. Một gói tin ở dạng NEW đối với netfilter mang ý nghĩa rộng hơn một gói tin mang SYN flag thuộc giao thức TCP (mặc dù trên bình diện TCP, SYN packet tương tự như NEW packet vì chỉ có gói tin TCP ở tình trạng NEW mới mang flag SYN).

Ví dụ, một gói tin TCP mang flag là ACK chưa hề có trong conntrack table đi vào iptables firewall:
- việc đầu tiên netfilter sẽ ghi nhận: đây là một gói tin "có thể" thuộc dạng NEW và nếu firewall của chúng ta có chứa một luật (trực tiếp hay gián tiếp) chỉ định rằng firewall không thể tiếp nhận các gói tin TCP thuộc dạng NEW mà lại mang TCP flag là ACK thì
- netfilter sẽ xếp loại gói tin này thành INVALID.

Đối với các giao thức "stateless" như UDP, ICMP thì tính ứng hiệu với các tình trạng NEW,RELATED,ESTABLISHED,VALID rất khác so với TCP. Ví dụ, UDP không hề có flags hay sequence number như TCP nên một gói tin UDP chưa hề có trong conntrack table sẽ được xếp loại là NEW và nếu nó thuộc một xuất truy cập đã ghi nhận thì nó được xếp loại ESTABLISHED.

Conntrack (hoặc Connection tracking) là một chức năng rất mạnh và linh động của netfilter. Nếu dùng -m state ấn định connection state song song với tính chất của từng loại giao thức của các gói tin thì có thể tạo ra các luật hết sức vững vàng và hiệu năng cho firewall.

-7- high availability, một thuật ngữ kỹ thuật. Một dịch vụ ở dạng high availability là dịch vụ hiện hữu ở mức cao độ. High availability chỉ thường thấy có (và thật sự có) ở những môi trường enterprise, nơi sự bền bỉ và sự hiện hữu của dịch vụ là đòi hỏi tối quan trọng.

-8- dấu chấm thang (!) đứng trước giá trị nào đó sẽ nghịch đảo (negate) ý nghĩa của giá trị ấy. Cách dùng này có sẵn trong iptables và rất phổ biến trong các "shell" trên *nix và các ngôn ngữ lập trình nói chung.

-9- Ở đây tôi cố gắng tránh việc cung cấp quá nhiều thông tin cho mỗi chọn lựa có thể ứng dụng. Hai ví dụ trên nhằm mục đích minh hoạ mức uyển chuyển và linh động iptables cho phép chúng ta hình thành các luật ứng dụng cho firewall. Để khai triển góc độ này, kiến thức về giao thức TCP và ứng dụng cụ thể cho nhu cầu của từng trường hợp là hai yếu tố tối quan trọng để hình thành các luật ở cấp độ này.

-10- Vấn đề này thuộc phạm vi "trend analysis" các dạng truy cập đến một dịch vụ. Đây là một công tác phức tạp, đòi hỏi công tác quan sát và phân tích. Tổng quát mà nói, một client truy cập vào một trang web trung bình thường mất vài giây và người ấy thường dừng lại ở trang này ít nhất là vài chục giây để lượt qua xem thông tin ở trang này có phù hợp với nhu cầu hay không. Trọn bộ quá trình truy cập mang tính "thiện ý" này có thể kéo dài ít nhất là trên dưới một phút trước khi người dùng ấy tiếp tục gởi yêu cầu truy cập mới. Bằng cách thu thập và phân tích biên độ truy cập của các người dùng, chúng ta có thể hình thành một con số tương đối cho giá trị truy cập thuộc phạm vi "thiện ý" ở đây.

-11- Vá Linux kernel và iptables cho mục đích dùng thêm các module (không thuộc nhóm base của netfilter) rất đơn giản. Sơ lược các bước như sau:
- tải gói patch-o-matic-ng-<yyyymmdd>.tar.bz2 từ website của iptables http://www.iptables.org)
- xả nén gói vá này ở nơi nào đó thích hợp.
- chuyển vào thư mục chứa mã nguồn Linux và chạy: make clean mrproper để dọn dẹp những object cũ có thể tạo trở ngại trước khi vá.
- chuyển vào thư mục chứa mã nguồn iptables và chạy: make distclean
- chuyển vào thư mục chứa các miếng vá sau khi xả nén xong (bước trên)
- chạy lệnh: KERNEL_DIR=<path_to_kernel_src> IPTABLES_DIR=<path_to_iptables_src> ./runme connlimit. Trong đó connlimit chính là miếng vá cần thiết.
- biên dịch lại Linux kernel (tham khảo thêm series 4 bài "Tái biên dịch Linux kernel ở: http://www.diendantinhoc.net/?articl...=tute_nix và các bài tiếp theo)
- tái khởi động máy sau khi biên dịch Linux kernel hoàn tất và thành công
- chuyển vào thư mục chứa mã nguồn của iptables (đã được patch ở trên) và tái biên dịch lại iptables. Xem thêm chi tiết trong hồ sơ INSTALL có trong thư mục chứa mã nguồn của iptables.

-12- Giao thức TCP mang tính đồng thời (concurrent). Mỗi dịch vụ TCP đang hoạt động ở tình trạng "lắng nghe" (LISTEN) trên một cổng dịch vụ nào đó. Tình trạng này duy trì cho đến khi nào dịch vụ này được tắt bỏ hoặc bị tắt bỏ (vì bị treo, chẳng hạn).

Cứ mỗi xuất truy cập từ một máy con vào dịch vụ TCP trên server của chúng ta sẽ,
- được tạo ra một socket riêng biệt và socket này tồn tại cho đến khi xuất truy cập giữa máy con và máy chủ kết thúc.
- mỗi xuất truy cập mang cổng nguồn (source port) khác nhau trên máy con và,
- máy chủ phải có trách nhiệm phục vụ từng xuất truy cập trên từng cổng của máy con.

Dựa trên tính chất này, chúng ta thấy một máy con có thể đòi hỏi nhiều xuất truy cập cùng một lúc và máy chủ có thể đáp ứng yêu cầu này theo đúng tính chất hoạt động của TCP. Tuy nhiên, điểm cần đưa ra ở đây thuộc phạm trù bảo mật là, nếu máy con yêu cầu nhiều xuất truy cập mang tính "ác ý" (như một dạng DoS) chẳng hạn thì sao? Tình trạng có thể xảy ra:
- máy chủ vận động nhiều process để tạo các socket đáp ứng máy con
- máy chủ có thể bị cạn kiệt tài nguyên dự trữ để tạo socket
- dịch vụ được yêu cầu truy cập có thể bị mất hiệu năng vì không đáp ứng kịp với quá nhiều yêu cầu
- các dịch vụ liên hệ bị treo hoặc không thể tiếp tục hoạt động vì tài nguyên trên máy bị cạn kiệt
- các máy con khác không thể truy cập máy chủ vì máy chủ không còn khả năng đáp ứng,
- và điều tệ hại nhất là máy chủ bị hoàn toàn tê liệt vì quá tải.

Nói một cách công bằng, dịch vụ trên máy của cố gắng đáp ứng các yêu cầu theo đúng chức năng nhưng vì không đủ tài nguyên nên phải dẫn đến tình trạng trên. vậy, bao nhiêu tài nguyên thì đủ cho máy chủ? Con số này phải được hình thành từ quá trình theo dõi và đúc kết số lần truy cập, tầng số truy cập... trên máy chủ. Trên bình diện bảo mật, firewall có thể dùng để trợ giúp các dịch vụ bằng cách hạn chế các xuất truy cập "concurrent".

-13- Giao thức UDP mang tính lặp (iteration). Mỗi dịch vụ UDP đang hoạt động trên máy chỉ tiếp nhận yêu cầu từ client ở một cổng (thay vì mở ra socket mới như TCP). Hầu hết dịch vụ UDP trên máy chủ ở trong trạng thái "ngủ" (sleep) cho đến khi một client nào đó gởi yêu cầu truy cập đến, dịch vụ này mới "thức dậy" để trả lời client. Nếu có nhiều client yêu cầu cùng một lúc, các yêu cầu này được sắp hàng và dịch vụ UDP này sẽ trả lời tuần tự nó đã tiếp nhận từng yêu cầu cho đến khi hoàn tất. Header của UDP rất đơn giản so với TCP, hoàn toàn không có cơ chế để kiểm tra đường đi, lối về của các gói tin ngoài thông tin cổng nguồn và cổng đích (source port and destination port). Bởi thế, kiểm tra và quản lý các gói tin UDP nằm ở một bình diện hoàn toàn khác TCP.

-14- Nhóm private IP cho nội mạng, đôi khi còn gọi là "non-routable IP", ám chỉ các IP này không thể route ra ngoài mạng công cộng (thật tế chúng vẫn có thể route được, nhưng chỉ trong nội mạng). Các nhóm private IP này gồm có:
Class A: 10.0.0.0/8
Class B: 172.16.0.0/12
Class C: 192.168.0.0/16
Class D: 224.0.0.0/4
Class E: 240.0.0.0/5
Link Local: 169.254.0.0/16
Test Net: 192.0.2.0/24
IP từ các nhóm này không thể xuất hiện trên mạng công cộng (public network) và tất nhiên không nên cho phép đi vào hệ thống máy chủ. Tham khảo thông tin từ website IANA để nắm thêm chi tiết quy định các network class trên.

-15- Đây chỉ là một đề nghị, hay nói đúng hơn là một chia xẻ từ kinh nghiệm cá nhân. Để hình thành các luật firewall gọn gàng, súc tích và chặt chẽ, có hai nguyên tắc cần nhớ:
- luật nào cho phép thì phải cụ thể tối đa.
- luật nào ngăn cản thì phải tổng quát hết mức.

Để cho phép các gói tin đi vào (hoặc đi ra) và chỉ cho phép những gói tin nào thoả mãn yêu cầu của chúng ta thì luật cho phép phải càng cụ thể càng tốt vì nó loại bỏ những những sơ sót có thể xảy ra khi "cho phép". Trong khi đó, để ngăn cản các gói tin đi vào (hoặc đi ra) thì luật ngăn cản nên tổng quát và bao trùm một tập họp những tình huống, điều kiện mang tính chất tương tự.

-16- Kích thước mặc định của gói tin ICMP gởi đi từ tiện ích "ping" có giá trị tùy theo ứng dụng của hệ điều hành. Ví dụ Windows ping dùng 32 bytes theo mặc định, *nix nói chung dùng 56 bytes. Để ping với kích thước gói tin theo ý muốn thì:
- trên windows: dùng thông số -l (ping -l <size> <host>smilie
- trên *nix: dùng thông số -s (ping -s <size> host>smilie

Tổng kết đoạn script case 2:

[code]
# các thông số cần thiết
IF=`/sbin/route | grep -i 'default' | awk '{print$8}'`
IP=`/sbin/ifconfig $IF | grep "inet addr" | awk -F":" '{print$2}' | awk '{print $1}'`
IPT="/usr/local/sbin/iptables"
NET="any/0"
DNS="xxx.xxx.xxx.xxx yyy.yyy.yyy.yyy.yyy"
SERV_TCP="22 25 80 443 110"
SERV_UDP="

SỬ DỤNG GRUB
Biên soạn bởi: Lâm Vĩnh Niên, (nien.lam -at- gmail -dot- com)
Phiên bản: v1.2 (040115)
Các thay đổi:

v1.2 (040115): bổ sung và sửa chữa

v1.0 (030731): phiên bản đầu tiên

Tài liệu này hướng dẫn cách sử dụng GRUB, một trình khởi động mạnh và linh hoạt dùng cho PC.
Nội dung

1. Giới thiệu về GRUB

1.1. Tổng quát
1.2. Tính năng

2. Cài đặt GRUB

2.1. Nơi tải GRUB xuống
2.2. Cài đặt GRUB trong môi trường Linux

3. Sử dụng GRUB

3.1. Chuẩn bị các tập tin cần thiết
3.2. Thuật ngữ dùng trong GRUB

3.2.1. Xác định thiết bị
3.2.2. Xác định tập tin

3.3. Các tập tin hình ảnh của GRUB
3.4. Cơ chế khởi động dùng trong GRUB
3.5. Tạo ổ đĩa mềm khởi động GRUB
3.6. Cài GRUB trong môi trường nguyên thuỷ của GRUB

3.6.1. Cài GRUB dùng lệnh setup
3.6.2. Cài GRUB dùng lệnh install

3.7. Cài GRUB trong môi trường hệ điều hành giống Unix

3.7.1. Cài GRUB dùng lệnh grub-install
3.7.2. Cài GRUB trong shell grub
3.7.3. Ánh xạ giữa các ổ đĩa BIOS và các thiết bị hệ điều hành

3.8. Khởi động hệ thống với GRUB

3.8.1. Khởi động hệ điều hành trực tiếp
3.8.2. Tải trình nạp khởi động khác
3.8.3. Một số thí dụ

3.8.3.1. Linux
3.8.3.2. FreeBSD
3.8.3.3. NetBSD
3.8.3.4. OpenBSD
3.8.3.5. DOS/Windows

3.9. Cấu hình
3.10. Bảo mật cho GRUB
3.11. Giao diện người dùng của GRUB

3.11.1. Giao diện dòng lệnh
3.11.2. Giao diện thực đơn

3.12. Một số lệnh trong GRUB

3.12.1. Các lệnh chỉ dùng cho thực đơn
3.12.2. Các lệnh chung
3.12.3. Các lệnh dùng ở dòng lệnh và đề mục thực đơn

4. Một số ứng dụng cụ thể và vấn đề thường gặp

4.1. Tạo đĩa mềm khởi động GRUB với giao diện thực đơn
4.2. Khởi động đĩa mềm có nhân Linux
4.3. Tạo đĩa CD khởi động với GRUB
4.4. Khởi động Windows từ đĩa cứng thứ hai
4.5. Khởi động nhiều bản Windows cài đặt trên một đĩa cứng
4.6. Khởi động GRUB từ ntldr
4.7. Khởi động ổ CD
4.8. Khởi động vào các runlevel khác nhau của nhân Linux
4.9. Một số vấn đề khác

5. Tài liệu tham khảo



1. Giới thiệu về GRUB
1.1. Tổng quát

GRUB là trình khởi động máy tính – nó có nhiệm vụ tải nhân và khởi động hệ thống Linux cũng như một số hệ điều hành khác: FreeBSD, NetBSD, OpenBSD, GNU HURD, DOS, Windows 95, 98, Me, NT, 2000 và XP...

Năm 1995, Erich Boley thiết kế GRUB. Năm 1999, Gordon Matzigkeit và Yoshinori K. Okuji kế thừa GRUB thành gói phần mềm GNU chính thức.
1.2. Tính năng

* GRUB hỗ trợ nhiều hệ điều hành – bằng cách khởi động trực tiếp nhân hệ điều hành hoặc bằng cách nạp chuỗi (chain-loading).
* GRUB hỗ trợ nhiều hệ thống tập tin: BSD FFS, DOS FAT16 và FAT32, Minix fs, Linux ext2fs và ext3fs, ReiserFS, JSF, XFS, và VSTa fs.
* GRUB cung cấp giao diện dòng lệnh linh hoạt lẫn giao diện thực đơn, đồng thời cũng hỗ trợ tập tin cấu hình.

2. Cài đặt GRUB
2.1. Nơi tải GRUB xuống

GRUB có sẵn ở ftp://alpha.gnu.org/gnu/grub hoặc các mirror của nó. Tên gói GRUB có dạng grub-version.tar.gz, thí dụ grub-0.93.tar.gz.

Ngoài ra, phiên bản mới nhất của GRUB cũng có thể được tải về qua CVS với kho là :pserver:anoncvs@subversions.gnu.org:/cvsroot/grub và mô-đun là grub, không cần password cho anoncvs. Do đó có thể làm như sau:

Code:
cvs -d :pserver:anoncvs@subversions.gnu.org:/cvsroot/grub login
Password: <ENTER>
cvs -d :pserver:anoncvs@subversions.gnu.org:/cvsroot/grub co grub
cvs -d :pserver:anoncvs@subversions.gnu.org:/cvsroot/grub logout


Một số hệ điều hành cung cấp GRUB dưới dạng đóng gói riêng, chẳng hạn như dạng rpm (có thể tìm thấy trong các bản phân phối Red Hat, SUSE...), dạng deb (trong bản phân phối Debian).
2.2. Cài đặt GRUB trong môi trường Linux

Cần phân biệt 2 bước của cài đặt GRUB: (i) cài đặt trong môi trường hệ điều hành để có thể sử dụng được GRUB và, (ii) cài đặt GRUB để GRUB làm trình khởi động máy tính. Bước 2 sẽ được đề cập trong chương Sử dụng GRUB.

Sau khi tải về một thư mục thích hợp, giải nén bằng lệnh

tar xzvf grub-0.93.tar.gz

Sau đó:

cd grub-0.93.tar.gz
./configure


(Để liệt kê các tuỳ chọn khi biên dịch:

./configure --help | more

)

Tiếp theo:

make
make install


Quá trình này sẽ cài đặt shell grub, chương trình kiểm tra multiboot mbchk, các hình ảnh GRUB (thông thường được cài vào thư mục /usr/share/grub/i386-pc), tài liệu hướng dẫn sử dụng và trang man của GRUB.
3. Sử dụng GRUB
3.1 Chuẩn bị các tập tin cần thiết

Có hai cách cài đặt GRUB làm trình khởi động máy tính: dùng môi trường nguyên thuỷ của GRUB (cách này được khuyên dùng) hoặc dùng môi trường hệ điều hành giống Unix. Để cài đặt GRUB trong môi trường nguyên thuỷ của GRUB, cần tạo đĩa mềm khởi động GRUB. Cài đặt GRUB trong môi trường hệ điều hành giống Unix dùng công cụ grub-install hoặc shell grub, tuy nhiên chúng có thể thăm dò sai BIOS.

Trước khi cài GRUB làm trình khởi động cần chép các tập tin stage1, stage2 và *stage1_5 từ thư mục /usr/share/grub/i386-pc (thư mục hình ảnh) vào thư mục /boot/grub (thư mục khởi động). Trong số các tập tin *stage1_5 có thể chỉ cần chép tập tin thích hợp với hệ thống tập tin của /boot/grub, chẳng hạn chép tập tin e2fs_stage1_5 nếu thư mục này nằm trên ext2 hoặc ext3. Ngoải ra có thể chép tập tin splash.xpm.gz vào thư mục /boot/grub.
3.2. Thuật ngữ dùng trong GRUB
3.2.1. Xác định thiết bị
(thiết-bị[,số-thứ-tự-phân-vùng][,chữ-cái-tiểu-phân-vùng-bsd])

* []: thông số tuỳ chọn
* thiết-bị: fd (ổ đĩa mềm) hoặc hd (ổ đĩa cứng, GRUB không phân biệt IDE hay SCSI hay RAID) theo sau bởi một con số biểu thị số của thiết bị theo BIOS và bắt đầu với 0, ví dụ ổ đĩa cứng IDE sơ cấp được đánh số 0, còn ổ đĩa cứng IDE thứ cấp được đánh số 1. Thứ tự này tương đối tương đương với cách nhân Linux sắp xếp các thiết bị theo chữ cái (a tương ứng với 0, b tương ứng với 1, v.v...). Cũng có thể thiết lập thiết-bị ở dạng thập lục phân hoặc thập phân, thí dụ

(hd0)
(0x80)
(128)

là tương đương nhau.
* số-thứ-tự-phân-vùng: là số thứ tự của phân vùng trên ổ đĩa, cũng bắt đầu với 0, phân vùng mở rộng bắt đầu bằng 4, bất kể số phân vùng sơ cấp thực có trên ổ đĩa.
* chữ-cái-tiểu-phân-vùng-bsd: đại diện cho tiểu phân vùng của BSD, như a hay e.

Cú pháp tắt gọi tiểu phân vùng BSD là (thiết-bị[,chữ-cái-tiểu-phân-vùng-bsd]), trong trường hợp này GRUB sẽ tìm phân vùng PC đầu tiên chứa nhãn đĩa BSD, rồi tìm tiểu phân vùng đưọc yêu cầu.

Thí dụ:

* (hd0): toàn bộ ổ đĩa thứ nhất (hoặc MBR khi cài đặt GRUB)
* (hd0,0): phân vùng thứ nhất trên ổ đĩa cứng thứ nhất (hoặc sector khởi động của phân vùng này khi cài GRUB)
* (hd0,4): phân vùng mở rộng thứ nhất trên ổ đĩa cứng thứ nhất
* (hd1,a): phân vùng BSD a trên ổ đĩa cứng thứ hai; nếu cần xác định cụ thể số PC slice nào được dùng, sử dụng cú pháp như (hd1,0,a), nếu bỏ trống số PC slice, GRUB tìm PC slice đầu tiên có phân vùng BSD a
* (fd0): ổ đĩa mềm thứ nhất

Ở hệ thống có 2 đĩa cứng IDE và 2 đĩa cứng SCSI, trình tự khởi động trong BIOS được thiết lập là "IDE trước SCSI", GRUB sẽ dùng các nhãn sau:

* (hd0) Đĩa cứng IDE thứ nhất
* (hd1) Đĩa cứng IDE thứ hai
* (hd2) Đĩa cứng SCSI thứ nhất
* (hd3) Đĩa cứng SCSI thứ hai

Ngoài ra còn có thiết bị ổ đĩa mạng (nd) nếu khi cài đặt GRUB có bật tính năng hỗ trợ mạng. Có thể dùng chức năng hoàn thành dòng lệnh của GRUB, ví dụ gõ root ( rồi <TAB>, GRUB sẽ liệt kê các ổ đĩa, phân vùng, hay tên tập tin.
3.2.2. Xác định tập tin
Có 2 cách xác định tập tin, bằng tên tập tin tuyệt đối hoặc bằng danh sách khối.

* Tên tập tin tuyệt đối của GRUB giống với tên tập tin tuyệt đối Unix, dùng / làm dấu phân cách thư mục. Ví dụ:

(hd0,0)/boot/grub/menu.lst

có nghĩa là tập tin (hd0,0)/boot/grub/menu.lst nằm ở phân vùng đầu tiên của ổ đĩa cứng thứ nhất. Nếu bỏ qua tên thiết bị trong tên tập tin tuyệt đối, GRUB dùng thiết bị root ngầm định. Thí dụ nếu đã thiết lập thiết bị root, chẳng hạn như (hd1,0), bằng lệnh root thì /boot/kernel có nghĩa là (hd0,1)/boot/kernel.

* Danh sách khối (block list) dùng để xác định tập tin không xuất hiện trong hệ thống tập tin, chẳng hạn như một trình nạp chuỗi (chainloader). Cú pháp:

[offset]+độ-dài[,offset]+độ-dài]...

Thí dụ

0+100,200+1,300+300

GRUB đọc các khối 0 đến 99, khối 200 và khối 300 đến 599.

Nếu bỏ qua offset, GRUB sẽ lấy offset là 0.

Cũng như trong cú pháp tên tập tin, nếu danh sách khối không chứa tên thiết bị thì GRUB sẽ dùng thiết bị root của GRUB. Thí dụ +1 khi thiết bị root là (hd0,1) tương ứng với (hd0,1)+1.

Lệnh blocklist liệt kê danh sách khối của tập tin, ví dụ:

grub> blocklist (hd1,0)/vmlinuz
(hd1,0)1322144+96,1322248+1227

có nghĩa là tập tin vmlinux, nằm ở phân vùng thứ nhất của đĩa cứng thứ hai, chiếm 96 khối kể từ khối 1322144 và 1227 khối kể từ khối 1322248 – có thể thấy rằng tập tin này hơi bị phân mảnh.

3.3. Các tập tin hình ảnh của GRUB
GRUB bao gồm một số hình ảnh: 2 giai đoạn chính, các giai đoạn tuỳ chọn gọi là Giai đoạn 1.5, và 2 hình ảnh khởi động mạng.

Code:
stage1
Giai đoạn 1, là một hình ảnh chính dùng đề khởi động GRUB, kích thước 512 byte.
stage2
Giai đoạn 2, là hình ảnh cốt lõi của GRUB.
e2fs_stage1_5
fat_stage1_5
ffs_stage1_5
jfs_stage1_5
minix_stage1_5
reiserfs_stage1_5
vstafs_stage1_5
xfs_stage1_5

Tất cả các hình ảnh này được gọi là Giai đoạn 1.5.
nbrub
pxebrub
Là các hình ảnh khởi động mạng.

3.4. Cơ chế khởi động dùng trong GRUB
Trên sector thứ nhất của đĩa cứng chứa, ngoài bảng phân vùng, một đoạn mã thực thi được là giai đoạn đầu tiên của quá trình khởi động máy tính, hoặc đoạn mã IPL (initial program load). Đoạn mã chuẩn này là cái mà lệnh fdisk /mbr trên DOS tạo ra. Khi thiết lập trong BIOS quy định khởi động từ đĩa cứng đó, BIOS sẽ trao quyền điều khiển cho IPL hoặc đoạn mã giai đoạn một. Khi đoạn mã chuẩn được nạp, nó sẽ quyết định phân vùng nào là chủ động (active) và trao quyền điều khiển cho đoạn mã thực thi được nằm ở trong hoặc gần sector thứ nhất của phân vùng chủ động. Những gì xảy ra tiếp theo phụ thuộc vào hệ điều hành. Ở các hệ điều hành DOS cũ, phần cốt lõi thi hành được của hệ điều hành nằm ngay tại vị trí đầu tiên của đĩa và được khởi động trực tiếp từ giai đoạn một. Trong các trường hợp điển hình hơn, một chương trình khởi động giai đoạn hai sẽ được nạp và đến lượt nó sẽ biết nơi nào để tìm nhân hoặc các thành phần cốt lõi của hệ điều hành và khởi động chúng. Khi GRUB hoặc một trình khởi động được cài đặt, đoạn mã của trình khởi động đó sẽ thay thế đoạn mã IPL chuẩn. Nó phải vừa vặn trong 512 byte và còn phải chia sẻ chung với bảng phân vùng. Khác biệt chính giữa một trình khởi động và đoạn mã IPL chuẩn là quyền điều khiển sẽ đi đâu tiếp sau đó. Trong trường hợp của GRUB, quyền điều khiển sẽ được trao cho trình Giai đoạn 2 (hoặc Giai đoạn 1.5).

Giai đoạn 1 được cài vào MBR hoặc vào sector khởi động của phân vùng, còn Giai đoạn 2 được đặt trên một hệ thống tập tin. Giai đoạn 1.5 có thể được cài trong một hệ thống tập tin (chẳng hạn như ở phân vùng /boot), trong vùng khởi động của FFS hoặc ReiserFS, và trong các sector ngay sau MBR vì Giai đoạn 1.5 đủ nhỏ và các sector ngay sau MBR thường không được sử dụng. Kích thước của vùng này là số sector cho mỗi head trừ đi 1. Giai đoạn 1.5 hoặc Giai đoạn 2 có thể được đặt ở bất cứ nơi đâu, và Giai đoạn 2 có thể nạp tập tin cấu hình từ bất cứ nơi đâu trên đĩa cứng (tập tin cấu hình không cần phải được đặt trong một hệ thống tập tin).

Vì vậy tất cả công việc mà Giai đoạn 1 phải làm là tải Giai đoạn 2 hoặc Giai đoạn 1.5. Giai đoạn 1 mã hoá vị trí của Giai đoạn 2 (hay Giai đoạn 1.5) ở dạng danh sách khối, nên nó không hiểu bất cứ cấu trúc hệ thống tập tin nào. Vì GRUB hỗ trợ cả chế độ CHS lẫn LBA nên Giai đoạn 1 trong GRUB, sau khi thăm dò thông số và chế độ truy cập của đĩa cứng, chỉ tải sector đầu tiên của Giai đoạn 2 (hoặc Giai đoạn 1.5) và Giai đoạn 2 tự nó tải phần còn lại (tức là tải từ địa chỉ bắt đầu của nó cộng thêm 512 byte).

Giai đoạn 1.5 là cầu nối giữa stage1 và stage2, nghĩa là Giai đoạn 1.5 được Giai đoạn 1 nạp và Giai đoạn 1.5 nạp Giai đoạn 2. stage1 không hiểu bất kì hệ thông tập tin nào nhưng *_stage1_5 hiểu một hệ thống tập tin (chẳng hạn e2fs_stage1_5 hiểu ext2fs. Giai đoạn 1.5 cho phép Giai đoạn 2 có thể được nạp từ một hệ thống tập tin bằng đường dẫn thông thường mà không cần phải dùng danh sách khối. Vì vậy có thể an toàn di chuyển vị trí của stage2 đến một nơi khác (chẳng hạn như khi giải phân mảnh hệ thống tập tin), ngay cả sau khi GRUB đã được cài đặt. Gai đoạn 1 nạp Giai đoạn 1.5 vào bộ nhớ nếu cần. Một số phần cứng cần bước trung gian để nạp Giai đoạn 2, chẳng hạn như khi phân vùng /boot nằm ở vị trí quá 1024 cylinder đầu của ổ cứng hoặc khi sử dụng chế độ LBA.
3.5. Tạo ổ đĩa mềm khởi động GRUB
Là quá trình chép các tập tin stage1 và stage2 từ thư mục hình ảnh vào block thứ nhất và thứ hai trên đĩa mềm. Quá trình này sẽ phá huỷ dữ liệu hiện đang lưu trữ trên đĩa mềm.

Các lệnh để thực hiện điều này trên một hệ điều hành giống UNIX:

# cd /usr/share/grub/i386-pc
# dd if=stage1 of=/dev/fd0 bs=512 count=1
1+0 records in
1+0 records out
# dd if=stage2 of=/dev/fd0 bs=512 seek=1
153+1 records in
153+1 records out
#

3.6. Cài GRUB trong môi trường nguyên thuỷ của GRUB
3.6.1. Cài GRUB dùng lệnh setup
Cài stage1 của GRUB theo cách này sẽ xoá sector khởi động đang được một hệ điều hành sử dụng. Hiện tại GRUB có thể trực tiếp khởi động GNU Mach, Linux, FreeBSD, NetBSD, và OpenBSD, vì vậy dùng GRUB trên sector khởi động thường là an toàn. Nhưng nói chung nên sao lưu sector đầu tiên của phân vùng sắp cài stage1 của GRUB. Điều này không quan trọng lắm nến cài GRUB vào sector đầu tiên của đĩa cứng, vì dễ dàng khôi phục nó (chẳng hạn như chạy fdisk /mbr trong DOS).

Để cài GRUB trong môi trường nguyên thuỷ, vốn là điều được khuyên, cần tạo đĩa khởi động GRUB và khởi động lại máy tính với đĩa khởi động đó. Một khi đã được khởi động, GRUB sẽ trình bày giao diện dòng lệnh.

Đầu tiên, định thiết bị root cho thư mục khởi động:

grub> root (hd0,0)

Có thể dùng lệnh find nếu không chắc phân vùng nào thực sự chứa các tập tin này:

grub> find /boot/grub/stage1

Cần lưu ý là thiết bị root của GRUB không nhất thiết là phân vùng root của hệ điều hành (nếu cần xác định phân vùng root cho hệ điều hành, thêm thông số đó vào lệnh kernel).

Một khi đã thiết lập thiết bị root chính xác, chạy lệnh setup:

grub> setup (hd0)

Lệnh này sẽ cài GRUB lên MBR của ổ đĩa thứ nhất. Nếu muốn cài GRUB vào sector khởi động của một phân vùng thay vì vào MBR, chỉ định phân vùng muốn cài GRUB:

grub> setup (hd0,0)

Nếu cài GRUB vào phân vùng hoặc ổ đĩa không phải là ổ đĩa đầu tiên, cần nạp chuỗi GRUB từ một trình khởi động khác.

Bây giờ có thể khởi động GRUB mà không cần đĩa mềm GRUB.

Nói thêm về lệnh setup:

setup [--force-lba] [--stage2=tập_tin_stage2_hđh] [--prefix=thư_mục] thiết_bị_cài_đặt [thiết_bị_hình_ảnh]

Lệnh này dùng để cài đặt GRUB tự động. setup không truy cập trực tiếp vào đĩa cứng mà gọi embed và install để thực hiện công việc. Trước hết nó kiểm tra xem có một tập tin stage1.5 hay không và có thể nhúng (embed) vào một nơi an toàn hay không, Sau đó, setup sử dụng install, một lệnh linh hoạt hơn, ở hậu trường và cài GRUB vào thiết bị thiết_bị_cài_đặt. Nếu chỉ định thiết_bị_hình_ảnh, nó sẽ tìm các hình ảnh GRUB trong thiết bị thiết_bị_hình_ảnh, nếu không nó sẽ dùng thiết bị root hiện tại được thiết lập bằng lệnh root. Nếu thiết_bị_cài_đặt là một đĩa cứng, nó sẽ nhúng Giai đoạn 1.5 nếu có thể. Tuỳ chọn --prefix chỉ định thư mục đặt các hình ảnh GRUB. Nếu không được chỉ định, GRUB sẽ tự động tìm chúng trong /boot/grub và /grub (dĩ nhiên là trong thiết bị root đã được quy định bởi lệnh root trước đó.)

Nếu có chỉ định, các tuỳ chọn --force-lba và --stage2 được chuyển vào lệnh install.

Thí dụ về cài GRUB lên đĩa cứng với /boot được gán trên phân vùng riêng biệt:

setup (hd0) (hd2,0)

Xuất hiện các thông báo:
Code:
Checking "/boot/grub/stage1" no
Checking "/grub/stage1" yes
Checking "/grub/stage2" yes
Checking "/grub/stage1_5" yes
Running "embed/grub/e2fs_stage1_5 (hd0)" 22 sectors are embedded
Running "install /grub/stage1 d (hd0) (hd0)1+22 p (hd2,0)/grub/stage2 /grub/menu.lst”


Lưu ý: stage1.5 đã được nhúng và (/boot)/grub/stage2 đã thay đổi (cập nhật vị trí tương ứng của stage2 và menu.lst).
3.6.2. Cài GRUB dùng lệnh install

install [--force-lba] [--stage2=tập_tin_stage2_hđh] tập_tin_stage1 [d] thiết_bị_đích tập_tin_stage2 [địa_chỉ] [p] [tập_tin_cấu_hình] [tập_tin_cấu_hình_thực]

Lệnh này khá phức tạp, và không nên dùng nếu không quen thuộc với GRUB – thay vào đó nên dùng setup.

Nói ngắn gọn, lệnh này sẽ thực hiện một cài đặt đầy đủ với giả định Giai đoạn 2 hay 1.5 đã có tại vị trí cài đặt cuối cùng.

Đi vào chi tiết hơn, nó sẽ tải tập_tin_stage1, xác nhận rẳng nó là Giai đoạn 1 đúng số phiên bản của GRUB, cài đặt một danh sách khối để nạp tập_tin_stage2 làm Giai đoạn 2 (nghĩa là tập_tin_stage2 sẽ trao cho Giai đoạn 1 vị trí của Giai đoạn 2). Nếu có tuỳ chọn d, Giai đoạn 1 luôn luôn tìm đĩa thực tế đã cài tập_tin_stage2 hơn là dùng ổ đĩa khởi động. Giai đoạn 2 sẽ được nạp tại địa chỉ địa_chỉ, phải là 0x8000 đối với Giai đoạn 2 thực, và 0x2000 đối với Giai đoạn 1.5. Nếu địa_chỉ không được chỉ định, GRUB sẽ xác định địa chỉ tự động. Sau đó nó viết Giai đoạn 1 đã hoàn chỉnh vào khối đầu tiên của thiết bị thiết_bị_đích. Nếu tuỳ chọn p hoặc tập_tin_cấu_hình được chỉ định, nó sẽ đọc khối đầu tiên của stage2, thay đổi nó bằng giá trị của phân vùng mà ở đó tập_tin_stage2 được tìm thấy (đối với p) hoặc đặt chuỗi tập_tin_cấu_hình vào vùng cho stage2 biết nơi tìm tập tin cấu hình lúc khởi động. Cũng như vậy, nếu tập_tin_cấu_hình_thực được chỉ định và tập_tin_stage2 là Giai đoạn 1.5, thì tập_tin_cấu_hình được vá bằng tên tập tin cấu hình tập_tin_cấu_hình_thực. Để dễ hiểu hơn cho trường hợp nhúng Giai đoạn 1.5: tập_tin_stage2 là vị trí nhúng stage1_5, tập_tin_cấu_hình là vị trí của stage2 (theo lô-gic, stage2 là tập tin cấu hình cho stage1_5), tập_tin_cấu_hình_thực là vị trí của menu.lst. Lệnh install không phát sinh sector bitmap cho stage2, tức là tham số tập_tin_cấu_hình, mà nó cần viết chuỗi tập_tin_cấu_hình và tập_tin_cấu_hình_thực (không ở dạng block bitmap mà ở dạng tên tập tin thuần tuý) tương ứng vào stage1_5 và stage2. stage2 nằm trên hệ thống tập tin, vì vậy tuỳ chọn --stage2 giúp cho việc viết được an toàn hơn.

Lệnh này giữ lại DOS BPB (và đối với đĩa cứng là bảng phân vùng) của sector sẽ được cài Giai đoạn 1.

Lưu ý:

* Một số BIOS bị lỗi cần phải chỉ định tuỳ chọn d cho dù Giai đoạn 2 nằm ở ổ đĩa khởi động hay không Khiếm khuyết này gặp ở: Fujitsu LifeBook 400 BIOS version 31J0103A, HP Vectra XU 6/200 BIOS version GG.06.11.
*

Một số BIOS không trả về bitmap hỗ trợ LBA đúng ngay cả chúng thực sự có hỗ trợ; vì vậy GRUB cung cấp giải pháp để bỏ qua bitmap sai, đó là tuỳ chọn --force-lba. Đừng dùng tuỳ chọn này nếu BIOS không hỗ trợ LBA (chế độ LBA dùng firmware để vượt qua giới hạn 1024 cylinder của BIOS).

Phải chỉ định tuỳ chọn --stage2 trong shell grub nếu không thể tháo gán hệ thống tập tin nơi chứa tập tin stage2. Đối số là tên tập tin trong hệ điều hành.

Thí dụ về sử dụng lệnh install:

root (hd0,1)
embed /boot/grub/reiserfs_stage1_5 (hd0) # or e2fs_stage1_5

(và lưu ý số sector)

install /boot/grub/stage1 (hd0) (hd0)1+<số sector có từ lệnh embed> p /boot/grub/stage2 /boot/grub/menu.lst


(hoặc dùng setup (hd0) )
3.7. Cài GRUB trong môi trường hệ điều hành giống Unix
3.7.1. Cài GRUB dùng lệnh grub-install
Cách này hoàn toàn không được khuyến khích, vì có thể máy tính sẽ không thể khởi động được với GRUB. Thí dụ, hầu hết các hệ điều hành không cho GRUB biết cách ánh xạ chính xác ổ đĩa BIOS sang thiết bị của hệ điều hành, GRUB chỉ đoán cách ánh xạ. Trong hầu hết các trường hợp thì quá trình này thành công, nhưng không luôn luôn như vậy. Do đó GRUB cung cấp tập tin ánh xạ do người dùng định nghĩa device.map; nếu tập tin này cho thấy ánh xạ sai bạn cần phải sửa nó lại. Nếu không may phải cài đặt GRUB trong môi trường hệ điều hành giống UNIX, gọi lệnh grub-install với tư cách siêu người dùng (root). Cách sử dụng rất dễ dàng, bạn chỉ cần chỉ định một đối số về nơi cài đặt GRUB. Đối số có thể là tập tin thiết bị hay ổ đĩa/phân vùng theo GRUB. Cú pháp:

grub-install thiết_bị_cài_đặt

Thí dụ: cài GRUB vào MBR của ổ đĩa IDE thứ nhất trong Linux:

# grub-install /dev/hda

Nếu đây cũng là ổ đĩa BIOS thứ nhất:

# grub-install 'hd(0)'

Các thí dụ trên giả định rằng dùng các hình ảnh GRUB ở thư mục root. Nếu muốn GRUB dùng hình ảnh ở thư mục không phải là thư mục root, cần chỉ định tuỳ chọn --root-directory. Cách dùng điển hình là tạo đĩa mềm khởi động GRUB với một hệ thống tập tin. Thí dụ:

# mke2fs /dev/fd0
# mount -t ext2 /dev/fd0 /mnt
# grub-install --root-directory=/mnt '(fd0)'
# umount /mnt


Một thí dụ khác là khi có một phân vùng khởi động được gán tại /boot. Vì GRUB là một trình nạp khởi động, nó không biết gì về các điểm gán, nên cần chạy lệnh grub-install như sau:

# grub-install --root-directory=/boot /dev/hda


Như trên đã nói, việc đoán ổ đĩa BIOS trong hệ điều hành giống UNIX là khá khó khăn. Vì vậy, sau khi cài đặt, grub-install sẽ nhắc người dùng kiểm ra xem nó có đoán đúng các ánh xạ không. Cần cẩn thận, vì nếu kết quả xuất ra sai máy tính rất có thể bạn sẽ gặp rắc rối khi khởi động lại máy tính.

Các tuỳ chọn của lệnh grub-install
Code:
--help
In tóm tắt về các tuỳ chọn dòng lệnh và thoát.
--version
In số phiên bản của GRUB và thoát.
--force-lba
Bắt buộc GRUB dùng chế độ LBA. Chỉ dùng tuỳ chọn này nếu BIOS không hoạt động ở chế độ LBA mặc dù nó hỗ trợ chế độ LBA.
--root-directory=thư_mục
Cài các hình ảnh GRUB vào thư mục thư_mục thay vì vào thư mục root. Tuỳ chọn này có ích khi bạn muốn cài GRUB vào một phân vùng riêng biệt hoặc vào một ổ đĩa di động Thí dụ cho trường hợp bạn có một thư mục boot riêng được gán tại /boot:
grub-install --root-directory=/boot 'hd0'
--grub-shell=tập_tin
Dùng tập_tin làm shell grub. Bạn có thể thêm các tuỳ chọn tuỳ ý vào tập_tin sau tên tập tin, thí dụ:
grub-install --grub-shell="grub –read-only" /dev/fd0
--recheck
Kiểm tra lại ánh xạ thiết bị, ngay cả khi /boot/grub/device.map đã tồn tại. Nên dùng tuỳ chọn này mỗi khi thêm/tháo một đĩa vào/ra khỏi máy tính.

Lưu ý rằng grub-install thực chất là một Bourne shell script và chức năng thực sự do shell grub thực hiện. Vì vậy có thể chạy grub trực tiếp để cài GRUB, mà không cần grub-install. Nhưng không nên làm như vậy trừ khi bạn rất quen thuộc với các yếu tố nội tại của GRUB. Việc cài một trình nạp khởi động trong một hệ điều hành đang chạy là cực kỳ nguy hiểm.

3.7.2. Cài GRUB trong shell grub
Cách này dùng lệnh grub trong môi trường hệ điều hành.

Cần lưu ý là shell grub là trình mô phỏng – nó thay thế các lời gọi BIOS bằng các lời gọi hệ thống UNIX và các hàm libc, nó không chạy dưới môi trường nguyên thuỷ, vì vậy đôi khi nó hoạt động không chính xác, nhất là trong việc ánh xạ giữa các ổ đĩa BIOS và các thiết bị hệ điều hành.

Quá trình cài đặt dùng shell grub tương tự như ở Giai đoạn 2 nguyên thuỷ. Bạn cần cẩn thận về buffer cache. grub dùng thiết bị thô thay vì hệ thống tập tin mà hệ điều hành đang sử dụng, vì vậy có khả năng cache inconsistency nào đó gây hư hỏng hệ thống tập tin. Lời khuyên là:

* tháo gán trước khi chạy grub, nếu có thể, các ổ đĩa mà GRUB có thể sẽ viết dữ liệu lên.
* gán ở chế độ chỉ-đọc nếu không thể tháo gán ổ đĩa nhưng có thể gán với cờ chỉ-đọc.
* chắc chắn rằng không có bất kì hoạt động đĩa nào trong khi chạy lệnh grub nếu ổ đĩa bắt buộc phải gán với cờ đọc-viết.
* khởi động lại hệ điều hành càng sớm càng tốt. Điều này có thể không cần thiết nếu các bước trên đã được tuân thủ, nhưng khởi động lại là cách an toàn nhất.

Sau khi hoàn tất cài đặt, việc nhập lệnh quit là rất quan trọng vì quit làm cho buffer cache trở nên consistent; đừng ấn <C-c>.

Nếu muốn cài GRUB không tương tác, chỉ định tuỳ chọn --batch ở dòng lệnh. Một thí dụ đơn giản:

Code:
#!/bin/sh
# Du`ng /usr/sbin/grub ne^'u o+? he^. tho^'ng cu~.
/sbin/grub --batch <<EOT 1>/dev/null 2>/dev/null
root (hd0,0)
setup (hd0)
quit
EOT


Các tuỳ chọn của lệnh grub:

Code:
--help
In tóm tắt về các tuỳ chọn dòng lệnh và thoát.
--version
In số phiên bản của GRUB và thoát.
--verbose
In các thông điệp verbose nhằm mục đích gỡ lỗi.
--device-map=tập_tin
Dùng tập tin ánh xạ thiết bị tập_tin.
--no-floppy
Không thăm dò ổ đĩa mềm. Tuỳ chọn này không có tác dụng nếu tuỳ chọn --device-map được chỉ định.
--probe-second-floppy
Thăm dò ổ đĩa mềm thứ hai. Shell grub không thăm dò nó nếu tuỳ chọn này không được chỉ định vì đôi khi nó cần thời gian lâu. Shell grub bỏ qua tuỳ chọn này nếu đã chỉ đinh tập tin ánh xạ thiết bị.
--config-file=tập_tin
Đọc tập tin cấu hình tập_tin thay vì /boot/grub/menu.lst.
--boot-drive=ổ_đĩa
Thiết lập ổ đĩa khởi động stage2 là ổ_đĩa. Đối số này là một số nguyên (thập thân, bát phân hay thập lục phân).
--install-partition=phân_vùng
Thiết lập phân vùng khởi động stage2 là phân_vùng. Đối số này là một số nguyên (thập thân, bát phân hay thập lục phân).
--no-config-file
Không dùng tập tin cấu hình.
--no-curses
Không dùng giao diện curses.
--batch
Tuỳ chọn này có cùng ý nghĩa như --no-config-file --no-curses.
--read-only
Không viết vào bất cứ đĩa nào.


Có thể cài GRUB theo một tập tin có sẵn chứa các thông số cần thiết cho lệnh grub. Thí dụ có tập tin /etc/grub.conf như sau:

root (hd0,4)
install /grub/stage1 d (hd0) /grub/stage2 0x8000 (hd0,4)/grub/menu.lst
quit


Và bạn vừa hiệu chỉnh tập tin device.map, bây giờ bạn phải cài lại GRUB:

grub --batch --device-map=/boot/grub/device.map </etc/grub.conf

Thí dụ bạn có tập tin /etc/grubfd.conf dùng để cài GRUB vào đĩa mềm:
Code:
#
# /etc/grubfd.conf – ta.o ddi~a me^`m kho+?i ddo^.ng
#
# DDe^? ca`i grub va`o ddi~a me^`m, nha^.p le^.nh sau:
# grep -v ^# /etc/grubfd.conf | grub --batch
#
root (fd0)
install /boot/grub/stage1 d (fd0) (fd0)/boot/grub/stage2 0x8000 p (fd0)/boot/grub/menu.lst
quit
Bạn dùng lệnh sau để cài GRUB vào đĩa mềm (đã được chú thích trong tập tin đó):
grep -v ^# /etc/grubfd.conf | grub --batch


3.7.3. Ánh xạ giữa các ổ đĩa BIOS và các thiết bị hệ điều hành
Khi chỉ định tuỳ chọn --device-map, shell grub tạo tập tin ánh xạ thiết bị, thường là /boot/grub/device.map, nếu chưa có tập tin này. Nếu tập tin này đã tồn tại, shell grub đọc nó để ánh xạ các ổ đĩa BIOS theo các thiết bị hệ điều hành. Tập tin này gồm các dòng:

thiết_bị tập_tin

thiết_bị là một ổ đĩa, cú pháp dùng theo cú pháp của GRUB; tập_tin là một tập tin thiết bị của hệ điều hành.

Lý do shell grub cung cấp tập tin ánh xạ thiết bị là vì nó không thể đoán ánh xạ giữa ổ đĩa BIOS và thiết bị hệ điều hành một cách chính xác trong một số môi trường; thí dụ như khi thay đổi trình tự khởi động giữa IDE và SCSI trong BIOS, shell grub sẽ nhầm lẫn thứ tự của chúng.

Vì vậy hãy điều chỉnh lại tập tin này nếu shell grub nhầm lẫn. Bạn có thể thêm chú thích trong tập tin này, nếu cần, vì shell grub xem các dòng bắt đầu bằng kí tự # là dòng chú thích.

Sau khi thay đổi nội dung tập tin device.map cần cài lại GRUB.

3.8. Khởi động hệ thống với GRUB
GRUB có 2 cách khác nhau để khởi động hệ thống. Một cách là nạp hệ điều hành trực tiếp, cách kia là nạp chuỗi một trình nạp khởi động khác, vả trình nạp khởi động nàysẽ nạp hệ điều hành. Nói chung thì cách thứ nhất được ưa chuộng hơn vì không phải cài hay duy trì trình khởi động khác. Tuy nhiên đôi khi vẫn cần dùng cách thứ hai vì GRUB không hỗ trợ mọi hệ điều hành về bản chất, đặc biệt là các hệ điều hành thuộc sở hữu độc quyển.
3.8.1. Khởi động hệ điều hành trực tiếp
Nói chung GRUB có thể khởi động Linux, FreeBSD, NetBSD, OpenBSD, GNU HURD theo các bước sau:

* Quy định thiết bị root của GRUB là ổ đĩa nơi giữ các hình ảnh hệ điều hành bằng lệnh root.
* Tải hệ điều hành bằng lệnh kernel, có thể gắn thêm các thông số cho nhân.
* Nếu cần, tải initrd bằng lệnh initrd hoặc các mô-đun bằng lệnh module hoặc modulenounzip.
* Chạy lệnh boot.

3.8.2. Tải trình nạp khởi động khác
Để khởi động các hệ điều hành không được hỗ trợ, GRUB nạp chuỗi một trình nạp khỏi động cho hệ điều hành đó. Thông thường, trình khởi động được đặt ở sector khởi động của phân vùng cài đặt hệ điều hành.

* Thiết lập thiết bị root của GRUB đến phân vùng hệ điều hành bằng lệnh rootnoverify

grub> rootnoverify hd(0,0)

* Thiết lập cờ active trong phần vùng bằng lệnh makeactive

grub> makeactive

* Tải trình nạp khởi động bằng lệnh chainloader

grub> chainloader +1

+1 biểu thị GRUB đọc một sector kể từ nơi bắt đầu của phân vùng.
* Chạy lệnh boot

Tuy nhiên DOS và Windows có một số yếu tố phụ thuộc cần chú ý khi muốn khởi động chúng.
3.8.3. Một số thí dụ
3.8.3.1. Linux

* Thiết lập thiết bị root vào ổ đĩa cài GNU/Linux. Có thể dùng lệnh find /vmlinuz (hoặc tương tự).
* Tải nhân:

grub> kernel /vmlinuz root=/dev/hda1

Nếu cần chỉ định các tham số cho nhân, gắn chúng vào lệnh trên. Thí dụ để thiết lập vga là ext:

grub> kernel /vmlinux root=/dev/hda1 vga=ext

Cần lưu ý là phân vùng root ở đây phải theo cách gọi của Linux vì nó được chuyển vào nhân Linux.
* Nếu có dùng initrd, thực hiện lệnh initrd sau lệnh kernel

grub> initrd /initrd

* Cuối cùng chạy lệnh boot.

Lưu ý: nếu dùng initrd và chỉ định tuỳ chọn mem= cho nhân để bắt nó dùng ít bộ nhớ hơn hiện có, thì cũng cần phải chỉ định cùng một kích thước bộ nhớ cho GRUB. Để GRUB biết được kích thước này, chạy lệnh uppermem trước khi tải nhân.

3.8.3.2. FreeBSD
GRUB có thể tải nhân trực tiếp, hoặc ở dạng ELF hoặc định dạng a.out, nhưng cách này không được khuyến khích vì giao diện trình khởi động của FreeBSD đôi khi thay đổi rất nhiều, vì vậy GRUB không thể bảo đảm chuyển chính xác các tham số nhân. Thay vì vậy, nên tải một trình khởi động rất linh hoạt là /boot/loader. Xem thí dụ:

grub> root (hd0,a)
grub> kernel /boot/loader
grub> boot


Phiên bản FreeBSD 5.x dùng mặc định hệ thống tập tin UFS2 mà hiện tại GRUB chưa hỗ trợ, vì vậy phải dùng cách nạp chuỗi:

grub> rootnoverify (hd0,1)
grub> chainloader +1
grub> boot


3.8.3.3. NetBSD
GRUB có thể tải trực tiếp a.out và ELF của NetBSD, theo các bước sau:

* Thiết lập thiết bị root của GRUB với lệnh root.
* Nạp nhân với lệnh kernel. Nên gắn tuỳ chọn --type=netbsd nếu muốn tải nhân ELF:

grub> kernel --type=netbsd /netbsd-elf

* Chạy boot.

Tuy nhiên hiện tại GRUB không cho phép chuyển tham số nhân, vì vậy dùng cách nạp chuỗi có thể tốt hơn.

3.8.3.4. OpenBSD
Cách thực hiện hoàn toàn giống như NetBSD. Tuy nhiên ở những phiên bản sau này (sau 2.7), có thể cách trên không thành công. Khi đó có thể dùng cách nạp chuỗi.

3.8.3.5. DOS/Windows
GRUB không thể khởi động DOS hay Windows trực tiếp, vì vậy cần phải nạp chuỗi. Tuy nhiên các trình khởi động của chúng có một số vấn đề phụ thuộc quan trọng, nên nó có thể không hoạt động nếu chỉ đơn thuần nạp chuỗi chúng. GRUB có 2 chức năng giúp khắc phục các khó khăn này. Nếu DOS hay Windows được cài trên ổ đĩa cứng không phải là ổ thứ nhất, cần phải dùng kĩ thuật tráo đổi đĩa, vì các hệ điều hành này không thể khởi động từ ổ cứng không phải là ổ thứ nhất. Một giải pháp trong GRUB là dùng lệnh map, thí dụ để chuyển đổi đĩa cúng thứ nhất và thứ hai:

grub> map (hd0) (hd1)
grub> map (hd1) (hd0)


Cần lưu ý là cách này chỉ hiệu quả khi DOS hay Windows dùng BIOS để truy cập ổ đĩa được chuyển đổi. Nếu hệ điều hành đó dùng trình điều khiển đặc biệt cho ổ đĩa đó, cách này có thể không hoạt động. Một vấn đề khác là khi cài nhiều hơn một bản của hệ điều hành DOS/Windows trên một đĩa cứng các hệ điều hành này có thể lẫn lộn nếu có nhiều hơn một phân vùng sơ cấp cho DOS/Windows. Dĩ nhiên nên tránh những trường hợp như thế này, nhưng GRUB đưa ra một giải pháp khi muốn làm như vậybằng kĩ thuật che/khử che phân vùng. Nếu GRUB che một phân vùng DOS hay Windows, DOS hay Windows sẽ bỏ qua phân vùng đó. Nếu GRUB khử che một phân vùng DOS hay Windows, DOS hay Windows sẽ nhận diện được phân vùng đó. Vì vậy nếu DOS hay Windows được cài ở phân vùng thứ nhất và thứ hai của đĩa cứng thứ nhất, để khởi động bản hệ điều hành trên phân vùng thứ nhất:

grub> unhide (hd0,0)
grub> hide (hd0,1)
grub> rootnoverify (hd0,0)
grub> chainloader +1
grub> makeactive
grub> boot


3.9. Cấu hình
Ở giao diện dòng lệnh cần phải gõ vài lệnh để khởi động hệ điều hành. GRUB cũng cung cấp giao diện thực đơn mà chỉ cần chọn một đề mục là mọi thứ được thực hiện để khởi động hệ điều hành.

Để có thể sử dụng giao diện thực đơn cần phải có tập tin cấu hình menu.lst ở thư mục khởi động. Khi hệ thống được khởi động, GRUB đọc nội dung của tập tin cấu hình. Không cần phải cài GRUB lại mỗi khi thay đổi nội dung tập tin này. Tập tin này mặc định nằm ở thư mục /boot/grub, nhưng có thể đặt ở bất cứ nơi đâu cũng như có thể đặt bất cứ tên gì cho nó.
Phân tích thí dụ về một tập tin cấu hình:
Tập tin này bắt đầu bằng các thiết lập chung, các tuỳ chọn liên hệ đến giao diện thực đơn. Các lệnh này có thể được đặt trước bất cứ đề mục nào (bắt đầu với lệnh title).

Code:
#
# Ta^.p tin ca^'u hi`nh thu+.c ddo+n ma^~u
#
Đây là các dòng bình luận. GRUB bỏ qua các dùng bắt đầu với kí tự # và các dòng trống.
# Theo ma(.c ddi.nh, kho+?i ddo^.ng dde^` mu.c thu+' nha^'t
default 0
Đề mục thứ nhất (lưu ý là đếm bắt đầu từ 0 chứ không phải 1) sẽ là lựa chọn mặc định.
# Tu+. ddo^.ng kho+?i ddo^.ng sau 30 gia^y
timeout 30
GRUB sẽ khởi động tự động sau 30 giây, trừ khi bị ngắt bởi một nhấn phím.
# Quay la.i dde^` mu.c thu+' hai
fallback 1
Nếu vì bất cứ lí do nào mà đề mục mặc định không hoạt động, quay lại đề mục thứ hai. Ở phần định nghĩa cho hệ điều hành, mỗi đề mục bắt đầu bằng một lệnh đặc biệt title. Không có lệnh boot ở cuối đề mục vì nó sẽ tự động thực hiện nếu GRUB nạp thành công các lệnh khác.
Đối số cho lệnh title được dùng để trình bày một tựa/miêu tả ngắn cho đề mục.
# DDe^? kho+?i ddo^.ng GNU/Linux
title GNU/Linux
kernel (hd1,0)/vmlinuz root=/dev/hdb1
Khởi động GNU/Linux từ đĩa cứng thứ hai.
# DDe^? kho+?i ddo^.ng FreeBSD
title FreeBSD
root (hd0,2,a)
kernel /boot/loader
Khởi động nhân FreeBSD tải từ phân vùng a trên PC slice thứ ba của đĩa cứng thứ nhất.
# DDe^? kho+?i ddo^.ng OS/2
title OS/2
root (hd0,1)
makeactive
# na.p chuo^~i tri`nh kho+?i ddo^.ng OS/2 tu+` sector thu+' nha^'t
chainloader +1
# Na.p chuo^~i mo^.t ta^.p tin cu. the^?
#chainloader /boot/chain.os2
Khởi động OS/2 dùng cách nạp chuỗi.
# DDe^? kho+?i ddo^.ng Windows NT hoa(.c Windows95
title Thu+.c ddo+n kho+?i ddo^.ng Windows NT / Windows 95
root (hd0,0)
makeactive
chainloader +1
# DDe^? na.p DOS ne^'u co' ca`i Windows NT
# chainload /bootsect.dos
Khởi động Windows bằng cách nạp chuỗi.
# DDe^? kho+?i ddo^.ng mo^.t he^. ddie^`u ha`nh tre^n ddi~a me^`m
title floppy
pause Ga`i ddi~a me^`m va`o o^? ddi~a
root (fd0)
chainloader +1
Khởi động một hệ điều hành từ đĩa mềm.
# DDe^? ca`i GRUB va`o ddi~a cu+'ng
title Ca`i GRUB va`o ddi~a cu+'ng
root (hd0,0)
setup (hd0)
Cài (cài lại) GRUB vào đĩa cứng.
# Thay ddo^?i ma`u sa('c.
title Thay ddo^?i ma`u sa('c
color light-green/brown blink-red/blue
Thay đổi màu sắc của thực đơn.
# Ta?i mo^.t thu+.c ddo+n kha'c
title Thu+.c ddo+n bo^? sung
configfile (hd0,4)/boot/grub/control.lst

Tải thực đơn bổ sung.
Đặc điểm của tập tin cấu hình:

* các lệnh đặc thù cho thực đơn phải được dùng trước các lệnh khác
* tập tin phải ở định dạng văn bản thuần tuý
* # ở đầu dòng cho biết đây chỉ là lời bình
* các tuỳ chọn cách nhau bằng khoảng trắng
* số có thể ở dạng thập phân hoặc thập lục phân. Số thập lục phân phải khởi đầu bằng 0x, và phân biệt chữ hoa-thường

Nếu quá trình cài GRUB đã không quy định tập tin cấu hình, vẫn có thể tải tập tin cấu hình trong môi trường GRUB bằng lệnh configfile, thí dụ:

grub> configfile (fd0)/boot/grub/menu.lst

3.10. Bảo mật cho GRUB
Dùng tính năng mật khẩu của GRUB để chỉ cho phép người quản trị dùng các hoạt động tương tác (như biên tập đề mục thực đơn và vào giao diện dòng lệnh). Để sử dụng tính năng này, cần chạy lệnh password trong tập tin cấu hình, như sau:

password --md5 PASSWORD

Khi đó GRUB không cho phép điều khiển tương tác nào (<e> và <c>smilie, cho đến khi gõ phím <p> và nhập đúng mật khẩu. Tuỳ chọn --md5 cho GRUB biết rằng PASSWORD ở định dạng MD5. Nếu không sử dụng tuỳ chọn này, GRUB cho rằng PASSWORD ở dạng văn bản thuần tuý. Mật khẩu có thể được mã hoá bằng lệnh md5crypt. Thí dụ chạy shell grub và nhập mật khẩu:

grub> md5crypt
Password: **********
Encrypted: $1$U$JK7xFegdxWH6VuppCUSIb.


Sau đó cắt và dán mật khẩu đã được mã hoá vào tập tin cấu hình. Ngoài ra cũng có thể chỉ định đối số tuỳ chọn cho lệnh password, thí dụ:

password PASSWORD /boot/grub/menu-admin.lst

Khi đó GRUB sẽ nạp /boot/grub/menu-admin.lst làm tập tin cấu hình khi nhập đúng mật khẩu. Nếu muốn chỉ có người quản trị mới có quyền chạy một số đề mục thực đơn nào đó, chẳng hạn như khởi động một hệ điều hành không bảo mật như DOS, có thể dùng lệnh lock; lệnh này luôn luôn dừng lại cho đến khi nhập đúng mật khẩu. Thí dụ:

Code:
title Kho+?i ddo^.ng DOS
lock
rootnoverify (hd0,1)
makeactive
chainload +1[b]


Cũng có thể dùng lệnh password thay cho lock. Trong trường hợp này tiến trình khởi động sẽ yêu cầu mật khẩu và dừng lại cho đến khi mật khẩu được nhập chính xác. Vì lệnh password nhận đối số PASSWORD của chính nó nên sẽ có lợi nếu dùng một mật khẩu khác với mật khẩu cho các đề mục khác.

Nên sử dụng lệnh lock/password ngay sau title vì các lệnh trong đề mục thực đơn được thực thi theo thứ tự.

grub-md5-crypt là script gọi shell grub để mã hoá một chuỗi kí tự ở dạng MD5. Mật khẩu do chương trình này mã hoá có thể được dùng với lệnh password.

grub-md5-crypt nhận các tuỳ chọn sau:

Code:
--help
In tóm tắt các tuỳ chọn dòng lệnh và thoát
--version
In thông tin phiên bản và thoát
--grub-shell=tập_tin
Dùng tập_tin làm shell grub


3.11. Giao diện người dùng của GRUB
GRUB có cả giao diện thực đơn đơn giản để chọn các đề mục được thiết lập sẵn từ tập tin cấu hình lẫn giao diện dòng lệnh linh hoạt cao để thực hiện bất cứ các tổ hợp lệnh khởi động nào theo ý muốn.
3.11.1. Giao diện dòng lệnh
Giao diện dòng lệnh cung cấp một dấu nhắc và sau nó là vùng văn bản có thể biên tập được giống một dòng lệnh trong Unix hoặc DOS. Mỗi dòng lệnh được thi hành ngay lập tức sau khi nó được nhập vào. Các lệnh này là một phần của các dòng lệnh có thể dùng trong tập tin cấu hình, với cùng một cú pháp. Dùng giao diện dòng lệnh có thể khởi động các hệ điều hành không có trong thực đơn GRUB.

Di chuyển con trỏ và biên tập văn bản trên một dòng có thể được thực hiện nhờ một phần các chức năng có sẵn trong shell Bash:

Code:
<C-f>
<PC mũi tên phải>
Di chuyển về trước một kí tự.
<C-b>
<PC mũi tên trái>
Di chuyển về sau một kí tự.
<C-a>
<HOME>
Di chuyển về đầu dòng.
<C-e>
<END>
Di chuyển về cuối dòng.
<C-d>
<DEL>
Xoá kí tự bên dưới con trỏ.
<C-h>
<BS>
Xoá kí tự bên trái con trỏ..
<C-k>
Xoá đoạn văn bản từ vị trí con trỏ hiện tại đến cuối dòng.
<C-u>
Xoá ngược đoạn văn bản từ vị trí con trỏ hiện tại đến đầu dòng.
<C-y>
Lấy lại đoạn văn bản đã xoá vào bộ đệm tại con trỏ.
<C-p>
<PC mũi tên lên>
Di chuyển lên trên trong danh sách các lệnh vừa gõ.
<C-n>
<PC mũi tên xuống>
Di chuyển xuống dưới trong danh sách các lệnh vừa gõ.


Khi gõ các lệnh một cách tương tác, nếu con trỏ ở trong hoặc trước từ đầu tiên trong dòng lệnh, ấn phím <TAB> (hoặc <C-i>smilie sẽ liệt kê các lệnh có sẵn, và nếu con trỏ ở sau từ đầu tiên, <TAB> sẽ liệt kê các ổ đĩa, phân vùng, và tên tập tin tuỳ vào tình huống.

Lưu ý rằng không thể dùng chức năng hoàn thành dòng lệnh trong hệ thống tập tin TFTP vì bởi vì TFTP không hỗ trợ liệt kê tên tập tin vì lí do bảo mật.

Dùng lệnh help để đọc thông tin về một lệnh, ví dụ để xem thông tin của lệnh root:

help root

3.11.2. Giao diện thực đơn
Giao diện thực đơn khá dễ dùng. Các lệnh của nó tương đối trực quan và được miêu tả trên màn hình.

Về cơ bản, giao diện thực đơn cung cấp danh sách các đề mục khởi động cho người dùng lựa chọn. Dùng các phím mũi tên để chọn đề mục, rồi ấn phím <RET> để chạy nó. Có thể quy định thời gian chờ để khởi động đề mục mặc định (hoặc đề mục đầu tiên nếu không thiết lập), thời gian này sẽ bị ngắt bằng cách nhấn phím bất kì.

Từ giao diện thực đơn có thể vào giao diện dòng lệnh bằng cách ấn <c> (khi đó sẽ giống như trường hợp không có tập tin cấu hình nhưng vẫn có thể quaylại giao diện thực đơn bằng phím <ESC>smilie hoặc có thể biên tập bất cứ đề mục khởi động nào bằng cách ấn phím <e>.

Nếu giao diện thực đơn được bảo vệ bằng mật khẩu, ấn <RET> rồi <p> và nhập mật khẩu để chọn đề mục.
Biên tập một đề mục trong thực đơn
Để biên tập một đề mục trên thực đơn, đầu tiên ấn <ESC>, sau đó chọn đề mục cần thay đổi bằng các phím con trỏ và ấn <e>, khi đó các dòng lệnh cho đề mục đó sẽ xuất hiện. Chọn dòng cần điều chỉnh bằng các phím con trỏ và ấn <e> lần nữa.

Trong khi biên tập một đề mục, ấn <RET> để thay thế dòng lệnh cũ bằng dòng lệnh vừa điều chỉnh, nếu ấn <ESC> mọi thay đổi sẽ được bỏ qua. Nếu muốn thêm một dòng mới vào đề mục khởi động, ấn <o> nếu thêm vào sau dòng hiện tại hoặc <O> nếu thêm vào trước dòng hiện tại. Để xoá một dòng, ấn <d>. GRUB không hỗ trợ huỷ bỏ thao tác vừa làm, nhưng có thề làm điều tương tự như vậy bằng cách quay trở lại thực đơn chính. Sau khi điều chỉnh xong, ấn <b> để khởi động với đề mục đó.
Giao diện thực đơn ẩn
Nếu thiết bị cuối câm hoặc GRUB được yêu cần che dấu giao diện thực đơn bằng lệnh hiddenmenu, GRUB sẽ không hiển thị giao diện thực đơn và tự động khởi động đề mục mặc định, trừ khi bị ngắt bằng cách ấn phím <ESC>. Khi ngắt thời gian chờ và thiết bị cuối câm, GRUB quay trở lại giao diện dòng lệnh.
3.12. Một số lệnh trong GRUB
3.12.1. Các lệnh chỉ dùng cho thực đơn

Code:
default số
Thiết lập mặc định cho đề mục số số. Việc đánh số bắt đầu từ 0, và đề mục số 0 là mặc định nếu lệnh này không được dùng.
Có thể chỉ định saved thay vì một con số. Khi đó, đề mục mặc định là đề mục được lưu bằng lệnh savedefault.
fallback số
Nếu đề mục mặc định có lỗi, ngay lập tức chuyển qua đề mục số thay vì chờ người dùng thao tác. Cách đánh số giống như ở lệnh default. Có thể thiết lập nhiều hơn một fallback.
hiddenmenu
Không hiển thị thực đơn trên thiết bị đầu cuối và đề mục mặc định sẽ được khởi động sau khi hết thời gian chờ. Người dùng vẫn có thể yêu cầu hiển thị thực đơn bằng cách ấn <ESC> trước khi thời gian chờ hết.
timeout gy
Thiết lập thời gian chờ, tính bằng gy giây, trước khi tự động khởi động vào đề mục mặc định.
title tên ...
Bắt đầu một đề mục khởi động mới; nội dung của phần còn lại của dòng này, bắt đầu bằng kí tự đầu tiên không phải là khoảng trắng, được lấy làm tên cho đề mục đó.


3.12.2. Các lệnh chung
Các lệnh này có thể được dùng trong thực đơn lẫn ở dòng lệnh.

color bình_thường [tô_sáng]
Thay đổi màu thực đơn. Màu bình_thường được dùng cho hầu hết các dòng trong thực đơn, và màu tô_sáng được dùng để tô sáng dòng mà con trỏ đang chỉ đến. Nếu không dùng tô_sáng, màu ngược lại của bỉnh_thường được dùng để tô sáng. Định dạng của một màu là tiền_cảnh/hậu_cảnh. tiền_cảnh và hậu_cảnh là các tên màu tượng trưng. Tên màu tượng trưng phải là một trong các tên sau:

* black
* blue
* green
* cyan
* red
* magenta
* brown
* light-gray


Những tên bên dưới chỉ dùng được cho tiền cảnh.

* dark-gray
* light-blue
* light-green
* light-cyan
* light-red
* light-magenta
* yellow
* white

Nhưng chỉ có 8 tên đầu có thể dùng cho hậu_cảnh.

Nếu muốn chớp nháy màu tiền cảnh, dùng tiền tố blink- cho tiền_cảnh.

Lệnh này dùng được trong tập tin cấu hình và ở dòng lệnh. Thí dụ trong tập tin cấu hình:

# Thie^'t la^.p ma`u ma(.c ddi.nh.
color light-gray/blue black/light-gray
# Thay ddo^?i ma`u.
title OS-BS like
color magenta/blue black/magenta

device ổ_đĩa tập_tin
Trong shell grub, chỉ định tập tin tập_tin như là ổ đĩa thực sự cho ổ đĩa BIOS ổ_đĩa. Có thể dùng lệnh này để tạo hình ảnh đĩa, và/hoặc sửa chữa các ổ đĩa được GRUB đoán khi GRUB không xác định được chúng một cách chính xác, như:

grub> device (fd0) /floppy-image
grub> device (hd0) /dev/sd0

Lệnh này chỉ dùng được ở shell grub.

hide phân_vùng
Che dấu phân vùng phân_vùng bằng cách thiết lập bit ẩn trong mã loại phân vùng của nó. Điều này có lợi khi khởi động DOS hay Windows và nhiều phân vùng FAT sơ cấp tồn tại trên một đĩa.

partnew phân_vùng loại từ đến
Tạo một phân vùng sơ cấp mới. phân_vùng là một đặc tả phân vùng theo cú pháp GRUB; loại là loại phân vùng và phải là một số trong khoảng 0–0xff; từ và đến là các sector khởi đầu và kết thúc, được diễn đạt bằng con số sector tuyệt đối.

parttype phân_vùng loại
Thay đổi loại của phân vùng đang tồn tại. phân_vùng là một đặc tả phân vùng theo cú pháp GRUB; loại là loại của phân vùng mới và phải là một số trong khoảng 0–0xff.

password [--md5] mật_khẩu [tập_tin_cấu_hình_mới]
Nếu được dùng trong phần đầu tiên của một tập tin thực đơn, nó sẽ vô hiệu hoá mọi hoạt động điều khiển biên tập tương tác (bộ phận biên tập đề mục thực đơn và dòng lệnh) và các đề mục được bảo vệ bằng lệnh lock. Nếu mật khẩu mật_khẩu được nhập, nó sẽ tải tập_tin_cấu_hình_mới làm tập tin cấu hình mới và khởi động lại GRUB Giai đoạn 2 nếu tập_tin_cấu_hình_mới được chỉ định. Nếu không, GRUB sẽ chỉ mở khoá các lệnh đặc quyền. Lệnh này cũng có thể được dùng trong phần script, khi đó nó sẽ hỏi mật khẩu trước khi tiếp tục. Tuỳ chọn --md5 bảo GRUB rằng mật_khẩu được mã hoá với md5crypt.

setkey [đến_phím từ_phím]
Thay đổi ánh xạ bàn phím. Phím từ_phím được ánh xạ sang đến_phím. Nếu không có đối số nó sẽ thiết lập lại ánh xạ bàn phím. Lưu ý rằng lệnh này không hoán đổi các phím. Nếu muốn hoán đổi các phím, chạy lệnh này một lần nữa với thông số hoán đổi, như:

grub> setkey capslock control
grub> setkey control capslock

Một phím phải là một chữ cái, một con số, hoặc một trong các kí hiệu sau: escape, exclam, at, numbersign, dollar, percent, caret, ampersand, asterisk, parenleft, parenright, minus, underscore, equal, plus, backspace, tab, bracketleft, braceleft, bracketright, braceright, enter, control, semicolon, colon, quote, doublequote, backquote, tilde, shift, backslash, bar, comma, less, period, greater, slash, question, alt, space, capslock, FX (X là một chữ số), và delete. Bảng sau đây miêu tả các kí tự tương ứng với các kí hiệu đó:

exclam
!
at
@
numbersign
#
dollar
$
percent
%
caret
^
ampersand
&
asterisk
*
parenleft
(
parenright
)
minus
-
underscore
_
equal
=
plus
+
bracketleft
[
braceleft
{
bracketright
]
braceright
}
semicolon
;
colon
:
quote
'
doublequote
"
backquote
`
tilde
~
backslash
\
bar
|
comma
,
less
<
period
.
greater
>
slash
/
question
?
space

unhide phân_vùng
Khử ẩn phân vùng phân_vùng bằng cách xoá bit ẩn trong mã loại phân vùng. Lệnh này có ích khi khởi động DOS hoặc Windows và có nhiều phân vùng sơ cấp trên một đĩa cứng.

3.12.3. Các lệnh dùng ở dòng lệnh và đề mục thực đơn
Các lệnh này dùng được ở dòng lệnh và ở đề mục thực đơn. Có thể chạy lệnh help để xem thông tin về các lệnh này.

[code]blocklist tập_tin
In kí hiệu danh sách khối của tập tin tập_tin.

boot
Khởi động hệ điều hành/trình nạp chuỗi đã được nạp. Chỉ cần thiết khi chạy trên dòng lệnh tương tác đầy đủ (nó được hiểu ngầm ở cuối đề mục thực đơn).

cat tập_tin
Hiển thị nội dung tập tin tập_tin. Lệnh này có thể giúp xác định đúng đâu là thư mục gốc của hệ điều hành:

grub> cat /etc/fstab

chainloader [--force] tập_tin
Nạp chuỗi tập_tin. Nếu chỉ định tuỳ chọn --force, nó sẽ cưỡng bức nạp tập_tin, cho dù nó có chữ kí đúng hay không. Điều này giúp nạp một trình nạp khởi động khiếm khuyết (như để khởi động SCO UnixWare 7.1).

cmp tập_tin1 tập_tin2
So sánh tập tin tập_tin1 với tập_tin2. Nếu chúng khác nhau về kích thước, in các kích thước như sau:

Differ in size: 0x1234 [foo], 0x4321 [bar]

Nếu kích thước bằng nhau nhưng các byte ở một offset khác nhau, in các byte như sau:

Differ at the offset 777: 0xbe [foo], 0xef [bar]

Nếu chúng hoàn toàn giống nhau, không in gì cả.

configfile tập_tin
Tải tập_tin làm tập tin cấu hình.

displayapm
Hiển thị thông tin BIOS về APM.

displaymem
Hiển thị thông tin về bộ nhớ đang được sử dụng, bao gồm tất cả các vùng của RAM vật lý được cài đặt, dựa trên thông tin từ BIOS. Giúp xác định hệ thống có bao nhiêu RAM dành cho khởi động.

embed stage1_5 thiết_bị
Ghi Giai đoạn 1.5 stage1_5 vào các sector sau MBR nếu thiết_bị là một ổ đĩa, hoặc vào vùng của trình khởi động nếu thiết_bị là một phân vùng FFS hoặc phân vùng ReiserFS. In con số các sector chiếm bởi stage1_5, nếu thành công. Thông thường không cần chạy lệnh này trực tiếp.

find tên_tập_tin
Tìm tên tập tin tên_tập_tin trong tất cả các phân vùng và in danh sách các thiết bi chứa tập tin. Tên tập tin tên_tập_tin nên là một tên tập tin tuyệt đối như /boot/grub/stage1.

geometry ổ_đĩa [cylinder head sector [tổng_sector]]
In thông tin về ổ đĩa ổ_đĩa. Trong shell grub, có thể thiết lập thông số ổ đĩa tuỳ ý. Số cylinder, số head, số sector và tổng số sector được thiết lập tương ứng cho cylinder, head, sector và tổng_sector. Nếu bỏ qua tổng_sector, nó sẽ được tính tự động dựa trên các giá trị C/H/S.

halt --no-apm
Tắt máy tính. Nếu tuỳ chọn --no-apm được chỉ định, không thực hiện lời gọi APM BIOS; nếu không, máy tính dùng APM khi tắt.

help --all [mẫu ...]
Hiển thị thông tin về các lệnh được cài sẵn. Nếu không chỉ định mẫu, lệnh này sẽ cho ra miêu tả ngắn của hầu hết các lệnh có sẵn. Nếu chỉ định tuỳ chọn --all, các miêu tả ngắn cho các lệnh hiếm dùng cũng được trình bày. Nếu chỉ định mẫu, nó sẽ trình bày thông tin dài hơn về mỗi lệnh khớp với các mẫu đó.

initrd tập_tin ...
Nạp đĩa RAM ban đầu cho hình ảnh khởi động theo định dạng Linux và thiết lập các thông số thích hợp cho vùng thiết lập Linux trong bộ nhớ.

install
Đã được đề cập ở trên.

ioprobe ổ_đĩa
Dò tìm cổng I/O dùng cho ổ đĩa ổ_đĩa. Lệnh này sẽ liệt kê các cổng I/O trên màn hình.

kernel [--type=loại] [--no-mem-option] tập_tin ...
Nạp hình ảnh khởi động (Multiboot a.out hoặc ELF, Linux zImage hoặc bzImage, FreeBSD a.out, NetBSD a.out, v.v...) từ tập_tin. Phần còn lại của dòng được chuyển nguyên văn như dòng lệnh nhân. Bất cứ mô-đun nào cũng có thể được nạp sau khi dùng lệnh này. Lệnh này cũng chấp nhận tuỳ chọn --type để chỉ định cụ thể loại nhân của tập_tin. Đối số loại phải là một trong các thứ sau: netbsd, freebsd, openbsd, linux, biglinux, và multiboot. Tuy nhiên, chỉ cần xác định loại nhân khi nạp nhân NetBSD E
Case 2 - iptables và máy đơn có dịch vụ
Trường hợp điển hình thứ nhì trong việc ứng dụng iptables để bảo vệ máy đơn có dịch vụ.

1. Trường hợp:
Firewall cho một máy đơn có dịch vụ.

2. Nhu cầu:
Bảo vệ máy đơn không bị thâm nhập vào những dịch vụ không dành cho công cộng và cho phép truy cập vào những dịch vụ được ấn định cụ thể.

3. Phương pháp kết nối:
Bất cứ phương tiện nào, (cách tốt nhất) nên có IP tĩnh để có thể tạo dịch vụ công cộng ổn định.

Đòi hỏi tối thiểu:
Đã hoàn tất thành công quy trình kết nối vào Internet và các dịch vụ trên máy đã có thể truy cập được từ Internet.

4. Mô hình:

eth0 là NIC tiếp diện với Internet với IP tĩnh. Mô hình này thích hợp cho các máy đơn (dedicated server) với các dịch vụ thông thường như HTTP, SMTP, POP3, DNS và SSH (quản lý từ xa).

5. Nhóm luật:


Code:
1. IF=`/sbin/route | grep -i 'default' | awk '{print$8}'`
2. IP=`/sbin/ifconfig $IF | grep "inet addr" | awk -F":" '{print$2}' | awk '{print $1}'`
3. IPT="/usr/local/sbin/iptables"
4. NET="any/0"
5. DNS="xxx.xxx.xxx.xxx yyy.yyy.yyy.yyy.yyy"
6. SERV_TCP="22 25 80 443 110"
7. SERV_UDP="53 123"
8. HI_PORTS="1024:65535"
9.
10. $IPT -F
11. $IPT -P INPUT DROP
12. $IPT -P OUTPUT DROP
13. $IPT -P FORWARD DROP
14.
15. for entry in $DNS, do
16. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $HI_PORTS -d $entry --dport 53 -m state --state NEW -j ACCEPT
17. $IPT -A INPUT -i $IF -p udp -s $entry --sport 53 -d $IP --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
18. done
19.
20. for port in $SERV_UDP; do
21. if test $port -eq 53
22. then
23. $IPT -A INPUT -i $IF -p udp -s $NET --sport $port -d $IP --dport $port -m state --state NEW,ESTABLISHED -j ACCEPT
24. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $port -m state --state ESTABLISHED -j ACCEPT
25. else
26. $IPT -A INPUT -i $IF -p udp -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT
27. $IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
28. fi
29. done
30.
31. for port in $ SERV_TCP; do
32. $IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT
33. $IPT -A OUTPUT -o $IF -p tcp ! --syn -s $IP --sport $port -d $NET --dport $HI_PORTS -m state --state ESTABLISHED -j ACCEPT
34. $IPT -A INPUT -i $IF -p tcp ! --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state ESTABLISHED -j ACCEPT
35. done
36.
37. $IPT -A INPUT -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_INPUT: "
38. $IPT -A INPUT -i $IF -d $IP -j DROP
39. $IPT -A OUTPUT -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_OUTPUT: "
40. $IPT -A OUTPUT -i $IF -d $IP -j DROP
41. $IPT -A FORWARD -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_FORWARD: "
42. $IPT -A FORWARD -i $IF -d $IP -j DROP



6. Phân tích:
- Dòng 1, 2, 3: Đã phân tích trong bài trước (case 1).

- Dòng 4: Ấn định giá trị của biến NET. Đối với iptables, việc ấn định NET=any/0 và ứng dụng trong firewall script không cần thiết (bị thừa) vì nếu không ấn định cụ thể giá trị source (-s) và destination (-d) thì được ngầm hiểu là any/0. Giá trị NET dùng ở đây với mục đích làm rõ các luật trên phương diện gói tin đến và đi.

- Dòng 5: Ấn định giá trị của biến DNS. Đây là một giá trị quan trọng cho trường hợp firewall trên máy đơn và có dịch vụ cho công cộng. Những dịch vụ cho công như web, mail... đều trực tiếp tương tác với cơ chế biên giải giữa IP và tên domain. Giá trị của biến DNS ở đây chính là các IP của một DNS server (biểu thị cho primary DNS và secondary DNS). DNS server này có thể là DNS do ISP cung cấp hoặc chính authoritative DNS -1- do bạn tạo ra. Các giá trị trong biến DNS này tách rời bởi khoảng trống (space) để tiện việc chạy lệnh sau này.

- Dòng 6: Ấn định giá trị của biến SERV_TCP. Biến SERV_TCP chứa giá trị các cổng dịch vụ ở giao thức TCP được firewall mở và kiểm soát. Các giá trị này tách rời bởi khoảng trống. Bạn có thể thêm, bớt các giá trị tùy thích. Nên lưu ý cách ấn định giá trị các cổng trong biến SERV_TCP chỉ là một cách (trong nhiều cách), bạn có thể khai triển tùy thích, miễn sao iptables "biết được" những cổng nào cần mở và cần kiểm soát. Sử dụng phương thức này chỉ thích hợp cho các cổng dịch vụ có tính chất tương tự nhau và bạn muốn kiểm soát các cổng với chế độ tương tự nhau. Cách ứng dụng khác là ấn định mỗi luật một dòng thay vì nhóm lại trong vòng lặp.

- Dòng 7: Ấn định giá trị của biến SERV_UDP. Tương tự như trên, biến SERV_UDP chứa các giá trị cổng dịch vụ ở giao thức UDP được firewall mở và kiểm soát. Riêng phần biến SERV_UDP này có chứa cổng 53 mang tính chất khá đặc biệt so với các cổng dịch vụ khác. Vấn đề này sẽ được bàn sâu hơn cho dòng 20, 21, 22. Tất nhiên bạn không phải quan tâm đến nó nếu bạn không cung cấp dịch vụ DNS từ máy chủ của mình.

- Dòng 8: Ấn định giá trị của biến HI_PORTS. Trong bài viết cho case 1, giá trị này không được nêu lên và sử dụng một cách cụ thể. Trái lại, nó được sử dụng ở đây với mục đích làm rõ các luật bảo vệ và kiểm soát những gói tin ra / vào cần được huy động tới giá trị của biến HI_PORTS này. Cần nói thêm, giá trị của biến HI_PORTS trải dài từ cổng 1024 đến cổng 65535 là các cổng thuộc chuỗi "high ports" hay "unprivileged ports". Mở một socket trong chuỗi cổng này không cần đến quyền hạn root (trên *nix nói chung) và đây là một trong những điểm quan trọng của việc áp đạt chuỗi HI_PORTS trong firewall script sau này.

- Dòng 10, 11, 12, 13: Đã phân tích trong bài trước (case 1).

- Dòng 15-18: Bốn dòng này thuộc một vòng lặp, đặc biệt dùng để xác lập các dòng luật cho phép máy đơn (ở trường hợp này) liên hệ đến các DNS servers (đã ấn định ở biến $DNS ở trên). Đây là nhóm luật hết sức quan trọng và sẽ được các chương trình cung cấp dịch vụ trên mày dùng đến thường xuyên cho nên việc xác định luật này đầu tiên là việc cần thiết.

- Diễn dịch nôm na vòng lặp của dòng 15, 16, 17 và 18 như sau: với mỗi giá trị thuộc biến $DNS, chạy hai dòng 16 và 17 cho đến khi không còn giá trị nào nữa.

- Dòng 16 có ý nghĩa như sau: cho phép các gói tin với giao thức UDP đi ra ngoài bằng IP hiện có xuyên qua IF. Các gói tin này được khởi tạo từ một socket thuộc chuỗi HI_PORTS (nguồn --sport) và đi đến các địa chỉ DNS server đã ấn định trong biến $DNS đến cổng 53 (đích --dport). Thêm vào đó, các gói tin này phải ở tình trạng NEW (trong state table được iptables quản lý). Điều này có nghĩa firewall cho phép máy chủ -2- này khởi tạo các truy cập đến các DNS server đã ấn định (xxx.xxx.xxx.xxx và yyy.yyy.yyy.yyy).

- Dòng 17 có ý nghĩa như sau: cho phép các gói tin với giao thức UDP từ các DNS server đã ấn định được đi đến IP hiện có xuyên qua IF. Các gói tin này được phép trả lời từ cổng 53 của DNS server ấy. Các gói tin ở dạng trả lời này phải ở tình trạng ESTABLISHED (trong state table được iptables quản lý). Điều này có nghĩa firewall cho phép các DNS server đã được ấn định trả lời các truy cập được khởi tạo từ máy chủ. Các gói tin ở tình trạng NEW đến từ các DNS server sẽ bị từ chối.

- Dòng 20-29: tương tự như nhóm dòng 15-18, dòng 20-29 thuộc một vòng lặp để xác lập luật cho các cổng thuộc biến $SERV_UDP cho giao thức UDP. Trong vòng lặp này chứa một một cụm điều kiện cách (if / else) để thử nghiệm và ứng dụng đúng luật thích ứng cho cổng dịch vụ.

- Diễn dịch nôm na vòng lặp 20-29 như sau: với mỗi giá trị thuộc biến $SERV_UDP, chạy các dòng lệnh 23 và 24 nếu một trong những giá trị thuộc biến $SERV_UDP là 53. Nếu không thì chạy các dòng lệnh 26 và 27 cho đến khi không còn giá trị nào nữa.

- Dòng 23 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi vào từ bất cứ nơi đâu từ cổng 53 đến cổng 53 của máy chủ. Các gói tin này phải đi đến $IP hiện có xuyên qua $IF và phải ở tình trạng NEW.

- Dòng 24 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi ra từ cổng 53 của máy chủ đến cổng 53 của máy đã đòi hỏi truy cập và đã được firewall tiếp nhận ở dòng 22. Các gói tin đi ra ngoài này phải ở tình trạng ESTABLISHED.

- Dòng 26 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi vào từ cổng nào đó thuộc dãy $HI_PORTS đến cổng đã ấn định trong biến $SERV_UDP của máy chủ. Các gói tin này phải ở tình trạng NEW.

- Dòng 27 có ý nghĩa như sau: firewall cho phép các gói tin với giao thức UDP đi ra từ cổng đã ấn định trong biến $SERV_UDP (và không phải là cổng 53) của máy chủ đến cổng nào đó thuộc dãy $HI_PORTS dùng để truy cập và đã được firewall tiếp nhận ở dòng 25. Các gói tin đi ra ngoài này phải ở tình trạng ESTABLISHED.

- Dòng 31-35: tương tự như nhóm dòng 20-29. Đây cũng là một vòng lặp dùng để xác lập luật cho các cổng thuộc biến $SERV_TCP cho giao thức TCP. Vòng lặp này không chứa cụm điều kiện cách như nhóm dòng 20-29 vì các cổng dịch vụ đã ấn định trong biến $SERV_TCP mang tính chất tương tự nhau -3-.

- Diễn dịch nôm na vòng lặp 31-35 như sau: với mỗi giá trị thuộc biến $SERV_TCP, chạy các dòng 32, 33 và 34 rồi lặp lại cho giá trị kế tiếp trong biến $SERV_TCP cho đến khi không còn giá trị nào khác.

- Dòng 32 có ý nghĩa như sau: các gói tin ở dạng TCP với cờ hiệu (TCP Flag) là SYN -4- đi vào từ bất cứ nơi nào từ một cổng ở dãy $HI_PORTS đến $IP hiện có xuyên qua $IF để đến cổng $port (giá trị hiện tại của vòng lặp) và ở tình trạng NEW thì tiếp nhận.

- Dòng 33 có ý nghĩa như sau: các gói tin ở dạng TCP không mang cờ hiệu là SYN đi từ $IP hiện có từ cổng $port (giá trị hiện tại của vòng lặp) trả lời cho gói tin yêu cầu truy cập ở trên (đi ra) và ở tình trạng ESTABLISHED thì tiếp nhận.

- Dòng 34 có ý nghĩa như sau: các gói tin ở dạng TCP với cờ hiệu không phải là SYN đi từ nơi gởi gói tin yêu cầu truy cập trên (tiếp tục) đi vào đến cổng $port của $IP hiện có và ở tình trạng ESTABLISHED thì tiếp nhận.

- Dòng 37-42: clean up rules. Đã phân tích ở case 1.


7. Tổng lượt dạng firewall trên:
Đây là dạng firewall được thiết lập cho một máy đơn hỗ trợ dịch vụ. Điểm cốt lõi và khác biệt giữa dạng này và dạng máy đơn không dịch vụ (như ở case 1) là máy đơn hỗ trợ dịch vụ tiếp nhận yêu cầu truy cập và chỉ trả lời yêu cầu truy cập khi những yêu cầu thoả mãn những luật iptables đưa ra (ngoại trừ luật tạo ra ở dòng 16 và 17). Trong khi đó, máy đơn của case 1 mang vai trò yêu cầu truy cập và các dịch vụ bên chỉ có thể trả lời nếu máy đơn này đòi hỏi.

Thử xét luật ở dòng 16 và 17 thì thấy, máy chủ này cần phải khởi tạo một xuất truy cập đến DNS server (và chỉ cụ thể những DNS server được ấn định trong biến $DNS mà thôi). Các DNS server này cũng chỉ có thể trả lời yêu cầu từ máy chủ khi máy chủ "hỏi" và tất nhiên, các DNS server khác sẽ không có cơ hội "trả lời" vì chúng không nằm trong phạm vi cho phép. Điều này cho thấy, máy chủ của chúng ta tin tưởng vào thông tin mà DNS server đã ấn định cung cấp. iptables không thể hạn chế thông tin của các DNS server này cung cấp, ngay cả khi chúng bị hư hoại (poisoned cache chẳng hạn). Ví dụ, www.mypage.net giả định được biên giải thành 123.123.123.123 nhưng DNS server ấy bị nhân nhượng nên www.mypage.net được biên giải thành 124.124.124.124 chẳng hạn thì máy chủ của chúng ta vẫn tiếp nhận gói tin chứa các thông tin này (nếu như chúng thoả mãn các điều kiện iptables đặt ra trên cấp độ ip).

Dòng 23 và 24 có vài điểm cần phân tích. Luật đưa ra ở hai dòng này dùng để kiểm soát và thoả mãn giao thức giữa dịch vụ DNS chạy trên máy chủ của chúng ta và các DNS server khác (server to server). Bởi vậy, thông tin đi và đến xuyên qua cổng 53 từ hai phía (thay vì từ một cổng thuộc $HI_PORTS đến cổng 53 và ngược lại). Đó là lý do tại sao chúng ta phải dùng đến cụm điều kiện cách if / else ở đây. Điểm cốt lõi của hai dòng lệnh này là đưa ra luật kiểm soát cho dịch vụ DNS giữa server và server. Máy chủ cung cấp dịch vụ DNS hầu hết chỉ cần "lắng nghe" và "trả lời" trên cổng 53 UDP ngoại trừ trường hợp một yêu cầu nào đó quá lớn hoặc một yêu cầu cho zone transfer thì mới cần đến cổng 53 TCP -5-

Dòng 26 và 27 tương tự như trên nhưng luật đưa ra dùng để kiểm soát gói tin giữa các clients từ bên ngoài và máy chủ (client to server). Tất nhiên các luật này không ứng dụng cho dịch vụ DNS vì đi đến hai dòng này đã thoát ra ngoài cụm điều kiện cách dùng cho DNS ở trên. Ở đây, thông tin đi xuyên qua cổng 53 của máy chủ và $HI_PORTS của máy con.

Dòng 32, 33, 34 có một số điểm lý thú cần bàn đến. Dựa trên tính "stateful" của giao thức TCP, iptables có thể kiểm soát các gói tin TCP sâu sát hơn UDP rất nhiều.

- Dòng 32 chỉ định rất cụ thể là các gói tin ở tình trạng NEW -6- và có tcp-flags là SYN,RST,ACK SYN thì mới được tiếp nhận. Điều này có nghĩa: một yêu cầu truy cập hoàn toàn mới bằng giao thức TCP thì phải có SYN bit và đối với iptables, gói tin khởi đầu cho một cuộc truy cập hoàn toàn mới vì nó chưa hề có trong bảng theo dõi của netfilter (conntrack table). Vậy nếu một gói tin muốn đi vào (truy cập) nhưng chưa hề có trong bảng theo dõi của netfilter (NEW) và không có SYN bit thì sao? Câu trả lời là tất nhiên iptables sẽ chặn nó lại như theo luật đưa ra ở dòng 32 và đây là điều tốt vì các truy cập hợp lệ (legitimate request) không thể có trường hợp một request mới mà không khởi đầu từ SYN. Trường hợp gói tin ở tình trạng NEW nhưng không có SYN bit rất hiếm thấy (ngoại trừ cố tình tạo ra gói tin ở dạng này để thử thâm nhập). Những gói tin ở trường hợp này đôi khi xuất hiện nếu bạn thiết kế hệ thống "high availability" -7- cho nhiều firewall và các firewall này vì lý do nào đó "lỡ" không chuyển giao các "state" của những gói tin hiện lưu hành xuyên qua firewall nên một gói tin nào đó đang ở tình trạng ESTABLISHED với firewall này có thể ở tình trạng NEW với firewall kia. Nếu iptables nằm trong vùng làm việc của các firewall trên thì thỉnh thoảng sẽ va phải một số gói tin như thế và đây là trường hợp (legitimate) rất ít xảy ra.

- Dòng 33 và 34 dùng để hỗ trợ dòng 32 và tiêu điểm của luật trên hai dòng này là dấu chấm thang (!) đi trước --syn. Chuyện gì sẽ xảy ra ở đây? Ở dòng 32, chúng ta ấn định các gói tin TCP đi vào mang SYN flag và ở tình trạng NEW thì được tiếp nhận, vậy sau khi được tiếp nhận thì chuyện gì tiếp tục xảy ra? Câu trả lời nằm ở dòng 33:

+ các gói tin đi ra ngoài để trả lời mà không mang SYN flag -8- và ở tình trạng ESTABLISHED thì được tiếp nhận. Điều cần nhấn mạnh ở đây là gói tin trả lời đi từ máy chủ của chúng ta không nên là gói tin mang SYN flag bởi vì không có lý do gì để máy chủ phải gởi yêu cầu truy cập đến một máy con nào đó trên Internet. Máy chủ chúng ta dùng để tiếp nhận và trả lời các yêu cầu truy cập cho nên luật ở dòng 33 ngầm chứa một quy định rất khắc khe: không những luật firewall cho máy chủ này chỉ tiếp nhận những yêu cầu đi vào một cách hợp lệ mà còn ngăn ngừa những lưu thông đi ra từ máy chủ một cách thiếu hợp lệ (thử hình dung vì lý do gì đó, máy chủ của chúng ta bị biến thành "zombie" và liên tục gởi SYN request đến các máy khác).

+ tình trạng ESTABLISHED kèm theo trong lệnh này càng nâng cao mức khắc khe. Đối với conntrack table lúc này, gói tin đi ra từ máy chủ để trả lời một yêu cầu truy cập nào đó phải thuộc dạng ESTABLISHED. --syn ở đây ứng dụng cụ thể cho gói tin thuộc giao thức TCP và --state ESTABLISHED ở đây ứng dụng cụ thể cho tính "stateful" của netfilter.

- Dòng 34 tiếp nối hai dòng lệnh trên. Ở giai đoạn này, gói tin đi vào máy chủ và thuộc xuất truy cập hiện tại phải ở tình trạng ESTABLISHED và không mang SYN flag nữa và đây chính là điều được dòng 33 áp đặt. Từ lúc này trở đi, trong suốt xuất truy cập, luật của dòng 33 và 34 điều tác và kiểm soát lưu thông giữa máy con và máy chủ của chúng ta. Cụ thể hơn:

+ nếu cũng từ một IP (cùng một client) gởi một gói tin mang SYN flag và hợp lệ thì nó sẽ được xếp loại NEW và được dòng lệnh 32 "xét xử".

+ nếu cũng từ một IP (cùng một client) gởi một gói tin mang một TCP flag nào đó thiếu hợp lệ và không nằm trong tình trạng được theo dõi bởi conntrack table thì nó bị loại trừ bởi các dòng trong nhóm 37-42 hoặc được quy chế mặc định của firewall xử (còn nhớ -P?).

8. Mở rộng:
Mở rộng? rộng thế nào? smilie. Khó có thể trả lời câu hỏi này thoả đáng vì không có sự cố hoặc nhu cầu thì khó biết được giải pháp? (no solution for unknown problem). Tuy nhiên có vài vấn đề có thể mở rộng một cách tổng quát và ứng dụng cho đa số các trường hợp.

8.1 Vấn đề chung cho mọi giao thức:
8.1.1 Vấn đề các gói tin ở tình trạng INVALID:
Như đã phân tích các tình trạng NEW,RELATED,ESTABLISHED,VALID trong bảng theo dõi của netfilter ở bị chú số 6 (bên dưới). Các gói tin ở tình trạng NEW,RELATED,ESTABLISHED có thể được tiếp nhận tùy theo hoàn cảnh. Tuy nhiên, gói tin ở tình trạng INVALID trên bình diện SPI (xem chú thích về SPI ở case 1), không thể được tiếp nhận với bất cứ lý do nào. Bởi vậy, hai dòng luật như sau có thể đưa vào phía trên dòng 15:


Code:
$IPT -A INPUT -m state --state INVALID -m limit --limit 1/s -j LOG --log-prefix "INVALID_STATE: "
$IPT -A INPUT -m state --state INVALID -j DROP


Dòng trên dùng để log và dòng kế tiếp chính thức cản các gói tin thuộc dạng này. Điểm cần chú ý ở đây là hai dòng lệnh trên không quy định cụ thể loại giao thức nào (bằng thông số -p) cho nên các luật này ứng hiệu cho mọi giao thức. Dòng trên cản phần lớn các gói tin "lạc loài" đi vào firewall với chủ đích hoặc vô tình. Cách áp đặt luật này phía trên dòng 15 không những log và cản các gói tin vi phạm cụ thể mà còn mang tính hiệu năng. Các gói tin vi phạm sẽ bị cản ngay tại vị trí này thay vì tiếp tục đi xuống cho đến khi nào trùng với một luật xử lý nào đó, nếu không thì chúng sẽ tiếp tục đi xuống đến tận chuỗi "clean-up" rule (rồi cũng sẽ bị log và cản). Để duy trì tính an toàn, chúng không nên được phép đi vào.

8.1.2 Vấn đề mạo danh IP của máy chủ:
Kỹ thuật mạo danh IP của một máy nào đó được gọi là "spoofing" theo thuật ngữ chuyên môn. "Spoofing" có nhiều dạng và nhiều mục đích nhưng ở đây chúng ta chỉ đề cập đến trường hợp "ai đó" từ Internet mạo danh địa chỉ của máy chủ chúng ta với mục đích "lừa" firewall mà lẻn vào. Thủ thuật này có độ thành công rất cao khi "thử nghiệm" trên các máy chủ và ngay cả các firewall nếu không điều chỉnh cẩn thận. Thử xét:


Code:
$IPT -A INPUT -i $IF -s $IP -d $IP -m limit --limit 1/s -j LOG --log-prefix "SPOOFING: "
$IPT -A INPUT -i $IF -s $IP -d $IP -j DROP


Các gói tin đi từ bên ngoài vào xuyên qua $IF và từ $IP không thể đến $IP được. Vả lại, làm sao có thể có gói tin được chính IP của máy chủ chúng ta tạo ra lại đi vào từ Internet? Nên nhớ, các gói tin được tạo ra ngay trên chính máy chủ cho chính máy chủ đều đi xuyên qua địa chỉ loopback (127.0.0.1) xuyên qua loopback interface (lo), cho nên, các gói tin đi từ bên ngoài mà mang IP của chính máy chủ chúng ta thì chắc chắn thuộc dạng "spoofing". Tất nhiên để có thể lẻn vào bằng phương thức "spoofing" này, kẻ muốn xâm nhập cần nhiều dữ kiện và điều kiện hơn là chỉ đơn thuần "spoofing" vì SPI là hàng rào cản đầu tiên (xem INVALID state ở trên).

8.2 Vấn đề thuộc giao thức TCP:
8.2.1 Loại trừ các truy cập mang tính thiếu hợp lệ
Thử mở rộng một vài TCP flags như đã bàn đến trong phần 7 ở trên -9-


Code:
a. $IPT -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -s $NET -j DROP

Một gói tin mang tcp flag SYN và FIN cùng một lượt không thể là một gói tin bình thường và hợp lệ. SYN-FIN chỉ thường thấy ở các thao tác rà cổng (port scan) hoặc được dùng với ý định không trong sáng. Gói tin ở dạng này nên loại trừ trước khi đi sâu vào hệ thống. Nếu cần phải log, bạn chỉ cần áp đặt một dòng luật tương tự với target là LOG ở trên.


Code:
b. $IPT -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -s $NET -j DROP

Một gói tin mang tcp flag FIN và RST cùng một lượt cũng có thể được xem bất hợp lệ. FIN flag trong một gói tin hợp lệ dùng để thông báo đầu bên kia dòng tin được chấm dứt để xuất truy cập được kết thúc đúng quy cách. Trong khi đó, RST flag dùng để "xé" ngang một xuất truy cập bất chợt. Trường hợp FIN và RST cùng trong một gói tin là điều bất thường và không nên tiếp nhận.

Trường hợp a, b và các trường hợp tương tự đều có thể tạo những tác động không tốt đến dịch vụ trên máy chủ. Chúng khiến cho hệ thống trên máy chủ phải làm việc nhiều hơn một cách không cần thiết và một số trường hợp các gói tin được "nắn ép" cẩn thận có thể dung hại nặng nề đến hệ thống. Tương tự như đã phân tích ở phần 8.1, hai dòng này nên đặt trên dòng 15 (hoặc trên các dòng lệnh bắt đầu cho phép tiếp nhận gói tin) để mang lại tính cụ thể và hiệu năng khi đưa ra các luật cụ thể.

8.2.2 Cản và log cụ thể cho TCP:
Trên dòng chúng ta cho phép các gói tin TCP đi vào phải mang SYN flag và ở tình trạng NEW. Tất nhiên, các gói tin không thoả mãn quy định trên sẽ bị log và cản ở dòng luật 37, 38. Nếu chúng ta không cần phải log chi tiết chuyện gì xảy và thì đoạn firewall script ở trên vừa đủ để hoạt động. Tuy nhiên, nếu chúng ta cần log và cản các gói tin vi phạm một cách cụ thể thì sao?


Code:
$IPT -A INPUT -p tcp ! --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -m limit --limit 1/s -j LOG --log-prefix "INVALID_SERVICE_REQUEST: "
$IPT -A INPUT -p tcp ! --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j DROP


Hai dòng trên là câu trả lời. Các gói tin TCP không mang SYN flag mà ở tình trạng NEW thì bị log và bị cản một cách cụ thể. Hai dòng này có thể được đưa vào phía trên dòng 32 (còn nhớ đến tính quan trọng với thứ tự của các luật?). Tất nhiên, tính cụ thể và hiệu năng sẽ được hình thành nếu áp đặt chúng ở đúng vị trí.

8.2.3 Loại trừ các truy cập hợp lệ nhưng nguy hại
Có lẽ bạn sẽ hỏi, tại sao các truy cập đã hợp lệ mà lại có thể nguy hại. Cho đến lúc này, chúng ta chỉ áp đặt các luật để cản những gói tin bất hợp lệ. Tuy nhiên, không nhất thiết các gói tin hợp lệ trên bình diện giao thức cũng hợp lệ trên bình diện tinh thần. Trường hợp điển hình nhất là phương thức xử dụng các gói tin hợp lệ để làm cạn kiệt tài nguyên của máy chủ. Thử hình dung trường hợp 1000 truy cập đến máy chủ trong vòng vài giây (chẳng hạn),
- liệu máy chủ đủ sức đáp ứng hay không?
- trong 1000 truy cập này, có bao nhiêu truy cập với "thiện ý" và bao nhiêu với "ác ý"?
- làm sao phân biệt và xử lý những truy cập "ác ý" trong mớ 1000 truy cập ấy?

Trên thực tế, khó có thể phân biệt một cách chính xác các truy cập thiện ý hoặc ác ý nhưng chúng ta có thể biết được những truy cập thiện ý thường có biên độ nhất định -10-

8.2.3.1 Giới hạn truy cập với "connection rate"
"Connection rate" có thể thực hiện bằng chọn lựa -m limit cho bất cứ giao thức nào. Chúng ta chỉ đề cập ở đây cho giao thức TCP và sẽ ứng dụng cho các giao thức khác theo ý muốn. Thử đổi dòng 32 từ:


Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT


trở thành:


Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m limit --limit 3/s --limit-burst 5 -m state --state NEW -j ACCEPT



Chuỗi -m limit --limit 3/s --limit-burst 3 dùng CONFIG_IP_NF_MATCH_LIMIT trên netfilter, một "match" trong gói căn bản và đã được tích hợp vào Linux kernel. "limit match" này ảnh hưởng lớn lao đến dòng lệnh trên bình diện giới hạn "connection rate". Chuỗi này ấn định các gói tin mang SYN flag từ một IP nào đó truy cập đến cổng dịch vụ của máy chủ ở tình trạng NEW. Trong chuỗi -m limit --limit 3/s --limit-burst 3 này, khi ứng dụng trong dòng lệnh, một gói tin sẽ được xử lý theo cơ chế:
--limit-burst ấn định giá trị số lần (cho phép hoặc không cho phép) một gói tin được đi đến bước kế tiếp trong luật (-j ACCEPT hoặc -j DROP hoặc bất cứ "jump to" nào). Mỗi giá trị của --limit-burst là một "giấy phép", mỗi packet trùng với luật này sẽ dùng hết một "giấy phép". Khi --limit-burst bằng 0, gói tin trùng với luật đã hết "giấy phép", thì mọi gói tin mới đi vào dù có trùng với luật quy định hay không đều sẽ không thể "jump" đến target ACCEPT (và do đó sẽ bị DROP bởi policy của firewall hoặc các luật đi theo sau). Vì lý do này, --limit 3/s chính là cơ chế "nạp" giấy phép lại cho --limit-burst. Chuỗi này có ý nghĩa là mỗi 1/3 giây, sẽ tăng --limit-burst lên 1, cho đến khi đạt giá trị tối đa ban đầu (= 3 trong trường hợp này) thì sẽ không tăng nữa.

Cụ thể hơn, tưởng tượng đang có một máy con nào đó truy cập vào máy chủ của chúng ta với tốc độ 50 packet/giây, có nghĩa là cứ 1/50 giây có một packet đi đến máy chủ. Rule trên sẽ xử lí như sau:
-Trong vòng (1/50)*5 = 1/10 giây đầu tiên, 5 giấy phép ban đầu đã được sử dụng hết, gọi thời điểm này là T1 (chẳng hạn). Từ thời điểm T1 trở đi cho đến thời điểm T1+1/3 giây, tất cả packet từ IP này truy cập vào máy chủ sẽ bị DROP.
-Tại thời điểm T1 + 1/3 giây, do qui định của chuỗi --limit 3/s, một giấy phép được nạp vào cho --limit-burst, nhưng gần như ngay tức khắc, giấy phép này được một packet của máy A sử dụng và do đó --limit-burst lại trở về 0 (tiếp tục hết "giấy phép"). Cứ tiếp tục như thế, sau 1/3 giây, sẽ có một packet được chấp nhận và chỉ 1 mà thôi nếu máy A cứ tiếp tục truy cập với tốc độ như trên vào máy chủ.

Nếu máy con ngừng truy cập vào máy chủ thì diễn biến sẽ như sau:
- Cứ sau 1/3 giây, một giấy phép sẽ được nạp vào --limit-burst, và vì bây giờ không còn packet nào được gửi đến do đó --limit-burst sẽ giữ nguyên giá trị. Cứ thể --limit-burst tăng dần cho đến khi chạm quy định ban đầu là 3 thì sẽ ngừng lại, "giấy phép" hoàn toàn ở tình trạng nguyên thuỷ. Trong thời gian --limit-burst tăng lại giá trị ban đầu, nếu máy A lại tiếp tục gửi packet thì những packet này sẽ sử dụng giấy phép trong limit-burst, và lại giảm limit-burst xuống, nếu limit-brust bằng 0 thì tất nhiên firewall sẽ tiếp tục cản các gói tin ở dạng này nếu vẫn tiếp tục vi phạm luật cho đến khi --limit-burst được giải toả (như đã giải thích).

Đây chỉ là một ví dụ minh hoạ ứng dụng -m limit. Bạn cần khảo sát số lượng truy cập đến dịch vụ nào đó trên máy chủ trước khi hình thành giá trị thích hợp cho -m limit. Nên cẩn thận trường hợp một proxy server chỉ có một IP và có thể có hàng ngàn người dùng phía sau proxy; ghi nhận yếu tố này để điều chỉnh limit rate cho hợp lý.

8.2.3.2 Giới hạn truy cập với "connection limit"
"Connection limit" cần huy động đến CONFIG_IP_NF_MATCH_CONNLIMIT có từ patch-o-matic trên website chính của iptables http://www.iptables.org). Module này cần được tải và biên dịch -11- trước khi có thể hoạt động. Ứng dụng tính năng này trên dòng 32 như sau:


Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT


trở thành:

Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -m connlimit ! --connlimit-above 2 -j ACCEPT


-m connlimit ! --connlimit-above 2 quyết định tối hậu đến số phận các gói tin đi vào ngoài các áp đặt đi trước (như gói tin TCP phải mang flag SYN và phải ở tình trạng NEW). Tính linh động nằm ở giá trị đảo (!) phía trước --connlimit-above 2. Dòng lệnh này áp đặt thêm một tầng kiểm soát: các gói tin truy cập này đến từ một IP mà không nhiều hơn 2 xuất truy cập thì tiếp nhận. 3, 4 hoặc hơn xuất truy cập không thể xảy ra từ cùng một máy con (có cùng IP) đến máy chủ. Tính chất này khác hẳn tính chất "connection rate" đã trình bày trong phần 8.2.3.1, "connection limit" dựa trên tính đồng thời (concurrent) của giao thức TCP mà điều tác -12-

8.2.4 Vấn đề độ dài của SYN packet:
Bạn có thật sự paranoid không? Nếu có thì tiếp tục theo dõi phần mở rộng này. Theo RFC 793, SYN packet không mang theo "payload" (dữ liệu) và nếu các hệ thống ứng dụng đúng theo RFC 793 thì SYN packet chỉ có chiều dài tối đa là ở khoảng 40 đến 60 bytes nếu bao gồm các tcp options. Dựa trên quy định này (hầu hết các ứng dụng trên mọi hệ điều hành đều tuân thủ theo quy định của RFC 793), chúng ta có thể hình thành một luật khác cho dòng 32 ở trên:


Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -j ACCEPT


trở thành:


Code:
$IPT -A INPUT -i $IF -p tcp --syn -s $NET --sport $HI_PORTS -d $IP --dport $port -m state --state NEW -m length --length 40:60 -j ACCEPT


Nếu cần, bạn vẫn có thể đưa vào một trong hai chọn lựa "connection rate" hoặc "connection limit" cho dòng lệnh trên để thắt chặt. Điều cần nói ở đây là giá trị -m length --length 40:60 ấn định chiều dài của gói tin SYN của giao thức TCP được firewall chúng ta tiếp nhận. Như đã đề cập ở trên, theo đúng quy định, gói SYN không mang dữ liệu cho nên kích thước của chúng không thể (và không nên) lớn hơn 40:60. Luật trên áp đặt một quy định rất khắc khe để loại trừ các gói SYN lại mang dữ liệu (và đặc biệt mang dữ liệu với kích thước lớn). Theo tôi thấy, những gói tin này rất hiếm thấy ngoại trừ trường hợp cố tình tạo ra hoặc thỉnh thoảng có dăm ba gói "lạc loài" ở đâu vào từ một hệ điều hành nào đó không ứng dụng đúng quy cách. Xử dụng luật này hay không là tùy mức khắc khe của bạn. Cách tốt nhất trước khi dùng, bạn nên thử capture các gói SYN cho suốt một ngày (hoặc nhiều) và mang về phân tích xem có bao nhiêu gói SYN thuộc dạng không cho phép, có bao nhiêu gói tin được xếp loại vào nhóm có chiều dài 40:60 bytes và từ đó mới đi đến quyết định cuối cùng.

8.3 Vấn đề thuộc giao thức UDP:
Giao thức UDP mang tính chất rất khác với TCP cho nên cơ chế điều hoạt và quản lý có những điểm khác biệt. Bởi UDP hoạt động trên căn bản lặp (interation) -13- nên đối với các gói tin thuộc giao thức này có hai điểm cần chú ý:

8.3.1 Vấn đề thuộc số lượng truy cập UDP
Bởi UDP là giao thức thuộc dạng "stateless" nên dịch vụ UDP trên máy chủ chỉ có thể nhận và "cố gắng" thoả mãn yêu cầu. Dịch vụ UDP trên máy chủ:
- không có cách nào kiểm tra xem nguồn truy cập có thật sự hiện hữu hay không; máy chủ cũng không thể phân biệt gói tin UDP đang đi vào là gói đang trả lời ngược lại (thuộc một xuất truy cập hiện có) hay một gói UDP hoàn toàn mới.
- chỉ đơn giản "trả lời" và không cần theo dõi xem gói tin trả lời có đi đến đích hay không.

Dựa trên tính chất này, kẻ tấn công có thể tạo hàng loạt gói tin (1000 yêu cầu trong một giây chẳng hạn) đến một dịch vụ UDP. Dịch vụ này sẽ cần mẫn đặt các yêu cầu vào hàng chờ đợi (queue) và tuần tự xử lý. Tuy nhiên, "queue" của dịch vụ có giới hạn trên căn bản tài nguyên, liệu dịch vụ UDP này chứa được bao nhiêu yêu cầu trên "queue" trước khi máy chủ bị cạn kiệt? Hơn nữa, vì tính "stateless" này mà thông tin chuyển tải xuyên qua UDP nhanh hơn TCP rất nhiều, điều này lại càng tiện lợi cho việc "dội" một dịch vụ UDP trên máy. Trong trường hợp này, -m limit của iptables trở nên hết sức tiện dụng. Thử xem hai dòng 23, 24 trở thành:


Code:
$IPT -A INPUT -i $IF -p udp -s $NET --sport $port -d $IP --dport $port -m state --state NEW,ESTABLISHED -m limit --limit 2/s --limit-burst 2 -j ACCEPT
$IPT -A OUTPUT -o $IF -p udp -s $IP --sport $port -d $NET --dport $port -m state --state ESTABLISHED -m limit --limit 2/s --limit-burst 2 -j ACCEPT


chắc chắn sẽ giúp cho dịch vụ DNS này có đủ thời gian và tài nguyên phục vụ các đòi hỏi về name một cách bình thường. Nên biết rằng, hầu hết các DNS server có thể lưu một bản "cache" cho những IP / Name đã được biên giải cho nên rất hiếm khi một DNS server nào đó đòi hỏi dịch vụ DNS trên máy chủ của chúng ta phải tiếp nhận hơn 2 yêu cầu trong một giây và liên tục 2 lần. Thật ra, giới hạn này vẫn còn rất "dễ chịu" cho một dịch vụ DNS. Tuy nhiên, với các dịch vụ khác cũng dùng giao thức UDP và phục vụ những dòng thông tin ở vận tốc cao (như streaming media chẳng hạn) thì giá trị -m limit trên cần được điều chỉnh cho thích hợp với nhu cầu này.

8.3.2 vấn đề thuộc thực tính của xuất truy cập UDP
Kiểm tra thực tính truy cập cho UDP? Chắc hẳn bạn sẽ hỏi câu này vì ở trên tôi đề cập đến khía cạnh dịch vụ UDP trên máy chủ không có cách nào kiểm tra xem nguồn truy cập có thật sự hiện hữu hay không (nguồn địa chỉ IP). Vậy, giải pháp là sao đây? Phần lớn các cuộc tấn công nghiêm trọng có thể làm tê liệt một dịch vụ bằng giao thức UDP được tạo ra từ các IP giả mạo và các IP thuộc nhóm được IANA phân bố dùng làm IP cho nội mạng -14-. Nếu các địa chỉ dùng để tấn công là các địa chỉ thuộc nhóm public IP thì bạn chỉ có thể giao phó cho -m limit và -m state ở trên. Nếu -m limit được ấn định gắt gao hơn nữa sẽ cản bớt số lượng gói UDP "flood" dịch vụ.

Riêng với các yêu cầu truy cập từ các nhóm IP nội mạng (xem chú thích 14) thì việc lượt bỏ chúng khá đơn giản. Thật ra, việc lọc bỏ này không riêng gì cho giao thức UDP mà còn có thể ứng dụng cho mọi giao thức. Đoạn lệnh sau dùng để thắt chặt vấn đề này:


Code:
NON_NET="10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 224.0.0.0/4 240.0.0.0/5 169.254.0.0/16 192.0.2.0/24"
for entry in $NON_NET; do
$IPT -A INPUT -i $IF -s $entry -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_NET: "
$IPT -A INPUT -i $IF -s $entry -j DROP
done



Biến $NON_NET trên có thể đưa vào nhóm biến được ấn định ở phần trên của firewall script và đoạn lặp "for / done" có thể nằm trên dòng 15 (trước luật đầu tiên ấn định ACCEPT). Dòng luật trong đoạn lặp không ấn định cụ thể giao thức (-p) và cũng không ấn định tình trạng (-m state) nên mọi giao thức và mọi tình trạng đều có tác dụng. Lệnh này trông rất đơn giản nhưng hàm chứa tính kiểm soát rất rộng -15-. Nếu bạn thích, thử tính xem có bao nhiêu địa chỉ cả thảy trong nhóm NON_NET này để hình dung một dòng lệnh đơn giản có thể loại bỏ bao nhiêu IP.

Điều căn bản là nên xem xét kỹ lưỡng trước khi quyết định chạy một dịch vụ UDP trên máy chủ, đặc biệt cho trường hợp một máy đơn vừa là firewall, vừa phải cung cấp dịch vụ thì càng cẩn thận hơn. Nguyên tắc bảo mật không khuyến khích máy chủ cung cấp dịch vụ cũng là firewall vì kiện toàn mô hình này cực kỳ khó khăn để bảo đảm hiệu năng và bảo mật.

8.4 Vấn đề thuộc giao thức ICMP:
Giao thức ICMP là một giao thức rất tiện dụng trong các giềng mối hoạt động của mạng. Tuy nhiên, nó cũng là phương tiện căn bản dùng trong các quy trình tìm hiểu và tấn công. Có những loại ICMP không nên dùng trên mạng công cộng nếu bảo mật là vấn đề hàng đầu vì những loại ICMP này tiết lộ quá nhiều thông tin quan trọng của hệ thống chúng ta muốn bảo vệ. Hơn nữa, có những loại ICMP còn là phương tiện để đưa hệ thống chúng ta muốn bảo vệ vào tình trạng nguy hiểm. Ở đây chúng ta thử đưa ra hai vấn đề chính về việc xử lý ICMP cho máy chủ.

8.4.1 Chọn lựa và giới hạn ICMP
ICMP có 15 loại và mỗi loại có ít nhất là một code khác nhau. Riêng ICMP loại 3 có đến 15 code khác nhau. Vậy, chúng ta nên chọn và giới hạn ICMP nào? Sự chọn lựa này mang tính cá nhân vì mỗi người có cách nhìn khác nhau về ICMP. Riêng tôi, ICMP 0, 3, 4, 8 và 11 nên được dùng, số còn lại không nên cho phép ra vào vì chúng mang những tính chất ảnh hưởng đến vấn đề bảo mật cho máy chủ. Nếu đã chọn lựa cụ thể loại ICMP nào được dùng, tại sao không hình thành một luật cụ thể cho ICMP? Thử ứng dụng đoạn kế tiếp:


Code:
OK_ICMP="0 3 4 8 11"
for item in $OK_ICMP; do
$IPTABS -A INPUT -i $IF -s $NET -p icmp --icmp-type $item -j ACCEPT
$IPTABS -A OUTPUT -o $IF -s $IP -p icmp --icmp-type $item -j ACCEPT
done


Đoạn lặp trên thiết lập nhóm luật xử lý giao thức ICMP cho phép các loại ICMP trong biến $OK_ICMP. Thật ra nhóm luật trên chỉ mới giới hạn loại ICMP được dùng nhưng chưa có bất cứ cơ chế nào kiểm soát lượng lưu thông ICMP ra vào. Bởi vậy, muốn vững hơn thì nên đưa vào -m limit để tạo nên mức kiểm soát cụ thể:


Code:
$IPTABS -A INPUT -i $IF -s $NET -p icmp --icmp-type $item -m limit --limit 1/s --limit-burst 1 -j ACCEPT
$IPTABS -A OUTPUT -o $IF -s $IP -p icmp --icmp-type $item -m limit --limit 1/s --limit-burst 1 -j ACCEPT



-m limit trên áp đặt giá trị "rate" rất khắc khe: chỉ tiếp nhận một gói ICMP trong mỗi giây. Với giới hạn này, các cuộc dội ICMP (ICMP flood) gần như vô tác dụng.

8.4.2 Cản ICMP hoặc cản ICMP "một nửa"
ICMP được dùng làm bước đầu cho những cuộc khám phá một host / network. Có rất nhiều công cụ rà cổng (port scan) dựa trên hồi báo của ICMP để quyết định các bước khám phá kế tiếp. Những thủ thuật tìm hiểu "chữ ký hệ thống" (system foot-print) cũng trông cậy rất nhiều vào ICMP. Bạn có "paranoid"? Vậy thì hãy thử thắt chặt thêm xem sao.

8.4.2.1 Cản ICMP
Mức độ cản ở đây chỉ dừng lại ở mức độ cản không cho các gói ICMP khởi tạo và đi vào từ bên ngoài. Máy chủ có thể khởi tạo các gói ICMP (trong giới hạn các loại ICMP cho phép thuộc biến $OK_ICMP) và các máy bên ngoài chỉ có thể "trả lời" các gói ICMP máy chủ tạo ra. Chức năng -m state một lần nữa hữu dụng cho trường hợp này:


Code:
$IPTABS -A INPUT -i $IF -s $NET -p icmp --icmp-type $item -m state --state ESTABLISHED -m limit --limit 1/s --limit-burst 1 -j ACCEPT
$IPTABS -A OUTPUT -o $IF -s $IP -p icmp --icmp-type $item -m state --state NEW,ESTABLISHED -m limit --limit 1/s --limit-burst 1 -j ACCEPT


Bạn có thể thấy gói tin đi vào xuyên qua chuỗi INPUT chỉ có thể được tiếp nhận ở tình trạng ESTABLISHED nhưng gói tin đi ra xuyên qua chuỗi OUTPUT thì có thể được tiếp nhận ở cả tình trạng NEW và ESTABLISHED. -m state hỗ trợ cho -m limit trong trường hợp này tạo nên các luật rất khắc khe cho ICMP. Có những quan điểm cho rằng quá khắc khe với ICMP không tiện dụng cho các hoạt động mạng; lựa chọn thắt chặt hay không là do quyết định của cá nhân bạn.

8.4.2.2 Cản ICMP "một nửa"
Cản "một nửa" là sao nhỉ? Có ai đó hỏi (một là cản, hai là không, không thể có chuyện "một nửa" ở đây). Vậy mà có cách cản "một nửa" nếu bạn thích những ứng dụng "fancy". Bạn còn nhớ -m length ở phần 8.2.4? Đây chính là chìa khoá của câu trả lời:


Code:
$IPTABS -A INPUT -i $IF -s $NET -p icmp --icmp-type $item -m length 42:43 -m limit --limit 1/s --limit-burst 1 -j ACCEPT
$IPTABS -A OUTPUT -o $IF -s $IP -p icmp --icmp-type $item -m length 42:43 -m limit --limit 1/s --limit-burst 1 -j ACCEPT


Thông thường tiện dụng ping gởi đi một gói dữ liệu nào đó để host được ping theo mặc định -16- . Nếu firewall được ấn định như trên, chỉ có gói tin ICMP nào có chiều dài trong khoảng 42 đến 43 bytes thì mới tiếp nhận. Điều này có nghĩa, khi một ai đó thử ping theo mặc định trên MS-DOS prompt hoặc trên một *nix console chắc chắn sẽ không có kết quả vì không thoả mãn kích thước gói tin đã ấn định. Tính "mở một nửa" nằm ở kích thước cụ thể của gói tin. Chỉ có bạn biết kích thước gói tin là bao nhiêu để ping vào máy chủ thành công (đây chính là tính "mở"); đối với mọi người dùng khác họ sẽ không ping vào máy chủ thành công vì hầu hết họ dùng kích thước gói tin theo mặc định (đây chính là tính "đóng").

Có thể có những cá nhân kiên nhẫn ngồi "rà" từng kích thước gói tin hoặc viết một đoạn script để thực hiện quy trình "rà" này nhưng chuyện này chỉ xảy ra nếu cá nhân ấy nghi ngờ máy chủ chúng ta ấn định kích thước gói tin cụ thể. Đối với người dùng bên ngoài, khả năng cản hoàn toàn và cản "một nửa" ở hai phần 8.4.2.1 và 8.4.2.2 không khác gì nhau vì đơn giản không thể "ping" ngay từ đầu. Với các ứng dụng kiểm soát ICMP trên, mối đe doạ của các dạng tấn công dựa trên ICMP hầu như vô hiệu hoá. Tùy ý bạn mà ứng dụng.

9. Thử nghiệm:
Bài viết cho case 2 này sẽ không đưa ra cụ thể quy trình thử nghiệm. Nếu bạn đã đọc kỹ và chú ý từng chi tiết được đưa ra ở trên, bạn hẳn nhận ra có vô số điều cần và nên thử nghiệm. Tính chất phòng bị và bảo vệ máy chủ được phân tích cụ thể cho từng giao thức ở trên; hãy để tính sáng tạo của mình làm việc cho công tác thử nghiệm vậy smilie

10. Kết luận:
Bài viết phân tích case 2 này không trực tiếp phục vụ mục đích tạo một firewall script có sẵn để người dùng xử dụng ngay. Bài viết này mượn iptables firewall script như một thứ lý do để:
- đi vào tính năng của iptables / netfilter
- đi vào những tình huống có thể xảy ra
- mở rộng cách nhìn bảo mật xuyên qua tính năng và hoạt động của một số giao thức thường dùng.

Với tinh thần bảo mật, bài viết quy tụ về một điểm chính: chỉ cho phép lưu thông hợp pháp. Phần bị chú bên dưới có lẽ không chỉ đơn thuần là bị chú mà là một số phân tích mở rộng những điều được phân tích trong thân bài. Nên xem case 2 này là một phương tiện để khám phá và nên khởi đầu mọi khúc mắc bằng câu hỏi "tôi có vấn đề này" và thử hình thành câu hỏi kế tiếp "tôi có thể làm gì để giải quyết". Hay nói một cách khác, bạn cần hiểu rõ vấn đề (problem) trước khi nghĩ đến giải pháp (solution).

Bị chú:
-1- Authoritative DNS: là name server có thẩm quyền trả lời các thỉnh cầu về tên của một domain và các host trong domain này ở cấp độ chủ quyền. Xem thêm trang http://en.wikipedia.org/wiki/DNS) để tham khảo "authoritative DNS".

-2- Cách gọi "máy chủ" ở đây để chỉ cho máy đơn có hỗ trợ dịch vụ mà chúng ta đang phân tích. Đừng nhầm lẫn với một máy chủ nào khác trong case 2 này.

-3- Giao thức cho các cổng dịch vụ như 80, 443, 25, 110, 22 cho ví dụ trên mang tính chất tương tự nhau trên phương diện kết nối. Ví dụ, một client nào đó từ Internet muốn truy cập một trong các cổng dịch vụ trên, giữa client ấy và máy chủ sẽ đi xuyên qua quy trình bắt tay (3 way handshake) bình thường và thiết lập xuất truy cập (connection). Xuất truy cập này không đòi hỏi huy động thêm một hoặc nhiều cổng dịch vụ khác hoặc giao thức khác để hoàn tất xuất truy cập. Giao thức như FTP chẳng hạn, ngoài quy trình bắt tay bình thường xảy ra ở cổng 21 thuộc máy chủ còn phải huy động thêm một cổng khác cho dữ liệu (cổng 20 nếu dùng active ftp hoặc $HI_PORTS nếu dùng passive ftp). Những giao thức tương tự như FTP không có cùng tính chất như các cổng đưa ra trong ví dụ trên.

-4- --syn là cách viết tắt của --tcp-flags SYN,RST,ACK SYN. --tcp-flags là một chọn lựa trong iptables để xử lý các gói tin với giao thức TCP. Một cách tổng quát mà nói, --tcp-flags có hai giá trị tách rời bởi khoảng trống. Với ví dụ này, giá trị thứ nhất là SYN,RST,ACK và giá trị thứ hai là SYN. Giá trị thứ nhất là danh sách các TCP flags bạn muốn iptables duyệt và giá trị thứ nhì là danh sách các TCP flags được ứng hiệu (được iptables kiểm soát và quyết định cho vào hay bị cản dựa trên sự hiện diện của các flags này). Để xác định các TCP flags thích ứng, bạn cần biết rõ mục đích và kết quả của các flags này. Thông thường các truy cập hợp lệ thường khởi đầu bằng --tcp-flags SYN,RST,ACK SYN như ở đây, trong đó các TCP packets dùng để khởi tạo một xuất truy cập phải chứa SYN flag. Xem thêm tài liệu packet-filtering-HOWTO trên website http://www.iptables.org và tham khảo một cuốn sách hay về TCP/IP như cuốn TCP Illustrated I của Richard Stevens chẳng hạn.

-5- Khi có ý định cung cấp dịch vụ DNS trên máy chủ, bạn cần kiện toàn dịch vụ này để có thể đáp ứng mọi yêu cầu hợp lệ. Thông thường dịch vụ DNS lắng nghe trên cổng 53 UDP đủ phục vụ name resolution cho hầu hết các trường hợp vì hiếm khi chiều dài của gói tin (cho các request / repsond) với giao thức DNS lớn hơn 512 bytes. Nếu chiều dài gói tin này hơn 512 bytes thì dịch vụ DNS của máy chủ phải đi xuyên qua cổng 53 TCP và trường hợp này rất hiếm thấy với các thông tin hợp lệ và bình thường (ngoại trừ trường hợp zone transfer giữa DNS). iptables trong bài viết này chỉ đóng vai trò kiểm soát các gói tin đi ra và đi vào cho dịch vụ DNS đã được hoàn chỉnh. Kiện toàn bảo mật cho DNS server ở cấp độ "application layer" là vấn đề cần thiết và quan trọng. Vấn đề này nằm ngoài phạm vi bài viết về tính năng của iptables.

-6- Các tình trạng NEW,RELATED,ESTABLISHED,VALID được theo dõi trong bảng theo dõi của netfilter (hay còn được gọi là conntrack table) có ý nghĩa và ứng dụng rộng hơn các "state" của TCP socket connection (được thấy khi chạy netstat) và rất cụ thể cho netfilter. Một gói tin ở dạng NEW đối với netfilter mang ý nghĩa rộng hơn một gói tin mang SYN flag thuộc giao thức TCP (mặc dù trên bình diện TCP, SYN packet tương tự như NEW packet vì chỉ có gói tin TCP ở tình trạng NEW mới mang flag SYN).

Ví dụ, một gói tin TCP mang flag là ACK chưa hề có trong conntrack table đi vào iptables firewall:
- việc đầu tiên netfilter sẽ ghi nhận: đây là một gói tin "có thể" thuộc dạng NEW và nếu firewall của chúng ta có chứa một luật (trực tiếp hay gián tiếp) chỉ định rằng firewall không thể tiếp nhận các gói tin TCP thuộc dạng NEW mà lại mang TCP flag là ACK thì
- netfilter sẽ xếp loại gói tin này thành INVALID.

Đối với các giao thức "stateless" như UDP, ICMP thì tính ứng hiệu với các tình trạng NEW,RELATED,ESTABLISHED,VALID rất khác so với TCP. Ví dụ, UDP không hề có flags hay sequence number như TCP nên một gói tin UDP chưa hề có trong conntrack table sẽ được xếp loại là NEW và nếu nó thuộc một xuất truy cập đã ghi nhận thì nó được xếp loại ESTABLISHED.

Conntrack (hoặc Connection tracking) là một chức năng rất mạnh và linh động của netfilter. Nếu dùng -m state ấn định connection state song song với tính chất của từng loại giao thức của các gói tin thì có thể tạo ra các luật hết sức vững vàng và hiệu năng cho firewall.

-7- high availability, một thuật ngữ kỹ thuật. Một dịch vụ ở dạng high availability là dịch vụ hiện hữu ở mức cao độ. High availability chỉ thường thấy có (và thật sự có) ở những môi trường enterprise, nơi sự bền bỉ và sự hiện hữu của dịch vụ là đòi hỏi tối quan trọng.

-8- dấu chấm thang (!) đứng trước giá trị nào đó sẽ nghịch đảo (negate) ý nghĩa của giá trị ấy. Cách dùng này có sẵn trong iptables và rất phổ biến trong các "shell" trên *nix và các ngôn ngữ lập trình nói chung.

-9- Ở đây tôi cố gắng tránh việc cung cấp quá nhiều thông tin cho mỗi chọn lựa có thể ứng dụng. Hai ví dụ trên nhằm mục đích minh hoạ mức uyển chuyển và linh động iptables cho phép chúng ta hình thành các luật ứng dụng cho firewall. Để khai triển góc độ này, kiến thức về giao thức TCP và ứng dụng cụ thể cho nhu cầu của từng trường hợp là hai yếu tố tối quan trọng để hình thành các luật ở cấp độ này.

-10- Vấn đề này thuộc phạm vi "trend analysis" các dạng truy cập đến một dịch vụ. Đây là một công tác phức tạp, đòi hỏi công tác quan sát và phân tích. Tổng quát mà nói, một client truy cập vào một trang web trung bình thường mất vài giây và người ấy thường dừng lại ở trang này ít nhất là vài chục giây để lượt qua xem thông tin ở trang này có phù hợp với nhu cầu hay không. Trọn bộ quá trình truy cập mang tính "thiện ý" này có thể kéo dài ít nhất là trên dưới một phút trước khi người dùng ấy tiếp tục gởi yêu cầu truy cập mới. Bằng cách thu thập và phân tích biên độ truy cập của các người dùng, chúng ta có thể hình thành một con số tương đối cho giá trị truy cập thuộc phạm vi "thiện ý" ở đây.

-11- Vá Linux kernel và iptables cho mục đích dùng thêm các module (không thuộc nhóm base của netfilter) rất đơn giản. Sơ lược các bước như sau:
- tải gói patch-o-matic-ng-<yyyymmdd>.tar.bz2 từ website của iptables http://www.iptables.org)
- xả nén gói vá này ở nơi nào đó thích hợp.
- chuyển vào thư mục chứa mã nguồn Linux và chạy: make clean mrproper để dọn dẹp những object cũ có thể tạo trở ngại trước khi vá.
- chuyển vào thư mục chứa mã nguồn iptables và chạy: make distclean
- chuyển vào thư mục chứa các miếng vá sau khi xả nén xong (bước trên)
- chạy lệnh: KERNEL_DIR=<path_to_kernel_src> IPTABLES_DIR=<path_to_iptables_src> ./runme connlimit. Trong đó connlimit chính là miếng vá cần thiết.
- biên dịch lại Linux kernel (tham khảo thêm series 4 bài "Tái biên dịch Linux kernel ở: http://www.diendantinhoc.net/?articl...=tute_nix và các bài tiếp theo)
- tái khởi động máy sau khi biên dịch Linux kernel hoàn tất và thành công
- chuyển vào thư mục chứa mã nguồn của iptables (đã được patch ở trên) và tái biên dịch lại iptables. Xem thêm chi tiết trong hồ sơ INSTALL có trong thư mục chứa mã nguồn của iptables.

-12- Giao thức TCP mang tính đồng thời (concurrent). Mỗi dịch vụ TCP đang hoạt động ở tình trạng "lắng nghe" (LISTEN) trên một cổng dịch vụ nào đó. Tình trạng này duy trì cho đến khi nào dịch vụ này được tắt bỏ hoặc bị tắt bỏ (vì bị treo, chẳng hạn).

Cứ mỗi xuất truy cập từ một máy con vào dịch vụ TCP trên server của chúng ta sẽ,
- được tạo ra một socket riêng biệt và socket này tồn tại cho đến khi xuất truy cập giữa máy con và máy chủ kết thúc.
- mỗi xuất truy cập mang cổng nguồn (source port) khác nhau trên máy con và,
- máy chủ phải có trách nhiệm phục vụ từng xuất truy cập trên từng cổng của máy con.

Dựa trên tính chất này, chúng ta thấy một máy con có thể đòi hỏi nhiều xuất truy cập cùng một lúc và máy chủ có thể đáp ứng yêu cầu này theo đúng tính chất hoạt động của TCP. Tuy nhiên, điểm cần đưa ra ở đây thuộc phạm trù bảo mật là, nếu máy con yêu cầu nhiều xuất truy cập mang tính "ác ý" (như một dạng DoS) chẳng hạn thì sao? Tình trạng có thể xảy ra:
- máy chủ vận động nhiều process để tạo các socket đáp ứng máy con
- máy chủ có thể bị cạn kiệt tài nguyên dự trữ để tạo socket
- dịch vụ được yêu cầu truy cập có thể bị mất hiệu năng vì không đáp ứng kịp với quá nhiều yêu cầu
- các dịch vụ liên hệ bị treo hoặc không thể tiếp tục hoạt động vì tài nguyên trên máy bị cạn kiệt
- các máy con khác không thể truy cập máy chủ vì máy chủ không còn khả năng đáp ứng,
- và điều tệ hại nhất là máy chủ bị hoàn toàn tê liệt vì quá tải.

Nói một cách công bằng, dịch vụ trên máy của cố gắng đáp ứng các yêu cầu theo đúng chức năng nhưng vì không đủ tài nguyên nên phải dẫn đến tình trạng trên. vậy, bao nhiêu tài nguyên thì đủ cho máy chủ? Con số này phải được hình thành từ quá trình theo dõi và đúc kết số lần truy cập, tầng số truy cập... trên máy chủ. Trên bình diện bảo mật, firewall có thể dùng để trợ giúp các dịch vụ bằng cách hạn chế các xuất truy cập "concurrent".

-13- Giao thức UDP mang tính lặp (iteration). Mỗi dịch vụ UDP đang hoạt động trên máy chỉ tiếp nhận yêu cầu từ client ở một cổng (thay vì mở ra socket mới như TCP). Hầu hết dịch vụ UDP trên máy chủ ở trong trạng thái "ngủ" (sleep) cho đến khi một client nào đó gởi yêu cầu truy cập đến, dịch vụ này mới "thức dậy" để trả lời client. Nếu có nhiều client yêu cầu cùng một lúc, các yêu cầu này được sắp hàng và dịch vụ UDP này sẽ trả lời tuần tự nó đã tiếp nhận từng yêu cầu cho đến khi hoàn tất. Header của UDP rất đơn giản so với TCP, hoàn toàn không có cơ chế để kiểm tra đường đi, lối về của các gói tin ngoài thông tin cổng nguồn và cổng đích (source port and destination port). Bởi thế, kiểm tra và quản lý các gói tin UDP nằm ở một bình diện hoàn toàn khác TCP.

-14- Nhóm private IP cho nội mạng, đôi khi còn gọi là "non-routable IP", ám chỉ các IP này không thể route ra ngoài mạng công cộng (thật tế chúng vẫn có thể route được, nhưng chỉ trong nội mạng). Các nhóm private IP này gồm có:
Class A: 10.0.0.0/8
Class B: 172.16.0.0/12
Class C: 192.168.0.0/16
Class D: 224.0.0.0/4
Class E: 240.0.0.0/5
Link Local: 169.254.0.0/16
Test Net: 192.0.2.0/24
IP từ các nhóm này không thể xuất hiện trên mạng công cộng (public network) và tất nhiên không nên cho phép đi vào hệ thống máy chủ. Tham khảo thông tin từ website IANA để nắm thêm chi tiết quy định các network class trên.

-15- Đây chỉ là một đề nghị, hay nói đúng hơn là một chia xẻ từ kinh nghiệm cá nhân. Để hình thành các luật firewall gọn gàng, súc tích và chặt chẽ, có hai nguyên tắc cần nhớ:
- luật nào cho phép thì phải cụ thể tối đa.
- luật nào ngăn cản thì phải tổng quát hết mức.

Để cho phép các gói tin đi vào (hoặc đi ra) và chỉ cho phép những gói tin nào thoả mãn yêu cầu của chúng ta thì luật cho phép phải càng cụ thể càng tốt vì nó loại bỏ những những sơ sót có thể xảy ra khi "cho phép". Trong khi đó, để ngăn cản các gói tin đi vào (hoặc đi ra) thì luật ngăn cản nên tổng quát và bao trùm một tập họp những tình huống, điều kiện mang tính chất tương tự.

-16- Kích thước mặc định của gói tin ICMP gởi đi từ tiện ích "ping" có giá trị tùy theo ứng dụng của hệ điều hành. Ví dụ Windows ping dùng 32 bytes theo mặc định, *nix nói chung dùng 56 bytes. Để ping với kích thước gói tin theo ý muốn thì:
- trên windows: dùng thông số -l (ping -l <size> <host>smilie
- trên *nix: dùng thông số -s (ping -s <size> host>smilie

Tổng kết đoạn script case 2:

[code]
# các thông số cần thiết
IF=`/sbin/route | grep -i 'default' | awk '{print$8}'`
IP=`/sbin/ifconfig $IF | grep "inet addr" | awk -F":" '{print$2}' | awk '{print $1}'`
IPT="/usr/local/sbin/iptables"
NET="any/0"
DNS="xxx.xxx.xxx.xxx yyy.yyy.yyy.yyy.yyy"
SERV_TCP="22 25 80 443 110"
SERV_UDP="

SỬ DỤNG GRUB

Biên soạn bởi: Lâm Vĩnh Niên, (nien.lam -at- gmail -dot- com)
Phiên bản: v1.2 (040115)
Các thay đổi:

v1.2 (040115): bổ sung và sửa chữa

v1.0 (030731): phiên bản đầu tiên

Tài liệu này hướng dẫn cách sử dụng GRUB, một trình khởi động mạnh và linh hoạt dùng cho PC.
Nội dung

1. Giới thiệu về GRUB

1.1. Tổng quát
1.2. Tính năng

2. Cài đặt GRUB

2.1. Nơi tải GRUB xuống
2.2. Cài đặt GRUB trong môi trường Linux

3. Sử dụng GRUB

3.1. Chuẩn bị các tập tin cần thiết
3.2. Thuật ngữ dùng trong GRUB

3.2.1. Xác định thiết bị
3.2.2. Xác định tập tin

3.3. Các tập tin hình ảnh của GRUB
3.4. Cơ chế khởi động dùng trong GRUB
3.5. Tạo ổ đĩa mềm khởi động GRUB
3.6. Cài GRUB trong môi trường nguyên thuỷ của GRUB

3.6.1. Cài GRUB dùng lệnh setup
3.6.2. Cài GRUB dùng lệnh install

3.7. Cài GRUB trong môi trường hệ điều hành giống Unix

3.7.1. Cài GRUB dùng lệnh grub-install
3.7.2. Cài GRUB trong shell grub
3.7.3. Ánh xạ giữa các ổ đĩa BIOS và các thiết bị hệ điều hành

3.8. Khởi động hệ thống với GRUB

3.8.1. Khởi động hệ điều hành trực tiếp
3.8.2. Tải trình nạp khởi động khác
3.8.3. Một số thí dụ

3.8.3.1. Linux
3.8.3.2. FreeBSD
3.8.3.3. NetBSD
3.8.3.4. OpenBSD
3.8.3.5. DOS/Windows

3.9. Cấu hình
3.10. Bảo mật cho GRUB
3.11. Giao diện người dùng của GRUB

3.11.1. Giao diện dòng lệnh
3.11.2. Giao diện thực đơn

3.12. Một số lệnh trong GRUB

3.12.1. Các lệnh chỉ dùng cho thực đơn
3.12.2. Các lệnh chung
3.12.3. Các lệnh dùng ở dòng lệnh và đề mục thực đơn

4. Một số ứng dụng cụ thể và vấn đề thường gặp

4.1. Tạo đĩa mềm khởi động GRUB với giao diện thực đơn
4.2. Khởi động đĩa mềm có nhân Linux
4.3. Tạo đĩa CD khởi động với GRUB
4.4. Khởi động Windows từ đĩa cứng thứ hai
4.5. Khởi động nhiều bản Windows cài đặt trên một đĩa cứng
4.6. Khởi động GRUB từ ntldr
4.7. Khởi động ổ CD
4.8. Khởi động vào các runlevel khác nhau của nhân Linux
4.9. Một số vấn đề khác

5. Tài liệu tham khảo



1. Giới thiệu về GRUB
1.1. Tổng quát

GRUB là trình khởi động máy tính – nó có nhiệm vụ tải nhân và khởi động hệ thống Linux cũng như một số hệ điều hành khác: FreeBSD, NetBSD, OpenBSD, GNU HURD, DOS, Windows 95, 98, Me, NT, 2000 và XP...

Năm 1995, Erich Boley thiết kế GRUB. Năm 1999, Gordon Matzigkeit và Yoshinori K. Okuji kế thừa GRUB thành gói phần mềm GNU chính thức.
1.2. Tính năng

* GRUB hỗ trợ nhiều hệ điều hành – bằng cách khởi động trực tiếp nhân hệ điều hành hoặc bằng cách nạp chuỗi (chain-loading).
* GRUB hỗ trợ nhiều hệ thống tập tin: BSD FFS, DOS FAT16 và FAT32, Minix fs, Linux ext2fs và ext3fs, ReiserFS, JSF, XFS, và VSTa fs.
* GRUB cung cấp giao diện dòng lệnh linh hoạt lẫn giao diện thực đơn, đồng thời cũng hỗ trợ tập tin cấu hình.

2. Cài đặt GRUB
2.1. Nơi tải GRUB xuống

GRUB có sẵn ở ftp://alpha.gnu.org/gnu/grub hoặc các mirror của nó. Tên gói GRUB có dạng grub-version.tar.gz, thí dụ grub-0.93.tar.gz.

Ngoài ra, phiên bản mới nhất của GRUB cũng có thể được tải về qua CVS với kho là :pserver:anoncvs@subversions.gnu.org:/cvsroot/grub và mô-đun là grub, không cần password cho anoncvs. Do đó có thể làm như sau:

Code:
cvs -d :pserver:anoncvs@subversions.gnu.org:/cvsroot/grub login
Password: <ENTER>
cvs -d :pserver:anoncvs@subversions.gnu.org:/cvsroot/grub co grub
cvs -d :pserver:anoncvs@subversions.gnu.org:/cvsroot/grub logout


Một số hệ điều hành cung cấp GRUB dưới dạng đóng gói riêng, chẳng hạn như dạng rpm (có thể tìm thấy trong các bản phân phối Red Hat, SUSE...), dạng deb (trong bản phân phối Debian).
2.2. Cài đặt GRUB trong môi trường Linux

Cần phân biệt 2 bước của cài đặt GRUB: (i) cài đặt trong môi trường hệ điều hành để có thể sử dụng được GRUB và, (ii) cài đặt GRUB để GRUB làm trình khởi động máy tính. Bước 2 sẽ được đề cập trong chương Sử dụng GRUB.

Sau khi tải về một thư mục thích hợp, giải nén bằng lệnh

tar xzvf grub-0.93.tar.gz

Sau đó:

cd grub-0.93.tar.gz
./configure


(Để liệt kê các tuỳ chọn khi biên dịch:

./configure --help | more

)

Tiếp theo:

make
make install


Quá trình này sẽ cài đặt shell grub, chương trình kiểm tra multiboot mbchk, các hình ảnh GRUB (thông thường được cài vào thư mục /usr/share/grub/i386-pc), tài liệu hướng dẫn sử dụng và trang man của GRUB.
3. Sử dụng GRUB
3.1 Chuẩn bị các tập tin cần thiết

Có hai cách cài đặt GRUB làm trình khởi động máy tính: dùng môi trường nguyên thuỷ của GRUB (cách này được khuyên dùng) hoặc dùng môi trường hệ điều hành giống Unix. Để cài đặt GRUB trong môi trường nguyên thuỷ của GRUB, cần tạo đĩa mềm khởi động GRUB. Cài đặt GRUB trong môi trường hệ điều hành giống Unix dùng công cụ grub-install hoặc shell grub, tuy nhiên chúng có thể thăm dò sai BIOS.

Trước khi cài GRUB làm trình khởi động cần chép các tập tin stage1, stage2 và *stage1_5 từ thư mục /usr/share/grub/i386-pc (thư mục hình ảnh) vào thư mục /boot/grub (thư mục khởi động). Trong số các tập tin *stage1_5 có thể chỉ cần chép tập tin thích hợp với hệ thống tập tin của /boot/grub, chẳng hạn chép tập tin e2fs_stage1_5 nếu thư mục này nằm trên ext2 hoặc ext3. Ngoải ra có thể chép tập tin splash.xpm.gz vào thư mục /boot/grub.
3.2. Thuật ngữ dùng trong GRUB
3.2.1. Xác định thiết bị
(thiết-bị[,số-thứ-tự-phân-vùng][,chữ-cái-tiểu-phân-vùng-bsd])

* []: thông số tuỳ chọn
* thiết-bị: fd (ổ đĩa mềm) hoặc hd (ổ đĩa cứng, GRUB không phân biệt IDE hay SCSI hay RAID) theo sau bởi một con số biểu thị số của thiết bị theo BIOS và bắt đầu với 0, ví dụ ổ đĩa cứng IDE sơ cấp được đánh số 0, còn ổ đĩa cứng IDE thứ cấp được đánh số 1. Thứ tự này tương đối tương đương với cách nhân Linux sắp xếp các thiết bị theo chữ cái (a tương ứng với 0, b tương ứng với 1, v.v...). Cũng có thể thiết lập thiết-bị ở dạng thập lục phân hoặc thập phân, thí dụ

(hd0)
(0x80)
(128)

là tương đương nhau.
* số-thứ-tự-phân-vùng: là số thứ tự của phân vùng trên ổ đĩa, cũng bắt đầu với 0, phân vùng mở rộng bắt đầu bằng 4, bất kể số phân vùng sơ cấp thực có trên ổ đĩa.
* chữ-cái-tiểu-phân-vùng-bsd: đại diện cho tiểu phân vùng của BSD, như a hay e.

Cú pháp tắt gọi tiểu phân vùng BSD là (thiết-bị[,chữ-cái-tiểu-phân-vùng-bsd]), trong trường hợp này GRUB sẽ tìm phân vùng PC đầu tiên chứa nhãn đĩa BSD, rồi tìm tiểu phân vùng đưọc yêu cầu.

Thí dụ:

* (hd0): toàn bộ ổ đĩa thứ nhất (hoặc MBR khi cài đặt GRUB)
* (hd0,0): phân vùng thứ nhất trên ổ đĩa cứng thứ nhất (hoặc sector khởi động của phân vùng này khi cài GRUB)
* (hd0,4): phân vùng mở rộng thứ nhất trên ổ đĩa cứng thứ nhất
* (hd1,a): phân vùng BSD a trên ổ đĩa cứng thứ hai; nếu cần xác định cụ thể số PC slice nào được dùng, sử dụng cú pháp như (hd1,0,a), nếu bỏ trống số PC slice, GRUB tìm PC slice đầu tiên có phân vùng BSD a
* (fd0): ổ đĩa mềm thứ nhất

Ở hệ thống có 2 đĩa cứng IDE và 2 đĩa cứng SCSI, trình tự khởi động trong BIOS được thiết lập là "IDE trước SCSI", GRUB sẽ dùng các nhãn sau:

* (hd0) Đĩa cứng IDE thứ nhất
* (hd1) Đĩa cứng IDE thứ hai
* (hd2) Đĩa cứng SCSI thứ nhất
* (hd3) Đĩa cứng SCSI thứ hai

Ngoài ra còn có thiết bị ổ đĩa mạng (nd) nếu khi cài đặt GRUB có bật tính năng hỗ trợ mạng. Có thể dùng chức năng hoàn thành dòng lệnh của GRUB, ví dụ gõ root ( rồi <TAB>, GRUB sẽ liệt kê các ổ đĩa, phân vùng, hay tên tập tin.
3.2.2. Xác định tập tin
Có 2 cách xác định tập tin, bằng tên tập tin tuyệt đối hoặc bằng danh sách khối.

* Tên tập tin tuyệt đối của GRUB giống với tên tập tin tuyệt đối Unix, dùng / làm dấu phân cách thư mục. Ví dụ:

(hd0,0)/boot/grub/menu.lst

có nghĩa là tập tin (hd0,0)/boot/grub/menu.lst nằm ở phân vùng đầu tiên của ổ đĩa cứng thứ nhất. Nếu bỏ qua tên thiết bị trong tên tập tin tuyệt đối, GRUB dùng thiết bị root ngầm định. Thí dụ nếu đã thiết lập thiết bị root, chẳng hạn như (hd1,0), bằng lệnh root thì /boot/kernel có nghĩa là (hd0,1)/boot/kernel.

* Danh sách khối (block list) dùng để xác định tập tin không xuất hiện trong hệ thống tập tin, chẳng hạn như một trình nạp chuỗi (chainloader). Cú pháp:

[offset]+độ-dài[,offset]+độ-dài]...

Thí dụ

0+100,200+1,300+300

GRUB đọc các khối 0 đến 99, khối 200 và khối 300 đến 599.

Nếu bỏ qua offset, GRUB sẽ lấy offset là 0.

Cũng như trong cú pháp tên tập tin, nếu danh sách khối không chứa tên thiết bị thì GRUB sẽ dùng thiết bị root của GRUB. Thí dụ +1 khi thiết bị root là (hd0,1) tương ứng với (hd0,1)+1.

Lệnh blocklist liệt kê danh sách khối của tập tin, ví dụ:

grub> blocklist (hd1,0)/vmlinuz
(hd1,0)1322144+96,1322248+1227

có nghĩa là tập tin vmlinux, nằm ở phân vùng thứ nhất của đĩa cứng thứ hai, chiếm 96 khối kể từ khối 1322144 và 1227 khối kể từ khối 1322248 – có thể thấy rằng tập tin này hơi bị phân mảnh.

3.3. Các tập tin hình ảnh của GRUB
GRUB bao gồm một số hình ảnh: 2 giai đoạn chính, các giai đoạn tuỳ chọn gọi là Giai đoạn 1.5, và 2 hình ảnh khởi động mạng.

Code:
stage1
Giai đoạn 1, là một hình ảnh chính dùng đề khởi động GRUB, kích thước 512 byte.
stage2
Giai đoạn 2, là hình ảnh cốt lõi của GRUB.
e2fs_stage1_5
fat_stage1_5
ffs_stage1_5
jfs_stage1_5
minix_stage1_5
reiserfs_stage1_5
vstafs_stage1_5
xfs_stage1_5

Tất cả các hình ảnh này được gọi là Giai đoạn 1.5.
nbrub
pxebrub
Là các hình ảnh khởi động mạng.

3.4. Cơ chế khởi động dùng trong GRUB
Trên sector thứ nhất của đĩa cứng chứa, ngoài bảng phân vùng, một đoạn mã thực thi được là giai đoạn đầu tiên của quá trình khởi động máy tính, hoặc đoạn mã IPL (initial program load). Đoạn mã chuẩn này là cái mà lệnh fdisk /mbr trên DOS tạo ra. Khi thiết lập trong BIOS quy định khởi động từ đĩa cứng đó, BIOS sẽ trao quyền điều khiển cho IPL hoặc đoạn mã giai đoạn một. Khi đoạn mã chuẩn được nạp, nó sẽ quyết định phân vùng nào là chủ động (active) và trao quyền điều khiển cho đoạn mã thực thi được nằm ở trong hoặc gần sector thứ nhất của phân vùng chủ động. Những gì xảy ra tiếp theo phụ thuộc vào hệ điều hành. Ở các hệ điều hành DOS cũ, phần cốt lõi thi hành được của hệ điều hành nằm ngay tại vị trí đầu tiên của đĩa và được khởi động trực tiếp từ giai đoạn một. Trong các trường hợp điển hình hơn, một chương trình khởi động giai đoạn hai sẽ được nạp và đến lượt nó sẽ biết nơi nào để tìm nhân hoặc các thành phần cốt lõi của hệ điều hành và khởi động chúng. Khi GRUB hoặc một trình khởi động được cài đặt, đoạn mã của trình khởi động đó sẽ thay thế đoạn mã IPL chuẩn. Nó phải vừa vặn trong 512 byte và còn phải chia sẻ chung với bảng phân vùng. Khác biệt chính giữa một trình khởi động và đoạn mã IPL chuẩn là quyền điều khiển sẽ đi đâu tiếp sau đó. Trong trường hợp của GRUB, quyền điều khiển sẽ được trao cho trình Giai đoạn 2 (hoặc Giai đoạn 1.5).

Giai đoạn 1 được cài vào MBR hoặc vào sector khởi động của phân vùng, còn Giai đoạn 2 được đặt trên một hệ thống tập tin. Giai đoạn 1.5 có thể được cài trong một hệ thống tập tin (chẳng hạn như ở phân vùng /boot), trong vùng khởi động của FFS hoặc ReiserFS, và trong các sector ngay sau MBR vì Giai đoạn 1.5 đủ nhỏ và các sector ngay sau MBR thường không được sử dụng. Kích thước của vùng này là số sector cho mỗi head trừ đi 1. Giai đoạn 1.5 hoặc Giai đoạn 2 có thể được đặt ở bất cứ nơi đâu, và Giai đoạn 2 có thể nạp tập tin cấu hình từ bất cứ nơi đâu trên đĩa cứng (tập tin cấu hình không cần phải được đặt trong một hệ thống tập tin).

Vì vậy tất cả công việc mà Giai đoạn 1 phải làm là tải Giai đoạn 2 hoặc Giai đoạn 1.5. Giai đoạn 1 mã hoá vị trí của Giai đoạn 2 (hay Giai đoạn 1.5) ở dạng danh sách khối, nên nó không hiểu bất cứ cấu trúc hệ thống tập tin nào. Vì GRUB hỗ trợ cả chế độ CHS lẫn LBA nên Giai đoạn 1 trong GRUB, sau khi thăm dò thông số và chế độ truy cập của đĩa cứng, chỉ tải sector đầu tiên của Giai đoạn 2 (hoặc Giai đoạn 1.5) và Giai đoạn 2 tự nó tải phần còn lại (tức là tải từ địa chỉ bắt đầu của nó cộng thêm 512 byte).

Giai đoạn 1.5 là cầu nối giữa stage1 và stage2, nghĩa là Giai đoạn 1.5 được Giai đoạn 1 nạp và Giai đoạn 1.5 nạp Giai đoạn 2. stage1 không hiểu bất kì hệ thông tập tin nào nhưng *_stage1_5 hiểu một hệ thống tập tin (chẳng hạn e2fs_stage1_5 hiểu ext2fs. Giai đoạn 1.5 cho phép Giai đoạn 2 có thể được nạp từ một hệ thống tập tin bằng đường dẫn thông thường mà không cần phải dùng danh sách khối. Vì vậy có thể an toàn di chuyển vị trí của stage2 đến một nơi khác (chẳng hạn như khi giải phân mảnh hệ thống tập tin), ngay cả sau khi GRUB đã được cài đặt. Gai đoạn 1 nạp Giai đoạn 1.5 vào bộ nhớ nếu cần. Một số phần cứng cần bước trung gian để nạp Giai đoạn 2, chẳng hạn như khi phân vùng /boot nằm ở vị trí quá 1024 cylinder đầu của ổ cứng hoặc khi sử dụng chế độ LBA.
3.5. Tạo ổ đĩa mềm khởi động GRUB
Là quá trình chép các tập tin stage1 và stage2 từ thư mục hình ảnh vào block thứ nhất và thứ hai trên đĩa mềm. Quá trình này sẽ phá huỷ dữ liệu hiện đang lưu trữ trên đĩa mềm.

Các lệnh để thực hiện điều này trên một hệ điều hành giống UNIX:

# cd /usr/share/grub/i386-pc
# dd if=stage1 of=/dev/fd0 bs=512 count=1
1+0 records in
1+0 records out
# dd if=stage2 of=/dev/fd0 bs=512 seek=1
153+1 records in
153+1 records out
#

3.6. Cài GRUB trong môi trường nguyên thuỷ của GRUB
3.6.1. Cài GRUB dùng lệnh setup
Cài stage1 của GRUB theo cách này sẽ xoá sector khởi động đang được một hệ điều hành sử dụng. Hiện tại GRUB có thể trực tiếp khởi động GNU Mach, Linux, FreeBSD, NetBSD, và OpenBSD, vì vậy dùng GRUB trên sector khởi động thường là an toàn. Nhưng nói chung nên sao lưu sector đầu tiên của phân vùng sắp cài stage1 của GRUB. Điều này không quan trọng lắm nến cài GRUB vào sector đầu tiên của đĩa cứng, vì dễ dàng khôi phục nó (chẳng hạn như chạy fdisk /mbr trong DOS).

Để cài GRUB trong môi trường nguyên thuỷ, vốn là điều được khuyên, cần tạo đĩa khởi động GRUB và khởi động lại máy tính với đĩa khởi động đó. Một khi đã được khởi động, GRUB sẽ trình bày giao diện dòng lệnh.

Đầu tiên, định thiết bị root cho thư mục khởi động:

grub> root (hd0,0)

Có thể dùng lệnh find nếu không chắc phân vùng nào thực sự chứa các tập tin này:

grub> find /boot/grub/stage1

Cần lưu ý là thiết bị root của GRUB không nhất thiết là phân vùng root của hệ điều hành (nếu cần xác định phân vùng root cho hệ điều hành, thêm thông số đó vào lệnh kernel).

Một khi đã thiết lập thiết bị root chính xác, chạy lệnh setup:

grub> setup (hd0)

Lệnh này sẽ cài GRUB lên MBR của ổ đĩa thứ nhất. Nếu muốn cài GRUB vào sector khởi động của một phân vùng thay vì vào MBR, chỉ định phân vùng muốn cài GRUB:

grub> setup (hd0,0)

Nếu cài GRUB vào phân vùng hoặc ổ đĩa không phải là ổ đĩa đầu tiên, cần nạp chuỗi GRUB từ một trình khởi động khác.

Bây giờ có thể khởi động GRUB mà không cần đĩa mềm GRUB.

Nói thêm về lệnh setup:

setup [--force-lba] [--stage2=tập_tin_stage2_hđh] [--prefix=thư_mục] thiết_bị_cài_đặt [thiết_bị_hình_ảnh]

Lệnh này dùng để cài đặt GRUB tự động. setup không truy cập trực tiếp vào đĩa cứng mà gọi embed và install để thực hiện công việc. Trước hết nó kiểm tra xem có một tập tin stage1.5 hay không và có thể nhúng (embed) vào một nơi an toàn hay không, Sau đó, setup sử dụng install, một lệnh linh hoạt hơn, ở hậu trường và cài GRUB vào thiết bị thiết_bị_cài_đặt. Nếu chỉ định thiết_bị_hình_ảnh, nó sẽ tìm các hình ảnh GRUB trong thiết bị thiết_bị_hình_ảnh, nếu không nó sẽ dùng thiết bị root hiện tại được thiết lập bằng lệnh root. Nếu thiết_bị_cài_đặt là một đĩa cứng, nó sẽ nhúng Giai đoạn 1.5 nếu có thể. Tuỳ chọn --prefix chỉ định thư mục đặt các hình ảnh GRUB. Nếu không được chỉ định, GRUB sẽ tự động tìm chúng trong /boot/grub và /grub (dĩ nhiên là trong thiết bị root đã được quy định bởi lệnh root trước đó.)

Nếu có chỉ định, các tuỳ chọn --force-lba và --stage2 được chuyển vào lệnh install.

Thí dụ về cài GRUB lên đĩa cứng với /boot được gán trên phân vùng riêng biệt:

setup (hd0) (hd2,0)

Xuất hiện các thông báo:
Code:
Checking "/boot/grub/stage1" no
Checking "/grub/stage1" yes
Checking "/grub/stage2" yes
Checking "/grub/stage1_5" yes
Running "embed/grub/e2fs_stage1_5 (hd0)" 22 sectors are embedded
Running "install /grub/stage1 d (hd0) (hd0)1+22 p (hd2,0)/grub/stage2 /grub/menu.lst”


Lưu ý: stage1.5 đã được nhúng và (/boot)/grub/stage2 đã thay đổi (cập nhật vị trí tương ứng của stage2 và menu.lst).
3.6.2. Cài GRUB dùng lệnh install

install [--force-lba] [--stage2=tập_tin_stage2_hđh] tập_tin_stage1 [d] thiết_bị_đích tập_tin_stage2 [địa_chỉ] [p] [tập_tin_cấu_hình] [tập_tin_cấu_hình_thực]

Lệnh này khá phức tạp, và không nên dùng nếu không quen thuộc với GRUB – thay vào đó nên dùng setup.

Nói ngắn gọn, lệnh này sẽ thực hiện một cài đặt đầy đủ với giả định Giai đoạn 2 hay 1.5 đã có tại vị trí cài đặt cuối cùng.

Đi vào chi tiết hơn, nó sẽ tải tập_tin_stage1, xác nhận rẳng nó là Giai đoạn 1 đúng số phiên bản của GRUB, cài đặt một danh sách khối để nạp tập_tin_stage2 làm Giai đoạn 2 (nghĩa là tập_tin_stage2 sẽ trao cho Giai đoạn 1 vị trí của Giai đoạn 2). Nếu có tuỳ chọn d, Giai đoạn 1 luôn luôn tìm đĩa thực tế đã cài tập_tin_stage2 hơn là dùng ổ đĩa khởi động. Giai đoạn 2 sẽ được nạp tại địa chỉ địa_chỉ, phải là 0x8000 đối với Giai đoạn 2 thực, và 0x2000 đối với Giai đoạn 1.5. Nếu địa_chỉ không được chỉ định, GRUB sẽ xác định địa chỉ tự động. Sau đó nó viết Giai đoạn 1 đã hoàn chỉnh vào khối đầu tiên của thiết bị thiết_bị_đích. Nếu tuỳ chọn p hoặc tập_tin_cấu_hình được chỉ định, nó sẽ đọc khối đầu tiên của stage2, thay đổi nó bằng giá trị của phân vùng mà ở đó tập_tin_stage2 được tìm thấy (đối với p) hoặc đặt chuỗi tập_tin_cấu_hình vào vùng cho stage2 biết nơi tìm tập tin cấu hình lúc khởi động. Cũng như vậy, nếu tập_tin_cấu_hình_thực được chỉ định và tập_tin_stage2 là Giai đoạn 1.5, thì tập_tin_cấu_hình được vá bằng tên tập tin cấu hình tập_tin_cấu_hình_thực. Để dễ hiểu hơn cho trường hợp nhúng Giai đoạn 1.5: tập_tin_stage2 là vị trí nhúng stage1_5, tập_tin_cấu_hình là vị trí của stage2 (theo lô-gic, stage2 là tập tin cấu hình cho stage1_5), tập_tin_cấu_hình_thực là vị trí của menu.lst. Lệnh install không phát sinh sector bitmap cho stage2, tức là tham số tập_tin_cấu_hình, mà nó cần viết chuỗi tập_tin_cấu_hình và tập_tin_cấu_hình_thực (không ở dạng block bitmap mà ở dạng tên tập tin thuần tuý) tương ứng vào stage1_5 và stage2. stage2 nằm trên hệ thống tập tin, vì vậy tuỳ chọn --stage2 giúp cho việc viết được an toàn hơn.

Lệnh này giữ lại DOS BPB (và đối với đĩa cứng là bảng phân vùng) của sector sẽ được cài Giai đoạn 1.

Lưu ý:

* Một số BIOS bị lỗi cần phải chỉ định tuỳ chọn d cho dù Giai đoạn 2 nằm ở ổ đĩa khởi động hay không Khiếm khuyết này gặp ở: Fujitsu LifeBook 400 BIOS version 31J0103A, HP Vectra XU 6/200 BIOS version GG.06.11.
*

Một số BIOS không trả về bitmap hỗ trợ LBA đúng ngay cả chúng thực sự có hỗ trợ; vì vậy GRUB cung cấp giải pháp để bỏ qua bitmap sai, đó là tuỳ chọn --force-lba. Đừng dùng tuỳ chọn này nếu BIOS không hỗ trợ LBA (chế độ LBA dùng firmware để vượt qua giới hạn 1024 cylinder của BIOS).

Phải chỉ định tuỳ chọn --stage2 trong shell grub nếu không thể tháo gán hệ thống tập tin nơi chứa tập tin stage2. Đối số là tên tập tin trong hệ điều hành.

Thí dụ về sử dụng lệnh install:

root (hd0,1)
embed /boot/grub/reiserfs_stage1_5 (hd0) # or e2fs_stage1_5

(và lưu ý số sector)

install /boot/grub/stage1 (hd0) (hd0)1+<số sector có từ lệnh embed> p /boot/grub/stage2 /boot/grub/menu.lst


(hoặc dùng setup (hd0) )
3.7. Cài GRUB trong môi trường hệ điều hành giống Unix
3.7.1. Cài GRUB dùng lệnh grub-install
Cách này hoàn toàn không được khuyến khích, vì có thể máy tính sẽ không thể khởi động được với GRUB. Thí dụ, hầu hết các hệ điều hành không cho GRUB biết cách ánh xạ chính xác ổ đĩa BIOS sang thiết bị của hệ điều hành, GRUB chỉ đoán cách ánh xạ. Trong hầu hết các trường hợp thì quá trình này thành công, nhưng không luôn luôn như vậy. Do đó GRUB cung cấp tập tin ánh xạ do người dùng định nghĩa device.map; nếu tập tin này cho thấy ánh xạ sai bạn cần phải sửa nó lại. Nếu không may phải cài đặt GRUB trong môi trường hệ điều hành giống UNIX, gọi lệnh grub-install với tư cách siêu người dùng (root). Cách sử dụng rất dễ dàng, bạn chỉ cần chỉ định một đối số về nơi cài đặt GRUB. Đối số có thể là tập tin thiết bị hay ổ đĩa/phân vùng theo GRUB. Cú pháp:

grub-install thiết_bị_cài_đặt

Thí dụ: cài GRUB vào MBR của ổ đĩa IDE thứ nhất trong Linux:

# grub-install /dev/hda

Nếu đây cũng là ổ đĩa BIOS thứ nhất:

# grub-install 'hd(0)'

Các thí dụ trên giả định rằng dùng các hình ảnh GRUB ở thư mục root. Nếu muốn GRUB dùng hình ảnh ở thư mục không phải là thư mục root, cần chỉ định tuỳ chọn --root-directory. Cách dùng điển hình là tạo đĩa mềm khởi động GRUB với một hệ thống tập tin. Thí dụ:

# mke2fs /dev/fd0
# mount -t ext2 /dev/fd0 /mnt
# grub-install --root-directory=/mnt '(fd0)'
# umount /mnt


Một thí dụ khác là khi có một phân vùng khởi động được gán tại /boot. Vì GRUB là một trình nạp khởi động, nó không biết gì về các điểm gán, nên cần chạy lệnh grub-install như sau:

# grub-install --root-directory=/boot /dev/hda


Như trên đã nói, việc đoán ổ đĩa BIOS trong hệ điều hành giống UNIX là khá khó khăn. Vì vậy, sau khi cài đặt, grub-install sẽ nhắc người dùng kiểm ra xem nó có đoán đúng các ánh xạ không. Cần cẩn thận, vì nếu kết quả xuất ra sai máy tính rất có thể bạn sẽ gặp rắc rối khi khởi động lại máy tính.

Các tuỳ chọn của lệnh grub-install
Code:
--help
In tóm tắt về các tuỳ chọn dòng lệnh và thoát.
--version
In số phiên bản của GRUB và thoát.
--force-lba
Bắt buộc GRUB dùng chế độ LBA. Chỉ dùng tuỳ chọn này nếu BIOS không hoạt động ở chế độ LBA mặc dù nó hỗ trợ chế độ LBA.
--root-directory=thư_mục
Cài các hình ảnh GRUB vào thư mục thư_mục thay vì vào thư mục root. Tuỳ chọn này có ích khi bạn muốn cài GRUB vào một phân vùng riêng biệt hoặc vào một ổ đĩa di động Thí dụ cho trường hợp bạn có một thư mục boot riêng được gán tại /boot:
grub-install --root-directory=/boot 'hd0'
--grub-shell=tập_tin
Dùng tập_tin làm shell grub. Bạn có thể thêm các tuỳ chọn tuỳ ý vào tập_tin sau tên tập tin, thí dụ:
grub-install --grub-shell="grub –read-only" /dev/fd0
--recheck
Kiểm tra lại ánh xạ thiết bị, ngay cả khi /boot/grub/device.map đã tồn tại. Nên dùng tuỳ chọn này mỗi khi thêm/tháo một đĩa vào/ra khỏi máy tính.

Lưu ý rằng grub-install thực chất là một Bourne shell script và chức năng thực sự do shell grub thực hiện. Vì vậy có thể chạy grub trực tiếp để cài GRUB, mà không cần grub-install. Nhưng không nên làm như vậy trừ khi bạn rất quen thuộc với các yếu tố nội tại của GRUB. Việc cài một trình nạp khởi động trong một hệ điều hành đang chạy là cực kỳ nguy hiểm.

3.7.2. Cài GRUB trong shell grub
Cách này dùng lệnh grub trong môi trường hệ điều hành.

Cần lưu ý là shell grub là trình mô phỏng – nó thay thế các lời gọi BIOS bằng các lời gọi hệ thống UNIX và các hàm libc, nó không chạy dưới môi trường nguyên thuỷ, vì vậy đôi khi nó hoạt động không chính xác, nhất là trong việc ánh xạ giữa các ổ đĩa BIOS và các thiết bị hệ điều hành.

Quá trình cài đặt dùng shell grub tương tự như ở Giai đoạn 2 nguyên thuỷ. Bạn cần cẩn thận về buffer cache. grub dùng thiết bị thô thay vì hệ thống tập tin mà hệ điều hành đang sử dụng, vì vậy có khả năng cache inconsistency nào đó gây hư hỏng hệ thống tập tin. Lời khuyên là:

* tháo gán trước khi chạy grub, nếu có thể, các ổ đĩa mà GRUB có thể sẽ viết dữ liệu lên.
* gán ở chế độ chỉ-đọc nếu không thể tháo gán ổ đĩa nhưng có thể gán với cờ chỉ-đọc.
* chắc chắn rằng không có bất kì hoạt động đĩa nào trong khi chạy lệnh grub nếu ổ đĩa bắt buộc phải gán với cờ đọc-viết.
* khởi động lại hệ điều hành càng sớm càng tốt. Điều này có thể không cần thiết nếu các bước trên đã được tuân thủ, nhưng khởi động lại là cách an toàn nhất.

Sau khi hoàn tất cài đặt, việc nhập lệnh quit là rất quan trọng vì quit làm cho buffer cache trở nên consistent; đừng ấn <C-c>.

Nếu muốn cài GRUB không tương tác, chỉ định tuỳ chọn --batch ở dòng lệnh. Một thí dụ đơn giản:

Code:
#!/bin/sh
# Du`ng /usr/sbin/grub ne^'u o+? he^. tho^'ng cu~.
/sbin/grub --batch <<EOT 1>/dev/null 2>/dev/null
root (hd0,0)
setup (hd0)
quit
EOT


Các tuỳ chọn của lệnh grub:

Code:
--help
In tóm tắt về các tuỳ chọn dòng lệnh và thoát.
--version
In số phiên bản của GRUB và thoát.
--verbose
In các thông điệp verbose nhằm mục đích gỡ lỗi.
--device-map=tập_tin
Dùng tập tin ánh xạ thiết bị tập_tin.
--no-floppy
Không thăm dò ổ đĩa mềm. Tuỳ chọn này không có tác dụng nếu tuỳ chọn --device-map được chỉ định.
--probe-second-floppy
Thăm dò ổ đĩa mềm thứ hai. Shell grub không thăm dò nó nếu tuỳ chọn này không được chỉ định vì đôi khi nó cần thời gian lâu. Shell grub bỏ qua tuỳ chọn này nếu đã chỉ đinh tập tin ánh xạ thiết bị.
--config-file=tập_tin
Đọc tập tin cấu hình tập_tin thay vì /boot/grub/menu.lst.
--boot-drive=ổ_đĩa
Thiết lập ổ đĩa khởi động stage2 là ổ_đĩa. Đối số này là một số nguyên (thập thân, bát phân hay thập lục phân).
--install-partition=phân_vùng
Thiết lập phân vùng khởi động stage2 là phân_vùng. Đối số này là một số nguyên (thập thân, bát phân hay thập lục phân).
--no-config-file
Không dùng tập tin cấu hình.
--no-curses
Không dùng giao diện curses.
--batch
Tuỳ chọn này có cùng ý nghĩa như --no-config-file --no-curses.
--read-only
Không viết vào bất cứ đĩa nào.


Có thể cài GRUB theo một tập tin có sẵn chứa các thông số cần thiết cho lệnh grub. Thí dụ có tập tin /etc/grub.conf như sau:

root (hd0,4)
install /grub/stage1 d (hd0) /grub/stage2 0x8000 (hd0,4)/grub/menu.lst
quit


Và bạn vừa hiệu chỉnh tập tin device.map, bây giờ bạn phải cài lại GRUB:

grub --batch --device-map=/boot/grub/device.map </etc/grub.conf

Thí dụ bạn có tập tin /etc/grubfd.conf dùng để cài GRUB vào đĩa mềm:
Code:
#
# /etc/grubfd.conf – ta.o ddi~a me^`m kho+?i ddo^.ng
#
# DDe^? ca`i grub va`o ddi~a me^`m, nha^.p le^.nh sau:
# grep -v ^# /etc/grubfd.conf | grub --batch
#
root (fd0)
install /boot/grub/stage1 d (fd0) (fd0)/boot/grub/stage2 0x8000 p (fd0)/boot/grub/menu.lst
quit
Bạn dùng lệnh sau để cài GRUB vào đĩa mềm (đã được chú thích trong tập tin đó):
grep -v ^# /etc/grubfd.conf | grub --batch


3.7.3. Ánh xạ giữa các ổ đĩa BIOS và các thiết bị hệ điều hành
Khi chỉ định tuỳ chọn --device-map, shell grub tạo tập tin ánh xạ thiết bị, thường là /boot/grub/device.map, nếu chưa có tập tin này. Nếu tập tin này đã tồn tại, shell grub đọc nó để ánh xạ các ổ đĩa BIOS theo các thiết bị hệ điều hành. Tập tin này gồm các dòng:

thiết_bị tập_tin

thiết_bị là một ổ đĩa, cú pháp dùng theo cú pháp của GRUB; tập_tin là một tập tin thiết bị của hệ điều hành.

Lý do shell grub cung cấp tập tin ánh xạ thiết bị là vì nó không thể đoán ánh xạ giữa ổ đĩa BIOS và thiết bị hệ điều hành một cách chính xác trong một số môi trường; thí dụ như khi thay đổi trình tự khởi động giữa IDE và SCSI trong BIOS, shell grub sẽ nhầm lẫn thứ tự của chúng.

Vì vậy hãy điều chỉnh lại tập tin này nếu shell grub nhầm lẫn. Bạn có thể thêm chú thích trong tập tin này, nếu cần, vì shell grub xem các dòng bắt đầu bằng kí tự # là dòng chú thích.

Sau khi thay đổi nội dung tập tin device.map cần cài lại GRUB.

3.8. Khởi động hệ thống với GRUB
GRUB có 2 cách khác nhau để khởi động hệ thống. Một cách là nạp hệ điều hành trực tiếp, cách kia là nạp chuỗi một trình nạp khởi động khác, vả trình nạp khởi động nàysẽ nạp hệ điều hành. Nói chung thì cách thứ nhất được ưa chuộng hơn vì không phải cài hay duy trì trình khởi động khác. Tuy nhiên đôi khi vẫn cần dùng cách thứ hai vì GRUB không hỗ trợ mọi hệ điều hành về bản chất, đặc biệt là các hệ điều hành thuộc sở hữu độc quyển.
3.8.1. Khởi động hệ điều hành trực tiếp
Nói chung GRUB có thể khởi động Linux, FreeBSD, NetBSD, OpenBSD, GNU HURD theo các bước sau:

* Quy định thiết bị root của GRUB là ổ đĩa nơi giữ các hình ảnh hệ điều hành bằng lệnh root.
* Tải hệ điều hành bằng lệnh kernel, có thể gắn thêm các thông số cho nhân.
* Nếu cần, tải initrd bằng lệnh initrd hoặc các mô-đun bằng lệnh module hoặc modulenounzip.
* Chạy lệnh boot.

3.8.2. Tải trình nạp khởi động khác
Để khởi động các hệ điều hành không được hỗ trợ, GRUB nạp chuỗi một trình nạp khỏi động cho hệ điều hành đó. Thông thường, trình khởi động được đặt ở sector khởi động của phân vùng cài đặt hệ điều hành.

* Thiết lập thiết bị root của GRUB đến phân vùng hệ điều hành bằng lệnh rootnoverify

grub> rootnoverify hd(0,0)

* Thiết lập cờ active trong phần vùng bằng lệnh makeactive

grub> makeactive

* Tải trình nạp khởi động bằng lệnh chainloader

grub> chainloader +1

+1 biểu thị GRUB đọc một sector kể từ nơi bắt đầu của phân vùng.
* Chạy lệnh boot

Tuy nhiên DOS và Windows có một số yếu tố phụ thuộc cần chú ý khi muốn khởi động chúng.
3.8.3. Một số thí dụ
3.8.3.1. Linux

* Thiết lập thiết bị root vào ổ đĩa cài GNU/Linux. Có thể dùng lệnh find /vmlinuz (hoặc tương tự).
* Tải nhân:

grub> kernel /vmlinuz root=/dev/hda1

Nếu cần chỉ định các tham số cho nhân, gắn chúng vào lệnh trên. Thí dụ để thiết lập vga là ext:

grub> kernel /vmlinux root=/dev/hda1 vga=ext

Cần lưu ý là phân vùng root ở đây phải theo cách gọi của Linux vì nó được chuyển vào nhân Linux.
* Nếu có dùng initrd, thực hiện lệnh initrd sau lệnh kernel

grub> initrd /initrd

* Cuối cùng chạy lệnh boot.

Lưu ý: nếu dùng initrd và chỉ định tuỳ chọn mem= cho nhân để bắt nó dùng ít bộ nhớ hơn hiện có, thì cũng cần phải chỉ định cùng một kích thước bộ nhớ cho GRUB. Để GRUB biết được kích thước này, chạy lệnh uppermem trước khi tải nhân.

3.8.3.2. FreeBSD
GRUB có thể tải nhân trực tiếp, hoặc ở dạng ELF hoặc định dạng a.out, nhưng cách này không được khuyến khích vì giao diện trình khởi động của FreeBSD đôi khi thay đổi rất nhiều, vì vậy GRUB không thể bảo đảm chuyển chính xác các tham số nhân. Thay vì vậy, nên tải một trình khởi động rất linh hoạt là /boot/loader. Xem thí dụ:

grub> root (hd0,a)
grub> kernel /boot/loader
grub> boot


Phiên bản FreeBSD 5.x dùng mặc định hệ thống tập tin UFS2 mà hiện tại GRUB chưa hỗ trợ, vì vậy phải dùng cách nạp chuỗi:

grub> rootnoverify (hd0,1)
grub> chainloader +1
grub> boot


3.8.3.3. NetBSD
GRUB có thể tải trực tiếp a.out và ELF của NetBSD, theo các bước sau:

* Thiết lập thiết bị root của GRUB với lệnh root.
* Nạp nhân với lệnh kernel. Nên gắn tuỳ chọn --type=netbsd nếu muốn tải nhân ELF:

grub> kernel --type=netbsd /netbsd-elf

* Chạy boot.

Tuy nhiên hiện tại GRUB không cho phép chuyển tham số nhân, vì vậy dùng cách nạp chuỗi có thể tốt hơn.

3.8.3.4. OpenBSD
Cách thực hiện hoàn toàn giống như NetBSD. Tuy nhiên ở những phiên bản sau này (sau 2.7), có thể cách trên không thành công. Khi đó có thể dùng cách nạp chuỗi.

3.8.3.5. DOS/Windows
GRUB không thể khởi động DOS hay Windows trực tiếp, vì vậy cần phải nạp chuỗi. Tuy nhiên các trình khởi động của chúng có một số vấn đề phụ thuộc quan trọng, nên nó có thể không hoạt động nếu chỉ đơn thuần nạp chuỗi chúng. GRUB có 2 chức năng giúp khắc phục các khó khăn này. Nếu DOS hay Windows được cài trên ổ đĩa cứng không phải là ổ thứ nhất, cần phải dùng kĩ thuật tráo đổi đĩa, vì các hệ điều hành này không thể khởi động từ ổ cứng không phải là ổ thứ nhất. Một giải pháp trong GRUB là dùng lệnh map, thí dụ để chuyển đổi đĩa cúng thứ nhất và thứ hai:

grub> map (hd0) (hd1)
grub> map (hd1) (hd0)


Cần lưu ý là cách này chỉ hiệu quả khi DOS hay Windows dùng BIOS để truy cập ổ đĩa được chuyển đổi. Nếu hệ điều hành đó dùng trình điều khiển đặc biệt cho ổ đĩa đó, cách này có thể không hoạt động. Một vấn đề khác là khi cài nhiều hơn một bản của hệ điều hành DOS/Windows trên một đĩa cứng các hệ điều hành này có thể lẫn lộn nếu có nhiều hơn một phân vùng sơ cấp cho DOS/Windows. Dĩ nhiên nên tránh những trường hợp như thế này, nhưng GRUB đưa ra một giải pháp khi muốn làm như vậybằng kĩ thuật che/khử che phân vùng. Nếu GRUB che một phân vùng DOS hay Windows, DOS hay Windows sẽ bỏ qua phân vùng đó. Nếu GRUB khử che một phân vùng DOS hay Windows, DOS hay Windows sẽ nhận diện được phân vùng đó. Vì vậy nếu DOS hay Windows được cài ở phân vùng thứ nhất và thứ hai của đĩa cứng thứ nhất, để khởi động bản hệ điều hành trên phân vùng thứ nhất:

grub> unhide (hd0,0)
grub> hide (hd0,1)
grub> rootnoverify (hd0,0)
grub> chainloader +1
grub> makeactive
grub> boot


3.9. Cấu hình
Ở giao diện dòng lệnh cần phải gõ vài lệnh để khởi động hệ điều hành. GRUB cũng cung cấp giao diện thực đơn mà chỉ cần chọn một đề mục là mọi thứ được thực hiện để khởi động hệ điều hành.

Để có thể sử dụng giao diện thực đơn cần phải có tập tin cấu hình menu.lst ở thư mục khởi động. Khi hệ thống được khởi động, GRUB đọc nội dung của tập tin cấu hình. Không cần phải cài GRUB lại mỗi khi thay đổi nội dung tập tin này. Tập tin này mặc định nằm ở thư mục /boot/grub, nhưng có thể đặt ở bất cứ nơi đâu cũng như có thể đặt bất cứ tên gì cho nó.
Phân tích thí dụ về một tập tin cấu hình:
Tập tin này bắt đầu bằng các thiết lập chung, các tuỳ chọn liên hệ đến giao diện thực đơn. Các lệnh này có thể được đặt trước bất cứ đề mục nào (bắt đầu với lệnh title).

Code:
#
# Ta^.p tin ca^'u hi`nh thu+.c ddo+n ma^~u
#
Đây là các dòng bình luận. GRUB bỏ qua các dùng bắt đầu với kí tự # và các dòng trống.
# Theo ma(.c ddi.nh, kho+?i ddo^.ng dde^` mu.c thu+' nha^'t
default 0
Đề mục thứ nhất (lưu ý là đếm bắt đầu từ 0 chứ không phải 1) sẽ là lựa chọn mặc định.
# Tu+. ddo^.ng kho+?i ddo^.ng sau 30 gia^y
timeout 30
GRUB sẽ khởi động tự động sau 30 giây, trừ khi bị ngắt bởi một nhấn phím.
# Quay la.i dde^` mu.c thu+' hai
fallback 1
Nếu vì bất cứ lí do nào mà đề mục mặc định không hoạt động, quay lại đề mục thứ hai. Ở phần định nghĩa cho hệ điều hành, mỗi đề mục bắt đầu bằng một lệnh đặc biệt title. Không có lệnh boot ở cuối đề mục vì nó sẽ tự động thực hiện nếu GRUB nạp thành công các lệnh khác.
Đối số cho lệnh title được dùng để trình bày một tựa/miêu tả ngắn cho đề mục.
# DDe^? kho+?i ddo^.ng GNU/Linux
title GNU/Linux
kernel (hd1,0)/vmlinuz root=/dev/hdb1
Khởi động GNU/Linux từ đĩa cứng thứ hai.
# DDe^? kho+?i ddo^.ng FreeBSD
title FreeBSD
root (hd0,2,a)
kernel /boot/loader
Khởi động nhân FreeBSD tải từ phân vùng a trên PC slice thứ ba của đĩa cứng thứ nhất.
# DDe^? kho+?i ddo^.ng OS/2
title OS/2
root (hd0,1)
makeactive
# na.p chuo^~i tri`nh kho+?i ddo^.ng OS/2 tu+` sector thu+' nha^'t
chainloader +1
# Na.p chuo^~i mo^.t ta^.p tin cu. the^?
#chainloader /boot/chain.os2
Khởi động OS/2 dùng cách nạp chuỗi.
# DDe^? kho+?i ddo^.ng Windows NT hoa(.c Windows95
title Thu+.c ddo+n kho+?i ddo^.ng Windows NT / Windows 95
root (hd0,0)
makeactive
chainloader +1
# DDe^? na.p DOS ne^'u co' ca`i Windows NT
# chainload /bootsect.dos
Khởi động Windows bằng cách nạp chuỗi.
# DDe^? kho+?i ddo^.ng mo^.t he^. ddie^`u ha`nh tre^n ddi~a me^`m
title floppy
pause Ga`i ddi~a me^`m va`o o^? ddi~a
root (fd0)
chainloader +1
Khởi động một hệ điều hành từ đĩa mềm.
# DDe^? ca`i GRUB va`o ddi~a cu+'ng
title Ca`i GRUB va`o ddi~a cu+'ng
root (hd0,0)
setup (hd0)
Cài (cài lại) GRUB vào đĩa cứng.
# Thay ddo^?i ma`u sa('c.
title Thay ddo^?i ma`u sa('c
color light-green/brown blink-red/blue
Thay đổi màu sắc của thực đơn.
# Ta?i mo^.t thu+.c ddo+n kha'c
title Thu+.c ddo+n bo^? sung
configfile (hd0,4)/boot/grub/control.lst

Tải thực đơn bổ sung.
Đặc điểm của tập tin cấu hình:

* các lệnh đặc thù cho thực đơn phải được dùng trước các lệnh khác
* tập tin phải ở định dạng văn bản thuần tuý
* # ở đầu dòng cho biết đây chỉ là lời bình
* các tuỳ chọn cách nhau bằng khoảng trắng
* số có thể ở dạng thập phân hoặc thập lục phân. Số thập lục phân phải khởi đầu bằng 0x, và phân biệt chữ hoa-thường

Nếu quá trình cài GRUB đã không quy định tập tin cấu hình, vẫn có thể tải tập tin cấu hình trong môi trường GRUB bằng lệnh configfile, thí dụ:

grub> configfile (fd0)/boot/grub/menu.lst

3.10. Bảo mật cho GRUB
Dùng tính năng mật khẩu của GRUB để chỉ cho phép người quản trị dùng các hoạt động tương tác (như biên tập đề mục thực đơn và vào giao diện dòng lệnh). Để sử dụng tính năng này, cần chạy lệnh password trong tập tin cấu hình, như sau:

password --md5 PASSWORD

Khi đó GRUB không cho phép điều khiển tương tác nào (<e> và <c>smilie, cho đến khi gõ phím <p> và nhập đúng mật khẩu. Tuỳ chọn --md5 cho GRUB biết rằng PASSWORD ở định dạng MD5. Nếu không sử dụng tuỳ chọn này, GRUB cho rằng PASSWORD ở dạng văn bản thuần tuý. Mật khẩu có thể được mã hoá bằng lệnh md5crypt. Thí dụ chạy shell grub và nhập mật khẩu:

grub> md5crypt
Password: **********
Encrypted: $1$U$JK7xFegdxWH6VuppCUSIb.


Sau đó cắt và dán mật khẩu đã được mã hoá vào tập tin cấu hình. Ngoài ra cũng có thể chỉ định đối số tuỳ chọn cho lệnh password, thí dụ:

password PASSWORD /boot/grub/menu-admin.lst

Khi đó GRUB sẽ nạp /boot/grub/menu-admin.lst làm tập tin cấu hình khi nhập đúng mật khẩu. Nếu muốn chỉ có người quản trị mới có quyền chạy một số đề mục thực đơn nào đó, chẳng hạn như khởi động một hệ điều hành không bảo mật như DOS, có thể dùng lệnh lock; lệnh này luôn luôn dừng lại cho đến khi nhập đúng mật khẩu. Thí dụ:

Code:
title Kho+?i ddo^.ng DOS
lock
rootnoverify (hd0,1)
makeactive
chainload +1[b]


Cũng có thể dùng lệnh password thay cho lock. Trong trường hợp này tiến trình khởi động sẽ yêu cầu mật khẩu và dừng lại cho đến khi mật khẩu được nhập chính xác. Vì lệnh password nhận đối số PASSWORD của chính nó nên sẽ có lợi nếu dùng một mật khẩu khác với mật khẩu cho các đề mục khác.

Nên sử dụng lệnh lock/password ngay sau title vì các lệnh trong đề mục thực đơn được thực thi theo thứ tự.

grub-md5-crypt là script gọi shell grub để mã hoá một chuỗi kí tự ở dạng MD5. Mật khẩu do chương trình này mã hoá có thể được dùng với lệnh password.

grub-md5-crypt nhận các tuỳ chọn sau:

Code:
--help
In tóm tắt các tuỳ chọn dòng lệnh và thoát
--version
In thông tin phiên bản và thoát
--grub-shell=tập_tin
Dùng tập_tin làm shell grub


3.11. Giao diện người dùng của GRUB
GRUB có cả giao diện thực đơn đơn giản để chọn các đề mục được thiết lập sẵn từ tập tin cấu hình lẫn giao diện dòng lệnh linh hoạt cao để thực hiện bất cứ các tổ hợp lệnh khởi động nào theo ý muốn.
3.11.1. Giao diện dòng lệnh
Giao diện dòng lệnh cung cấp một dấu nhắc và sau nó là vùng văn bản có thể biên tập được giống một dòng lệnh trong Unix hoặc DOS. Mỗi dòng lệnh được thi hành ngay lập tức sau khi nó được nhập vào. Các lệnh này là một phần của các dòng lệnh có thể dùng trong tập tin cấu hình, với cùng một cú pháp. Dùng giao diện dòng lệnh có thể khởi động các hệ điều hành không có trong thực đơn GRUB.

Di chuyển con trỏ và biên tập văn bản trên một dòng có thể được thực hiện nhờ một phần các chức năng có sẵn trong shell Bash:

Code:
<C-f>
<PC mũi tên phải>
Di chuyển về trước một kí tự.
<C-b>
<PC mũi tên trái>
Di chuyển về sau một kí tự.
<C-a>
<HOME>
Di chuyển về đầu dòng.
<C-e>
<END>
Di chuyển về cuối dòng.
<C-d>
<DEL>
Xoá kí tự bên dưới con trỏ.
<C-h>
<BS>
Xoá kí tự bên trái con trỏ..
<C-k>
Xoá đoạn văn bản từ vị trí con trỏ hiện tại đến cuối dòng.
<C-u>
Xoá ngược đoạn văn bản từ vị trí con trỏ hiện tại đến đầu dòng.
<C-y>
Lấy lại đoạn văn bản đã xoá vào bộ đệm tại con trỏ.
<C-p>
<PC mũi tên lên>
Di chuyển lên trên trong danh sách các lệnh vừa gõ.
<C-n>
<PC mũi tên xuống>
Di chuyển xuống dưới trong danh sách các lệnh vừa gõ.


Khi gõ các lệnh một cách tương tác, nếu con trỏ ở trong hoặc trước từ đầu tiên trong dòng lệnh, ấn phím <TAB> (hoặc <C-i>smilie sẽ liệt kê các lệnh có sẵn, và nếu con trỏ ở sau từ đầu tiên, <TAB> sẽ liệt kê các ổ đĩa, phân vùng, và tên tập tin tuỳ vào tình huống.

Lưu ý rằng không thể dùng chức năng hoàn thành dòng lệnh trong hệ thống tập tin TFTP vì bởi vì TFTP không hỗ trợ liệt kê tên tập tin vì lí do bảo mật.

Dùng lệnh help để đọc thông tin về một lệnh, ví dụ để xem thông tin của lệnh root:

help root

3.11.2. Giao diện thực đơn
Giao diện thực đơn khá dễ dùng. Các lệnh của nó tương đối trực quan và được miêu tả trên màn hình.

Về cơ bản, giao diện thực đơn cung cấp danh sách các đề mục khởi động cho người dùng lựa chọn. Dùng các phím mũi tên để chọn đề mục, rồi ấn phím <RET> để chạy nó. Có thể quy định thời gian chờ để khởi động đề mục mặc định (hoặc đề mục đầu tiên nếu không thiết lập), thời gian này sẽ bị ngắt bằng cách nhấn phím bất kì.

Từ giao diện thực đơn có thể vào giao diện dòng lệnh bằng cách ấn <c> (khi đó sẽ giống như trường hợp không có tập tin cấu hình nhưng vẫn có thể quaylại giao diện thực đơn bằng phím <ESC>smilie hoặc có thể biên tập bất cứ đề mục khởi động nào bằng cách ấn phím <e>.

Nếu giao diện thực đơn được bảo vệ bằng mật khẩu, ấn <RET> rồi <p> và nhập mật khẩu để chọn đề mục.
Biên tập một đề mục trong thực đơn
Để biên tập một đề mục trên thực đơn, đầu tiên ấn <ESC>, sau đó chọn đề mục cần thay đổi bằng các phím con trỏ và ấn <e>, khi đó các dòng lệnh cho đề mục đó sẽ xuất hiện. Chọn dòng cần điều chỉnh bằng các phím con trỏ và ấn <e> lần nữa.

Trong khi biên tập một đề mục, ấn <RET> để thay thế dòng lệnh cũ bằng dòng lệnh vừa điều chỉnh, nếu ấn <ESC> mọi thay đổi sẽ được bỏ qua. Nếu muốn thêm một dòng mới vào đề mục khởi động, ấn <o> nếu thêm vào sau dòng hiện tại hoặc <O> nếu thêm vào trước dòng hiện tại. Để xoá một dòng, ấn <d>. GRUB không hỗ trợ huỷ bỏ thao tác vừa làm, nhưng có thề làm điều tương tự như vậy bằng cách quay trở lại thực đơn chính. Sau khi điều chỉnh xong, ấn <b> để khởi động với đề mục đó.
Giao diện thực đơn ẩn
Nếu thiết bị cuối câm hoặc GRUB được yêu cần che dấu giao diện thực đơn bằng lệnh hiddenmenu, GRUB sẽ không hiển thị giao diện thực đơn và tự động khởi động đề mục mặc định, trừ khi bị ngắt bằng cách ấn phím <ESC>. Khi ngắt thời gian chờ và thiết bị cuối câm, GRUB quay trở lại giao diện dòng lệnh.
3.12. Một số lệnh trong GRUB
3.12.1. Các lệnh chỉ dùng cho thực đơn

Code:
default số
Thiết lập mặc định cho đề mục số số. Việc đánh số bắt đầu từ 0, và đề mục số 0 là mặc định nếu lệnh này không được dùng.
Có thể chỉ định saved thay vì một con số. Khi đó, đề mục mặc định là đề mục được lưu bằng lệnh savedefault.
fallback số
Nếu đề mục mặc định có lỗi, ngay lập tức chuyển qua đề mục số thay vì chờ người dùng thao tác. Cách đánh số giống như ở lệnh default. Có thể thiết lập nhiều hơn một fallback.
hiddenmenu
Không hiển thị thực đơn trên thiết bị đầu cuối và đề mục mặc định sẽ được khởi động sau khi hết thời gian chờ. Người dùng vẫn có thể yêu cầu hiển thị thực đơn bằng cách ấn <ESC> trước khi thời gian chờ hết.
timeout gy
Thiết lập thời gian chờ, tính bằng gy giây, trước khi tự động khởi động vào đề mục mặc định.
title tên ...
Bắt đầu một đề mục khởi động mới; nội dung của phần còn lại của dòng này, bắt đầu bằng kí tự đầu tiên không phải là khoảng trắng, được lấy làm tên cho đề mục đó.


3.12.2. Các lệnh chung
Các lệnh này có thể được dùng trong thực đơn lẫn ở dòng lệnh.

color bình_thường [tô_sáng]
Thay đổi màu thực đơn. Màu bình_thường được dùng cho hầu hết các dòng trong thực đơn, và màu tô_sáng được dùng để tô sáng dòng mà con trỏ đang chỉ đến. Nếu không dùng tô_sáng, màu ngược lại của bỉnh_thường được dùng để tô sáng. Định dạng của một màu là tiền_cảnh/hậu_cảnh. tiền_cảnh và hậu_cảnh là các tên màu tượng trưng. Tên màu tượng trưng phải là một trong các tên sau:

* black
* blue
* green
* cyan
* red
* magenta
* brown
* light-gray


Những tên bên dưới chỉ dùng được cho tiền cảnh.

* dark-gray
* light-blue
* light-green
* light-cyan
* light-red
* light-magenta
* yellow
* white

Nhưng chỉ có 8 tên đầu có thể dùng cho hậu_cảnh.

Nếu muốn chớp nháy màu tiền cảnh, dùng tiền tố blink- cho tiền_cảnh.

Lệnh này dùng được trong tập tin cấu hình và ở dòng lệnh. Thí dụ trong tập tin cấu hình:

# Thie^'t la^.p ma`u ma(.c ddi.nh.
color light-gray/blue black/light-gray
# Thay ddo^?i ma`u.
title OS-BS like
color magenta/blue black/magenta

device ổ_đĩa tập_tin
Trong shell grub, chỉ định tập tin tập_tin như là ổ đĩa thực sự cho ổ đĩa BIOS ổ_đĩa. Có thể dùng lệnh này để tạo hình ảnh đĩa, và/hoặc sửa chữa các ổ đĩa được GRUB đoán khi GRUB không xác định được chúng một cách chính xác, như:

grub> device (fd0) /floppy-image
grub> device (hd0) /dev/sd0

Lệnh này chỉ dùng được ở shell grub.

hide phân_vùng
Che dấu phân vùng phân_vùng bằng cách thiết lập bit ẩn trong mã loại phân vùng của nó. Điều này có lợi khi khởi động DOS hay Windows và nhiều phân vùng FAT sơ cấp tồn tại trên một đĩa.

partnew phân_vùng loại từ đến
Tạo một phân vùng sơ cấp mới. phân_vùng là một đặc tả phân vùng theo cú pháp GRUB; loại là loại phân vùng và phải là một số trong khoảng 0–0xff; từ và đến là các sector khởi đầu và kết thúc, được diễn đạt bằng con số sector tuyệt đối.

parttype phân_vùng loại
Thay đổi loại của phân vùng đang tồn tại. phân_vùng là một đặc tả phân vùng theo cú pháp GRUB; loại là loại của phân vùng mới và phải là một số trong khoảng 0–0xff.

password [--md5] mật_khẩu [tập_tin_cấu_hình_mới]
Nếu được dùng trong phần đầu tiên của một tập tin thực đơn, nó sẽ vô hiệu hoá mọi hoạt động điều khiển biên tập tương tác (bộ phận biên tập đề mục thực đơn và dòng lệnh) và các đề mục được bảo vệ bằng lệnh lock. Nếu mật khẩu mật_khẩu được nhập, nó sẽ tải tập_tin_cấu_hình_mới làm tập tin cấu hình mới và khởi động lại GRUB Giai đoạn 2 nếu tập_tin_cấu_hình_mới được chỉ định. Nếu không, GRUB sẽ chỉ mở khoá các lệnh đặc quyền. Lệnh này cũng có thể được dùng trong phần script, khi đó nó sẽ hỏi mật khẩu trước khi tiếp tục. Tuỳ chọn --md5 bảo GRUB rằng mật_khẩu được mã hoá với md5crypt.

setkey [đến_phím từ_phím]
Thay đổi ánh xạ bàn phím. Phím từ_phím được ánh xạ sang đến_phím. Nếu không có đối số nó sẽ thiết lập lại ánh xạ bàn phím. Lưu ý rằng lệnh này không hoán đổi các phím. Nếu muốn hoán đổi các phím, chạy lệnh này một lần nữa với thông số hoán đổi, như:

grub> setkey capslock control
grub> setkey control capslock

Một phím phải là một chữ cái, một con số, hoặc một trong các kí hiệu sau: escape, exclam, at, numbersign, dollar, percent, caret, ampersand, asterisk, parenleft, parenright, minus, underscore, equal, plus, backspace, tab, bracketleft, braceleft, bracketright, braceright, enter, control, semicolon, colon, quote, doublequote, backquote, tilde, shift, backslash, bar, comma, less, period, greater, slash, question, alt, space, capslock, FX (X là một chữ số), và delete. Bảng sau đây miêu tả các kí tự tương ứng với các kí hiệu đó:

exclam
!
at
@
numbersign
#
dollar
$
percent
%
caret
^
ampersand
&
asterisk
*
parenleft
(
parenright
)
minus
-
underscore
_
equal
=
plus
+
bracketleft
[
braceleft
{
bracketright
]
braceright
}
semicolon
;
colon
:
quote
'
doublequote
"
backquote
`
tilde
~
backslash
\
bar
|
comma
,
less
<
period
.
greater
>
slash
/
question
?
space

unhide phân_vùng
Khử ẩn phân vùng phân_vùng bằng cách xoá bit ẩn trong mã loại phân vùng. Lệnh này có ích khi khởi động DOS hoặc Windows và có nhiều phân vùng sơ cấp trên một đĩa cứng.

3.12.3. Các lệnh dùng ở dòng lệnh và đề mục thực đơn
Các lệnh này dùng được ở dòng lệnh và ở đề mục thực đơn. Có thể chạy lệnh help để xem thông tin về các lệnh này.

[code]blocklist tập_tin
In kí hiệu danh sách khối của tập tin tập_tin.

boot
Khởi động hệ điều hành/trình nạp chuỗi đã được nạp. Chỉ cần thiết khi chạy trên dòng lệnh tương tác đầy đủ (nó được hiểu ngầm ở cuối đề mục thực đơn).

cat tập_tin
Hiển thị nội dung tập tin tập_tin. Lệnh này có thể giúp xác định đúng đâu là thư mục gốc của hệ điều hành:

grub> cat /etc/fstab

chainloader [--force] tập_tin
Nạp chuỗi tập_tin. Nếu chỉ định tuỳ chọn --force, nó sẽ cưỡng bức nạp tập_tin, cho dù nó có chữ kí đúng hay không. Điều này giúp nạp một trình nạp khởi động khiếm khuyết (như để khởi động SCO UnixWare 7.1).

cmp tập_tin1 tập_tin2
So sánh tập tin tập_tin1 với tập_tin2. Nếu chúng khác nhau về kích thước, in các kích thước như sau:

Differ in size: 0x1234 [foo], 0x4321 [bar]

Nếu kích thước bằng nhau nhưng các byte ở một offset khác nhau, in các byte như sau:

Differ at the offset 777: 0xbe [foo], 0xef [bar]

Nếu chúng hoàn toàn giống nhau, không in gì cả.

configfile tập_tin
Tải tập_tin làm tập tin cấu hình.

displayapm
Hiển thị thông tin BIOS về APM.

displaymem
Hiển thị thông tin về bộ nhớ đang được sử dụng, bao gồm tất cả các vùng của RAM vật lý được cài đặt, dựa trên thông tin từ BIOS. Giúp xác định hệ thống có bao nhiêu RAM dành cho khởi động.

embed stage1_5 thiết_bị
Ghi Giai đoạn 1.5 stage1_5 vào các sector sau MBR nếu thiết_bị là một ổ đĩa, hoặc vào vùng của trình khởi động nếu thiết_bị là một phân vùng FFS hoặc phân vùng ReiserFS. In con số các sector chiếm bởi stage1_5, nếu thành công. Thông thường không cần chạy lệnh này trực tiếp.

find tên_tập_tin
Tìm tên tập tin tên_tập_tin trong tất cả các phân vùng và in danh sách các thiết bi chứa tập tin. Tên tập tin tên_tập_tin nên là một tên tập tin tuyệt đối như /boot/grub/stage1.

geometry ổ_đĩa [cylinder head sector [tổng_sector]]
In thông tin về ổ đĩa ổ_đĩa. Trong shell grub, có thể thiết lập thông số ổ đĩa tuỳ ý. Số cylinder, số head, số sector và tổng số sector được thiết lập tương ứng cho cylinder, head, sector và tổng_sector. Nếu bỏ qua tổng_sector, nó sẽ được tính tự động dựa trên các giá trị C/H/S.

halt --no-apm
Tắt máy tính. Nếu tuỳ chọn --no-apm được chỉ định, không thực hiện lời gọi APM BIOS; nếu không, máy tính dùng APM khi tắt.

help --all [mẫu ...]
Hiển thị thông tin về các lệnh được cài sẵn. Nếu không chỉ định mẫu, lệnh này sẽ cho ra miêu tả ngắn của hầu hết các lệnh có sẵn. Nếu chỉ định tuỳ chọn --all, các miêu tả ngắn cho các lệnh hiếm dùng cũng được trình bày. Nếu chỉ định mẫu, nó sẽ trình bày thông tin dài hơn về mỗi lệnh khớp với các mẫu đó.

initrd tập_tin ...
Nạp đĩa RAM ban đầu cho hình ảnh khởi động theo định dạng Linux và thiết lập các thông số thích hợp cho vùng thiết lập Linux trong bộ nhớ.

install
Đã được đề cập ở trên.

ioprobe ổ_đĩa
Dò tìm cổng I/O dùng cho ổ đĩa ổ_đĩa. Lệnh này sẽ liệt kê các cổng I/O trên màn hình.

kernel [--type=loại] [--no-mem-option] tập_tin ...
Nạp hình ảnh khởi động (Multiboot a.out hoặc ELF, Linux zImage hoặc bzImage, FreeBSD a.out, NetBSD a.out, v.v...) từ tập_tin. Phần còn lại của dòng được chuyển nguyên văn như dòng lệnh nhân. Bất cứ mô-đun nào cũng có thể được nạp sau khi dùng lệnh này. Lệnh này cũng chấp nhận tuỳ chọn --type để chỉ định cụ thể loại nhân của tập_tin. Đối số loại phải là một trong các thứ sau: netbsd, freebsd, openbsd, linux, biglinux, và multiboot. Tuy nhiên, chỉ cần xác định loại nhân khi nạp nhân NetBSD E
The Unofficial Fedora FAQ (bản dịch tiếng Việt)

Nội dung

Về Fedora

1. Fedora Core 2 là gì?
2. Nghe nói Fedora chạy không ổn định?
3. Nó đã được phát hành chưa?
4. Có thể tải về Fedora từ đâu?
5. Có thể tìm thấy danh sách các phần mềm có trong Fedora Core 2 ở đâu?
6. Chương trình up2date vẫn hoạt động?
7. Có thể cài đặt FC2 trên ReiserFS, JFS hay XFS không?
8. Fedora có thể chạy trên AMD64 (Opteron) không?
9. Fedora có thể chạy trên máy Mac (PowerPC) không?
10. Có thể tìm thấy đĩa cài đặt cho Fedora Core 2 ở đâu ?

Cài đặt Fedora

1. Có thể tìm thấy các phần mềm cho Fedora ở đâu?
2. Làm sao cài đặt phần mềm cho Fedora? (cách dùng yum hay RPM)
3. Có chương trình nào tương tự như apt cho Fedora?
4. Có thể tìm thấy ở đâu các gói phần mềm Extras cho Fedora ?
5. Các máy chủ cập nhật của Red Hat chạy chậm quá! Làm sao bây giờ?
6. Làm sao cài đặt Java?
7. Làm sao cài đặt Flash vào trình duyệt web?
8. Làm sao xem PDF trong trình duyệt web?
9. Có thể dùng MSN(R) Messenger/AIM /ICQ/Yahoo trong Fedora?
10. Có thể dùng các font chữ TrueType trong Fedora?
11. Có thể tìm thấy drivers cho phần cứng của tôi trong Fedora?

Các vần đề thường gặp và cách khắc phục

1. Tôi gặp thông báo NOKEY từ RPM, hoặc tôi gặp lỗi chữ kí gpg khi dùng Apt / Yum / up2date!
2. Tôi gặp lỗi XKB sau khi đăng nhập!
3. Làm sao để thiết lập hỗ trợ 3D cho card ATI Radeon trong Fedora Core 2? (cập nhật 17/07/2004)
4. Làm sao để thiết lập hỗ trợ 3D cho card đồ họa nVidia trong Fedora Core 2? (cập nhật 3/07/2004)
5. Vài trang web tải chậm (như fedorafaq.org hay the New York Times)!
6. Card mạng 3com không hoạt động!
7. Card mạng không dây không hoạt động!
8. Máy tính của tôi khởi động lại khi cài đặt Fedora Core 2! (cập nhật 17/07/2004)
9. Tôi gặp lỗi về không gian đĩa khi cài đặt Fedora!
10. Sau khi cài đặt Fedora Core 2, bây giờ tôi không thể khởi động được Windows! (cập nhật 17/07/2004)
11. Tôi gặp vấn đề cài đặt khác chưa có trong các vấn đề nêu trên.
12. Sau khi cài đặt một chương trình, làm sao chạy nó?
13. Làm sao nghe nhạc MP3s với XMMS ?
14. Làm sao nghe nhạc MP3s với Rhythmbox?
15. Làm sao nghe nhạc MP3s với trình KDE MP3 như Noatun hay Juk?
16. Làm sao đọc được đĩa NTFS (Windows NT/2000/XP/2003) trong Fedora?
17. Tôi không thích kiểu quản lý file mới trong nautilus, làm sao để tắt nó?
18. Làm sao thay đổi các menu trong panel? (cập nhật 17/07/2004)
19. Làm sao chạy Wine?
20. Tôi không thể kết nối vào mạng chia sẻ Windows ! Có người bảo tôi dùng lệnh smbmount, nhưng nó cũng không chạy!
21. Chế độ rescue là gì và làm sao khởi động vào chế độ đó?
22. d00d, u sukc

FAQ
Về Fedora

1. Q: Fedora Core 2 là gì?
A: Fedora Core có thể xem như phiên bản kế tục của các bản Red Hat, nhưng đây là một dự án của cộng đồng. Theo trên trang chủ chính thức của Fedora, dự án Fedora là:

"... một dự án nguồn mở do Red Hat tài trợ và được đóng góp bởi cộng đồng. Nó tạo ra một sân chơi cho công nghệ mới mà có thể đưa vào các sản phẩm của Red Hat. Đây không phải là sản phẩm được hỗ trợ bởi Red Hat."

Hỗ trợ chính thức của dự án Fedora khoảng 6 đến 8 tháng cho mỗi phiên bản. Điều đó có nghĩa là bạn sẽ phải nâng cấp Hệ điều hành 6 hay 8 tháng một lần. Việc nâng cấp là tương đối dễ dàng, như Red Hat Linux 8 - Red Hat Linux 9. Nhưng việc nâng cấp là không bảo đảm lúc nào cũng dễ dàng.

Nếu bạn không muốn nâng cấp 6 hay 8 tháng một lần thì đã có dự án gọi là Fedora Legacy Project có mục đích kéo dài thời gian hỗ trợ để áp dụng bản vá sửa lỗi an toàn quan trọng cho các phiên bản không còn hỗ trợ nữa bởi Fedora.
2. Q:Nghe nói Fedora chạy không ổn định?
A: Không đúng!
3. Q: Phiên bản nào của Fedora đã đươc phát hành?
A: Fedora Core 2 (Tettnang) đã được phát hành vào ngày 18/05/2004.
4. Q: Có thể tải về Fedora từ đâu? (cập nhật 27/05/2004)
A: tải về bằng http/ftp hay bằng BitTorrent. Bạn chỉ cần các gói "binary" hay "i386", không cần "source" hay "SRPM".
Một máy chủ khác có lưu trữ các phần mềm liên quan đến tiếng Việt và tất nhiên có cả Fedora.
5. Q: Có thể tìm thấy danh sách các phần mềm có trong Fedora Core 2 ở đâu?
A: Có một danh sách của tất cả các gói của Fedora Core 2 tại trang Distrowatch Fedora.
6. Q: Chương trình up2date vẫn hoạt động với Fedora?
A: Vâng, nhưng nó không dùng Red Hat Network (RHN) nữa. (Nó vẫn tải các gói từ máy chủ Red Hat, nhưng bạn sẽ không thể dùng các tính năng của Red Hat Network.)

up2date đang dần được thay thế bằng yum hoặc apt.
7. Q: Có thể cài đặt FC trên ReiserFS, JFS hay XFS?
A: Vâng, hiện tại bạn có thể cài đặt Fedora trên ReiserFS, JFS hay XFS. Nên nhớ rằng không có một file hệ thống nào trong số đó được hỗ trợ chính thức bởi dự án Fedora cả. (Có nghĩa rằng bạn có thể dùng chúng, nhưng sẽ không có các trợ giúp chính thức từ dự án Fedora nếu có vấn đề.)

Tại dấu nhắc cài đặt, gõ lệnh sau đây cho ReiserFS:

linux reiserfs

hay là đối với JFS:

linux jfs

hay cho XFS:

linux xfs

CHÚ Ý: Bạn không thể dùng SELinux trên ReiserFS hay JFS. XFS thì được. (Nếu bạn không biết SELinux là gì, bạn có thể không cần quan tâm đến chú ý này.)

(Cảm ơn whiprush [quoting Jesse Keating] đã nêu lên vấn đề này. Cảm ơn Kai Thomsen đã phát hiện lỗi chính tả quan trọng. Cảm ơn Colin Charles về phần XFS và cảnh báo liên quan đến SELinux.)
8. Q: Có thể chạy Fedora trên máy AMD64 (Opteron) ?
A: Vâng, được! Phiên bản AMD64 của Fedora Core 2 hiện đang có. Xem câu hỏi về tải xuống Fedora.

Nếu bạn có câu hỏi liên quan đến AMD64 Fedora, xem AMD64 Fedora FAQ.
9. Q: Có thể chạy Fedora trên máy Mac (PowerPC)?
A: Vâng, được nhưng hơi phức tạp một chút -- xem hướng dẫn của Colin Charles để cài đặt Fedora trên iBook (bạn có thể cài đặt trên các máy Mac khác với các hướng dẫn đó, nhưng có thể sẽ phải thay đổi đôi chút.)

(Cảm ơn Colin Charles!)
10. Q: Có thể tìm thấy đĩa cài đặt Fedora Core 2 ở đâu?
A: Hạt nhân mới 2.6 trong Fedora Core 2 không thể ghi lên một đĩa mềm được. Do vậy bạn không thể khởi động hay cài đặt từ đĩa mềm. Tuy nhiên bạn có thể cài đặt từ CD, đĩa cứng hoặc thậm chí từ đĩa USB (nếu máy tính của bạn có thể khởi động từ đĩa USB).

(Cảm ơn Noa Resare về đề nghị cho câu hỏi này và cho tôi các ví dụ rất tốt.)

Tải về và cài đặt các phần mềm

1. Q: Có thể tìm được các ứng dụng cho Fedora ở đâu?
A: Có nhiều "repositories" (máy chủ lưu trữ các gói phần mềm): trong số đó có rpm.livna.org (cho các gói có giấy phép hạn chế) và chính thức hơn là dự án fedora.us Extras. Các kho này lưu trữ các phần mềm khác nhau.

Có thể lựa chọn FreshRPMs nếu cần đến các gói mà cả fedora.us hay livna.org đều không có.

Để tìm kiếm các phần mềm trong các kho lưu trữ chính, dùng công cụ tìm kiếm có tại FedoraTracker.
2. Q: Làm sao để cài đặt các gói phần mềm trong Fedora? (Làm sao để dùng yum hay RPM)
A: Cách đơn giản nhất để cài đặt một phần mềm trong Fedora là dùng yum.

CHÚ Ý: Fedora Core 2 vừa mới được công bố, cho nên không phải tất cả các gói đều có. Nếu khi bạn cài đặt bằng yum và thấy thông báo "can't resolve dependencies" đừng lo lắng. Chỉ cần thử lại sau vài ngày.
1. Tải về file yum.conf. (cập nhật 29/05/2004)
2. Thay thế file /etc/yum.conf của bạn bằng file vừa mới tải xuống. Bạn cần phải đăng nhập vào root để làm chuyện đó. Thật ra, bạn cần root để thực thi các lệnh sau đây.

Nhớ rằng file yum.conf cung cấp ở đây thỉnh thoảng được cập nhật.

CHÚ Ý: Khi bạn chạy yum lần đầu, yum sẽ tải về các file header cho mỗi gói. Điều này có khi phải mất khá nhiều thời gian, có khi đến cả giờ, ngay với cả các đường truyền tốc độ nhanh.

Bây giờ, bạn có thể liệt kê các phần mềm có bằng lệnh sau:

# yum list available
* Để cài đặt một phần mềm, dùng lệnh:

# yum install têngói
* Để cập nhật một phần mềm, dùng lệnh:

# yum update têngói

Nếu bạn không chỉ định têngói, yum sẽ cập nhật tất cả các phần mềm trên hệ thống của bạn
* Để xem có gói phần mềm nào để cập nhật, dùng lệnh:

# yum check-update
* Để tìm kiếm một gói phần mềm, dùng lệnh:

# yum search

Muốn biết thêm chi tiết về yum, xin xem tại trang chủ của dự án yum. (Cảm ơn Ron Kuris đã gợi ý.)

Nếu bạn muốn an toàn hơn, bạn nên kiểm tra chữ ký GPG cho tất cả các gói trước khi cài đặt hay cập nhật. Thông thường chỉ cần loại bỏ dấu # cho hàng có "gpgcheck=1" trong file /etc/yum.conf. Bạn nên xem thêm tại câu hỏi về chữ ký GPG. (Cảm ơn Kai Thomsen đã đề nghị thêm ghi chú này.)

Để dùng yum qua một proxy, xem mục thảo luận tại FedoraForum. (Cảm ơn Reinhard Herzfeld đã cung cấp liên kết này.)

Để cài đặt một gói RPM mà bạn đã tải về khi không dùng yum, hãy mở một cửa sổ dòng lệnh (xterm, rxvt, gnome-terminal, konsole,...) trong root và thực hiện:

# rpm -Uvh filename.rpm
3. Q: Có chương trình nào tương tự như apt cho Fedora?
A: APT là một công cụ của Debian Linux cho phép không những để cài đặt/cập nhật phần mềm mà bạn yêu cầu, mà còn làm việc được với các gói phần mềm phụ thuộc liên quan. Công cụ này giúp cho người dùng cài đặt phần mềm dễ dàng hơn.

Có một công cụ như apt cho Fedora, và nó được cài đặt mặc định cho Fedora Core. Đó là yum. Nó có thể tự động tải về và cài đặt một phần mềm cùng với các phần mềm phụ thuộc chỉ với một dòng lệnh duy nhất. Đây là file cấu hình mà tôi dùng trên máy tính của mình. Các giải thích về cách dùng yum đã được đề cập đến trong phần Cài đặt phần mềm.

Cho những ai thật sự thích apt, có một phiên bản cho Fedora. Bạn có thể tải về từ fedora.us. (Tìm gói có tên apt.) Tôi nghe nói rằng công cụ đó chạy rất tốt.
4. Q: Có thể tìm thấy các gói Extras cho Fedora ở đâu?
A: Các gói "Fedora Extras" là tập hợp các gói bán [không] chính thức được hỗ trợ bởi dự án Fedora. Địa chỉ của máy chủ là fedora.us Extras. Để cài đặt, chỉ cần xem câu hỏi về cài đặt phần mềm. Hiện nay dự án này chưa bắt đầu.
5. Q: Các máy chủ cập nhật của Red Hat chậm quá! Phải làm gì bây giờ?
A: Trước hết, bạn phải dùng yum. Sau đó, dùng file yum.conf từ FAQ này -- trong file này, người ta dùng các máy chủ mirror để đạt được tốc độ nhanh. (Xem câu hỏi về cài đặt phần mềm nếu bạn cần giúp đỡ về sử dụng yum.)

Nếu bạn thật sự muốn dùng up2date, bạn có thể xem bài viết của Alexander Dalloz để biết cách cấu hình up2date để dùng các máy chủ mirror.
6. Q: Làm sao cài đặt Java?
Cách đơn giản nhất là cài đặt các gói RPM của Dag Wieers:
1. Tải về gói RPM "j2re-" có chữ "fc2" trong tên, và cài đặt nó. (Tên của gói RPM có dạng như là : j2re-1.4.2-5.1.fc2.dag.i586.rpm)
2. Để dùng Java trong trình duyệt web (mozilla), tải về gói "mozilla-j2re" có "fc2" trong tên và cài đặt. (Tên của gói RPM có dạng như : mozilla-j2re-1.4.2-5.1.fc2.dag.i586.rpm)

Nếu các bước trên không chạy được, hoặc là bạn muốn lập trình với Java (tức là bạn cần SDK thay vì Java Runtime), dùng các hướng dẫn cài đặt Java.

Nếu bạn có vấn đề với Java, xem lỗi 121902 ở hệ thống theo dõi lỗi của Red Hat để tìm cách khắc phục.

(Cảm ơn Dag Wieers đã đơn giản hóa rất hay câu hỏi này. Cảm ơn Tarjei Knapstad về mẹo liên quan đến Java.)
7. Q: Làm sao cài đặt Flash trong trình duyệt web?
A:Có hai cách để thực hiện, dùng yum hoặc không dùng.
* Dùng yum (dễ nhất):
1. Dùng file yum.conf trong phần câu hỏi cài đặt phần mềm.
2. Mở một cửa sổ dòng lệnh.
3. Trở thành root bằng lệnh :

# su -
4. Gõ lệnh :

# yum install flash-plugin
* Không dùng yum (phức tạp hơn):
1. Tải về gói Flash Plugin RPM (Chọn gói cho "Fedora Core 2" sau khi nhấn vào liên kết.)
2. Mở một cửa sổ dòng lệnh
3. Trở thành root bằng lệnh :

# su -
4. Gõ lệnh

# rpm -Uvh flash-plugin-*.i386.rpm

CHÚ Ý: Nếu bạn cài đặt phiên bản mới của Mozilla bạn phải cài đặt lại Flash.

Nếu Flash chạy chậm, chỉ cần thêm export FLASH_GTK_LIBRARY=libgtk-x11-2.0.so.0 vào trong file .gtkrc trong thư mục gốc của bạn ($HOME). (Cảm ơn Kristin Aanestad về mẹo này!)

Nếu bạn có thắc mắc xem Flash Plugin FAQ! (Cảm ơn Warren Togami về liên kết này.)

(Cảm ơn nhiều người trên kênh IRC và vegan_linuxguy về việc xử lý sự cố. Cảm ơn "m d," David Ball và các người khác đã chỉ ra lỗi typo quan trọng trong câu hỏi này! Cảm ơn David Jansen đã chỉ cho tôi hay rằng phiên bản mới của Flash không cần thư viện libstdc++-compat nữa.)
8. Q: Làm sao để xem các file PDF trong trình duyệt web?
A: Cách dễ nhất là dùng Adobe Acrobat Reader. Chỉ cần cài đặt gói mozilla-acroread của Dag Wieers (lấy gói cho "fc2").
9. Q: Có thể dùng MSN® Messenger/AIM/ICQ/Yahoo IM trong Fedora?
A: Vâng, trong Fedora có phần mềm tên GAIM cho phép dùng MSN® Messenger, ICQ, AIM, Yahoo! Messenger và Jabber, tất cả cùng một lúc.

Để chạy GAIM, nhấn vào menu "Red Hat", sau đó "Internet" và chọn "Messaging Client".

Xem tài liệu GAIM để biết cách dùng GAIM với MSN.
10. Q: Có thể dùng TrueType font trong Fedora? (cập nhật 31/05/2004)
A:Vâng, ban; có thể dùng.
1. Nhấn double lên biểu tượng "Computer" trên desktop.
2. Trong menu "File", chọn "Open Location..."
3. Gõ vào đó:

fonts:

Bây giờ đơn giản chỉ cần rê & thả các font của bạn vào cửa sổ đó để cài đặt chúng. (Cảm ơn Harold Gimenez)
11. Q: Tôi có thể tìm thấy các driver cho phần cứng của tôi trong Fedora?
Dag Wieers cung cấp một gói các module của kernel for Fedora, dùng cho tất cả các dạng phần cứng. Tất cá các gói mà tên bắt đầu bằng "kernel-module" là các driver. Chỉ cần tải về phiên bản thích hợp của driver cho kernel của bạn. Nếu bạn muốn biết kernel đang chạy là kernel nào thì mở một cửa sổ dòng lệnh và gõ:

# uname -r

CHÚ Ý: Bạn phải tải về phiên bản mới của driver mỗi khi bạn cài đặt kernel mới.

Nếu bạn không tìm thấy những gì bạn cần trên trang chủ của Dag, thử tìm kiếm với Google với:

Linux NameOfHardware

Trong đó NameOfHardware là tên bình thường của phần cứng của bạn. Nếu có nhiều tên khác nhau, thử với các tên khác nhau cho đến lúc tìm thấy kết quả.

Sự cố và các giải pháp khắc phục

1. Q: Tôi nhận thông báo NOKEY từ RPM, hay có lỗi chữ kí GPG khi dùng Apt / Yum / up2date! (cập nhật 24/05/2004)
A: Thông báo NOKEY thực ra không phải là vấn đề. Nó không ngăn cản bạn làm bất cứ cái gì cả. (Lỗi của Apt / yum / up2date thông thường sẽ không cho phép bạn cài đặt phần mềm.)

Nếu bạn muốn khắc phục cái đó thì gõ lệnh sau đây để lấy KEY từ máy chủ về.

Bạn phải là root để thực hiện các lệnh dưới đây
* fedora.us:

# rpm --import http://www.fedora.us/FEDORA-GPG-KEY
* rpm.livna.org:

# rpm --import http://rpm.livna.org/RPM-LIVNA-GPG-KEY
* FreshRPMs:

# rpm --import http://freshrpms.net/packages/RPM-GPG-KEY.txt
* DAG:

# rpm --import http://dag.wieers.com/packages/RPM-GPG-KEY.dag.txt
* ATrpms:

# rpm --import http://atrpms.net/RPM-GPG-KEY.atrpms
* NewRPMs:

# rpm --import http://newrpms.sunsite.dk/gpg-pubkey-newrpms.txt
* JPackage:

# rpm --import http://www.jpackage.org/jpackage.asc

Nếu bạn chưa bao giờ dùng up2date bạn cần thực hiện lệnh:

# rpm --import /usr/share/doc/fedora-release-2/RPM-GPG-KEY*

để cài đặt các key của Red Hat.

(Cảm ơn Kai Thomsen về địa chỉ của ATrpms key, và cảm ơn Tom Householder về địa chỉ mới!.)
2. Q: Tôi gặp lỗi XKB sau khi đăng nhập!
A: Ồ, cái này thì dễ!
1. Mở cửa sổ dòng lệnh, trở thành root bằng cách:

$ su -
2. Mở file cấu hình của X.org trong trình soạn thảo gedit bằng cách gõ:

# gedit /etc/X11/XF86Config

(Nếu có thông báo không có file đó thì dùng lệnh gedit /etc/X11/xorg.conf)
3. Tìm dòng :

Option "Xkbrules" "xfree86"

và sửa thành:

Option "Xkbrules" "xorg"

Bây giờ thì sẽ không còn thông báo lỗi đó nữa! (Cảm ơn Fedora News Updates về giải pháp này!)
3. Q: Làm sao thiết lập hỗ trợ 3D cho card ATI Radeon trong Fedora Core 2? (cập nhật 17/07/2004)
A: ATI có các driver trên trang chủ để thiết lập hỗ trợ tăng tốc 3D cho các card Radeon. Tuy nhiên phải thay đổi mới dùng được với Fedora Core 2:
1. Trước hết, tải về ATI Drivers (file cho "XFree86 4.3.0").
2. Sau đó, tải về Fedora Core 2 patch(cập nhật 17/07/2004) cho ATI Driver. (Cảm ơn micha trên FedoraForum về bản vá lỗi!) Lưu bản vá lỗi vào thư mục /tmp.
3. Mở cửa sổ dòng lệnh, trở thành root bằng cách:

$ su -
4. Cài đặt gói kernel-sourcecode :

$ yum install kernel-sourcecode
5. Loại bỏ module của ATI driver:

# rmmod radeon
6. Cài đặt driver của ATI:

# rpm -Uvh --replacefiles fglrx-4.3.0-*.i386.rpm
7. Bây giờ cần phải chỉnh một tí nếu bạn dùng dual-processor (nếu bạn không chắc chắn, cứ thực hiện lệnh sau vì nó vô hại):

# ln -s /usr/src/linux-`uname -r` /usr/src/linux-`uname -r`smp
8. Bây giờ sẽ vá lỗi cho driver để nó chạy trong Fedora Core 2:

# cd /lib/modules/fglrx/build_mod/
# patch -p1 -i /tmp/fglrx-3.9.0-fc2-2.6.6.patch

9. Tiếp tục biên dịch và cài đặt module :

# sh make.sh
# cd ..
# sh make_install.sh

10. Đóng server X (giao diện đồ họa của Linux) để cài đặt driver. Mở cửa sổ dòng lệnh và gõ :

# telinit 3

Lệnh này sẽ tắt X và làm xuất hiện dấu nhắc đăng nhập dạng text "Login:"
11. Đăng nhập vào root.
12. Và cài đặt driver:

# fglrxconfig
13. Driver của ATI sẽ tạo ra file cấu hình mới. Để chắc chắn rằng X sẽ dùng file cấu hình mới :

# cd /etc/X11
# mv xorg.conf xorg.conf.bak
# ln -sf XF86Config-4 xorg.conf

14. Khởi động lại chế độ đồ họa X:

# telinit 5

Và như vậy là driver cho card đồ họa ATI với hỗ trợ 3D đã được cài đặt !

(Cảm ơn Rage3D Linux Forum và Sindre về những bước đầu tiên của quá trình cài đặt này! Cảm ơn Paul Kilgo, Kevin Goldstein, và Simon Olofsson về những phát hiện lỗi chính tả trong câu hỏi này! Cảm ơn Peter Lawler về sự giúp đỡ và thử nghiệm!)
4. Q: Làm sao thiết lập hỗ trợ 3D cho card màn hình nVidia trong Fedora Core 2? (cập nhật 3/07/2004)
A: nVidia đã công bố các driver cho Fedora Core 2! Sau đây là tóm tắt quá trình cài đặt:
1. Tải về phiên bản mới nhất cho Linux.
2. Mở cửa sổ dòng lệnh và trở thành root:

# su -
3. Tắt chế độ X:

# telinit 3
4. Từ dấu nhắc "Login:" đăng nhập vào root và chuyển đến thư mục mà driver nVidia đã được lưu.
5. Gõ:

# sh NVIDIA-Linux-x86-1.0-6106-pkg*.run
.
6. Theo hướng dẫn của nVidia để cài đặt driver. (Đọc phần "EDITING YOUR XF86CONFIG FILE".)
7. Bây giờ cần phải xóa các file có thể không tương thích :

# rpm -e --nodeps xorg-x11-Mesa-libGL

CHÚ Ý: Nếu cập nhật các gói "xorg-x11" với up2date hay yum, bạn cần phải làm lại lệnh trên.
8. Bạn có thể khởi động lại X bằng cách gõ telinit 5.

CHÚ Ý: Bạn phải làm lại các bước mô tả trên mỗi khi cập nhật nhân mới với yum hay up2date.

(Cảm ơn Dexter Ang đã giúp đỡ câu trả lời ! Cảm ơn Vahe Sarkissian đã sửa lỗi.)
5. Q: Vài trang web chạy chậm (như fedorafaq.org hay New York Times)!
A: Đó không phải là lỗi của máy chủ! Phiên bản mới nhất của Mozilla có hỗ trợ "IPv6", dạng thức mới để quản lý địa chỉ trên internet.

Tuy nhiên đa số các trang web sites và các kết nối hiện tại chưa hỗ trợ IPv6.

Vấn đề là: Mozilla tìm cách dùng IPv6 trước khi dùng IPv4. Khi kết nối Internet không hỗ trợ IPv6, Mozilla sẽ thất bại với IPv6 (lần thử đầu tiên). Trong phiên bản hiện tại của Mozilla, bạn không thể thay đổi do một lỗi.

Do đó phải tắt IPv6 trong Fedora:
1. Mở cửa sổ dòng lệnh và trở thành root:

# su -
2. Mở file /etc/modprobe.conf bằng gedit:

# gedit /etc/modprobe.conf
3. Thêm các dòng sau đây vào cuối file:

# Turn off IPv6
alias net-pf-10 off
alias ipv6 off

4. Khởi động lại máy và trình duyệt sẽ tải các trang nhanh hơn!

(Cảm ơn Jonathan Baron và Chris Hubick về câu trả lời này!)
6. Q: Card mạng 3Com không hoạt động!
A: Được rồi, trước hết hãy xem lỗi này. Có vấn đề với loại card 3Com 3c905B/TX và nó tác động đến kudzu như thế nào.

Nếu bạn tắt kudzu (là trình nhận biết các thiết bị phần cứng mới) thì sẽ giải quyết được vấn đề đó. Dưới root, trong một cửa sổ dòng lệnh, gõ :

# chkconfig kudzu off

Khi khi khởi động lại, card mạng của bạn sẽ hoạt động. (Cảm ơn jroysdon)
7. Q: Card mạng không dây không chạy!
A: Vâng, đó là một lỗi đã biết của Anaconda, trình cài đặt của Fedora Core 2. Trình này đã cài đặt sai card mạng không dây. Do vậy cần thiết phải cài đặt lại cho đúng:
1. Mở menu "Red Hat" và đến mục System Settings -> Network.
2. Nhấn vào thẻ Hardware, chọn card của bạn và nhấn nút "Delete".
3. Đóng Network Configuration.
4. Bây giờ mở menu "Red Hat" và đến System Tools -> Internet Configuration Wizard.
5. Chọn "Wireless Connection" và nhấn Forward.
6. Chọn card mạng của bạn và nhấn "Forward."
7. Kể từ đây chỉ cần nhấn "Forward" nếu bạn không biết rõ câu trả lời.
8. Khởi động lại máy và card mạng không dây sẽ hoạt động.

Giải pháp này khắc phục hầu hết các sự cố với card mạng không dây, nhưng không phải là tất cả.
8. Q: Máy tự khởi động lại khi cài đặt Fedora Core 2! (Cập nhật 17/07/2004)
A: Chắc hẳn bạn dùng ASUS P4P800 motherboard hoặc là bộ xử lý hiệu VIA C3. Đây là cách khắc phục:
1. Tải về bản ISO đã sửa lỗi hoặc từ VIA C3 hoặc từ ASUS P4P800.
2. Ghi image lên CD. Trong cửa sổ dòng lệnh dùng lệnh:

# cdrecord -dev=/dev/cdrom -data name.iso

Với "name.iso" là tên của file đã tải về trong các bước trên. (Thiết bị ghi CD của bạn có thể cdrom1 nếu bạn có 2 ổ CD.)
3. Khởi động tù đĩa CD mới ghi đó và cài đặt Fedora Core 2. Khi được hỏi về nguồn cài đặt chọn "Local CDROM" và bỏ CD số 1 nguyên gốc của Fedora Core 2 vào.
4. Fedora Core 2 sẽ được cài đặt với sự cố như cũ, do vậy cần phải chỉnh. Khởi động bằng CD mà bạn đã ghi, thay vì cài đặt chọn:

linux rescue
5. Chọn "Local CDROM" là nơi có CD rescue, và bỏ CD số 1 nguyên gốc của Fedora Core 2 vào.
6. Khi được hỏi về Networking, trả lời "yes", và "yes" để mount hệ thống. Nhấn "OK" hoặc "Next" cho tất cả các phần còn lại, hay là trả lời những gì bạn biết rõ.
7. Khi thấy dấu nhắc, gõ:

# chroot /mnt/sysimage/
8. Mở trang Fedora Updates:

# links http://mirrors.kernel.org/fedora/core/updates/2/i386/
9. Dùng phím mũi tên để chọn kernel mới nhất cho đúng loại CPU của bạn:
* Với VIA C3 thì sẽ có dạng như : kernel-2.6.6-1.[version].i586.rpm.
* Với ASUS P4P800 thì sẽ có dạng : kernel-2.6.6-1.[version].i686.rpm.

Nếu có nhiều phiên bản thì chỉ cần chọn gói nào có giá trị [version] lớn nhất.
10. Nhấn Enter để tải về và chọn "Save" khi được hỏi.
11. Nhấn q để thoát khỏi trình duyệt web.
12. Cài đặt hạt nhân mới bằng lệnh:

# rpm -Uvh kernel-2.6*
13. Xóa file mà bạn vừa cài đặt:

# rm -f kernel-2.6*
14. Xóa hạt nhân gốc của Fedora :

# rpm -e kernel-2.6.5-1.358
15. Khởi động lại máy tính, bỏ CD ra khỏi ổ đĩa, và Fedora Core 2 sẽ chạy tốt!

# reboot

(Cảm ơn Tarjei Knapstad và Alan Cox đã cung cấp thông tin. Cảm ơn JW Vraets về những giải thích!)
9. Q: Tôi gặp lỗi "disk space" khi cài đặt Fedora!
A: Nếu gặp lỗi với trình cài đặt, trước hết hãy thử:

linux allowcddma

khi khởi động trình cài đặt. Nếu vẫn không chạy thì thử :

linux mem=128M

Nếu với tùy chọn 128M vẫn không chạy thì thử với giá trị nhỏ hơn cho đến khi chạy được. Mẹo nhỏ: chọn giá trị bằng "Bộ nhớ RAM - 2M". (Cảm ơn Alan Cox đã giải thích rõ.)

Thông báo lỗi thường thấy là : An error occurred transferring the install image to your hard drive. You are probably out of disk space.

(Cảm ơn Neuberg Tor Erik, |Jef| và StarHeart về phương pháp DMA. Cảm ơn Dave Lovelace và Götz Reinicke về phương pháp memsmilie
10. Q: Sau khi cài đặt Fedora Core 2 tôi không thể khởi động vào Windows! (Cập nhật 17/07/2004)
A: Điều này chỉ có thể xảy ra khi bạn cài đặt phiên bản Fedora Core 2 Test và sau đó nâng cấp lên Fedora Core 2.

Lỗi này không chỉ liên quan đến Fedora. Nó xảy ra với nhiều bản phân phối Linux dùng phiên bản mới của nhân 2.6.

Nếu bạn gặp vấn đè này thì đây là cách khắc phục:
1. Mở cửa sổ dòng lệnh và trở thành root:

# su -
2. Gõ lệnh:

# sfdisk -d /dev/hda | sfdisk --no-reread -H255 /dev/hda

CHÚ Ý: Ổ đĩa Windows của bạn có thể không phải là "hda" -- Nếu không chắc chắn, bạn có thể chạy lệnh cat /proc/partitions để xem kích thước cho từng ổ đĩa. Điều đó có thể cho phép bạn suy luận và tìm ra đâu là ổ đĩa Windows.

Nếu lệnh trên không chạy hoặc có lỗi thì thử "-H240" thay vì "-H255". Nếu vẫn không chạy bạn có thể đọc HOWTO khá dài chỉ cách khắc phục lỗi khi khởi động Linux và Windows.

Nếu muốn thông tin chi tiết hơn xin xem thông báo lỗi 115980 tại trang quản lý lỗi (Bugzilla) của Red Hat.

(Cảm ơn Gareth Russell)
11. Q: Tôi có vấn đề khác khi cài đặt mà không có nêu ra ở trên.
A: Nếu quá trình cài đặt của bạn không suông sẻ hay là bạn có trục trặc trong lúc hay sau khi cài đặt thì trước hết hãy đọc README và Release Notes.

Nếu README và Release Notes không có giúp bạn được gì thì hãy thử khởi động trình cài đặt với một trong các lệnh sau đây:

linux acpi=off

linux i8042.nomux

linux acpi=off apm=off

Tùy chọn "i8042.nomux" là rất có ích nếu bạn có vấn đề với bàn phím hoặc chuột.

Nếu vẫn không có giải pháp nào ở trên có thể giúp bạn thì xin gửi báo cáo lỗi cho trung tâm quản lý lỗi của Red Hat.

(Cảm ơn Alan Cox về các thông tin này)
12. Q: Sau khi cài đặt một chương trình, làm sao chạy nó?
A: Trước hết xem trong menu "Red Hat" trên thanh công cụ (toolbar). Đa số các chương trình cài đặt đều được thêm vào các menu một cách tự động.

Nếu không tìm thấy trong menu, bạn có thể dùng cửa sổ dòng lệnh (Terminal). Đa số chương trình đều được thực thi bằng tên của nó. Ví dụ, để chạy trình duyệt web "mozilla" bạn chỉ cần gõ trong cửa sổ dòng lệnh:

# mozilla

Nếu không có trong menu và lệnh trùng tên gói cũng không chạy, thử tìm chương trình khả thi trong gói phần mềm:

# rpm -ql packagename | grep bin
13. Q: Làm sao nghe nhạc MP3 với XMMS? (Cập nhật 23/05/2004)
A: Trước khi đề cập đến vấn đề này bạn nên biết rằng: Ở Mỹ và một vài nước khác, bạn phải trả lệ phí bản quyền để sử dụng các trình nghe nhạc hay các trình tạo MP3. Tuy nhiên cho các người dùng cá nhân thì không có vấn đề vi phạm bản quyền với các trình nghe nhạc MP3. (Cảm ơn Doug McClean đã giải thích rõ ràng vấn đề này!)

Các module chuẩn bị sẵn (plugins) cho các trình nghe nhạc MP3 có tại kho lưu trữ rpm.livna.org.
1. Xác lập cấu hình của file yum.conf để nối vào rpm.livna.org. (Xem câu hỏi về tải xuống phần mềm Fedora)
2. Mở cửa sổ dòng lệnh và trở thành root:

# su -
3. Gõ lệnh :

# yum install xmms-mp3
14. Q: Làm sao nghe nhạc MP3 với Rhythmbox? (Cập nhật 24/05/2004)
A: Nên nhớ có thể có vấn đề về bản quyền. Xem câu hỏi XMMS.

Các module chuẩn bị sẵn (plugins) cho các trình nghe nhạc MP3 có tại kho lưu trữ rpm.livna.org.
1. Xác lập cấu hình của file yum.conf để nối vào rpm.livna.org. (Xem câu hỏi về tải xuống phần mềm Fedora)
2. Mở cửa sổ dòng lệnh và trở thành root:

# su -
3. Gõ :

# yum install gstreamer-plugins-mp3
4. Tải plugin:

# gst-register-0.8
15. Q: Làm sao nghe nhạc MP3 với trình nghe nhạc KDE như Noatun hay Juk?
A: Xem trả lời của Adrian Holovaty cho câu hỏi này.
16. Q: Làm sao đọc các đĩa NTFS (Windows NT/2000/XP/2003) trong Fedora?
A: Được, chuyện này thì dễ! Dự án linux-ntfs có hẳn một trang dành cho Red Hat và Fedora.
17. Q: Tôi không thích trình quản lý file kiểu "spatial", làm sao tắt nó đi?
A:Ít nhất bạn cũng nên thử trình quản lý file mới. Nó rất hay, nhiều người cho rằng đó là một trình quản lý file tốt, nhanh và khá hiệu quả. Nếu bạn muốn có một hướng dẫn tốt hãy đọc trang giới thiệu về trình quản lý file kiểu "spatial".

Nếu bạn thực sự không thích kiểu mới này và muốn quay trở lại kiểu cũ:
1. Mở một cửa sổ dòng lệnh.
2. Gõ :

$ gconftool-2 --type bool --set /apps/nautilus/preferences/always_use_browser true
3. Thoát ra và đăng nhập trở lại, bạn sẽ có trình quản lý file hoạt động theo kiểu cũ.

Nếu bạn muốn bật kiểu mới cho trình quản lý file thì gõ:

$ gconftool-2 --type bool --set /apps/nautilus/preferences/always_use_browser false

thoát ra và đăng nhập trở lại.

(Cảm ơn Mark McLoughlin và Jorge Castro đã chỉ cách sử dụng đơn giản với gconftool-2.)
18. Q: Làm sao sửa đổi các menu trên panel? (Cập nhật 17/06/2004)
A: Không có cách dễ dàng để làm chuyện đó trong các phiên bản mới của GNOME hay KDE.

Nếu bạn thực sự muốn sửa đổi thì các mục menu được định nghĩa trong một file dạng text ".desktop" trong /usr/share/applications/. Bạn có thể sửa đổi nó trong các trình soạn thảo (như gedit) nếu bạn là root. Bạn cũng có thể dùng công cụ dòng lệnh tên là desktop-file-install để thêm file .desktop mới mà bạn tạo ra. Nếu bạn muốn biết làm sao để viết file .desktop, bạn có thể hoặc xem các file hiện có trong /usr/share/applications, hoặc bạn có thể đọc (hơi mang tính kĩ thuật) chi tiết kĩ thuật .desktop.
19. Q: Làm sao chạy được Wine?
A: Có các gói RPM tại NewRPMs. Đến kho lưu trữ NewRPMs Fedora và tải về bất cứ gói Wine nào mới nhất (kiểm tra ngày tháng của file), và cài đặt nó. (Cảm ơn che)

Nếu vì một lí do nào đó bạn không thể dùng các gói RPM của Wine RPMs (ví dụ bạn đang dùng phiên bản Wine của CrossOver Office), bạn có thể un-prelink tất cả để giải quyết các vấn đề liên quan đến Wine trong Fedora:
1. Trở thành root:

# su -
2. Chạy lệnh:

# prelink -ua
3. Sửa đổi file /etc/sysconfig/prelink bằng cách thay:

PRELINK_OPTS=-mR

bằng :

PRELINK_OPTS="-m --no-exec-shield"
4. Rồi chạy lệnh sau để tắt exec-shield:

# prelink -am --no-exec-shield

CHÚ Ý: Exec-shield làm giảm nguy cơ bị "buffer overflow" mà đa số các virus và tấn công dùng để làm hại hệ thống của bạn. Tuy nhiên, nếu bạn giữ hệ thống được cập nhật đầy đủ thì sẽ không có gì nguy hiểm sau khi bạn tắt exec-shield.

CHÚ Ý: Bạn cũng có thể sửa đổi file /etc/prelink.conf và bó qua tất cả những gì liên quan đến Wine, nhưng tôi không biết chi tiết về những gì bạn cần bỏ qua. (Nếu bạn thành công, báo cho tôi hay!)

(Cảm ơn Carlos Vidal và Jeremy White về những chỉ dẫn chung liên quan đến un-prelink cho Wine. Cảm ơn Guy Fraser về phương pháp PRELINK_OPTS)
20. Q: Tôi không thể kết nối với mạng chia sẻ của Windows ! Có người bảo tôi dùng lệnh smbmount nhưng nó không chạy được!
A: Fedora Core 2 dùng loại file hệ thống mới để chia sẻ mạng Windows tên là "The Common Internet Filesharing System" (CIFS). Thay vì dùng smbmount, hãy thử:

# mount -t cifs //computername/share /mnt/somedirectory

Muốn biết thêm chi tiết về lệnh đó, trong cửa sổ dòng lệnh, gõ :

# man mount.cifs
21. Q: Chế độ cứu nguy (rescue) là gì và làm sao khởi động vào chế độ đó?
A: Chế độ cứu nguy cho phép khởi động một môi trường nhỏ của Fedora hoàn toàn từ CD-ROM hoặc đĩa USB thay vì từ đĩa cứng của hệ thống. Như tên gọi của nó, chế độ này dùng để giải quyết sự cố của hệ thống. Với chế độ này bạn có thể mount và sửa đổi các file, ví dụ như các file cấu hình để khắc phục sự cố.

Để khởi động vào chế độ cứu nguy, bạn phải có khả năng dùng một trong những phương pháp sau đây:
1. Khởi động từ một CD-ROM hoặc từ "boot image" có trên một đĩa USB.
2. Khởi động từ đĩa CD số 1 của Fedora.

Một khi đã khởi động với một trong những phương pháp nói trên, nhập vào lệnh sau đây khi thấy dấu nhắc:

linux rescue
22. Q: d00d, u sukc
A: Whoa, dude. I love you too.

Too many goats, not enough kudzu. (Mèn! biết dịch sao đây hè ?)


FAQ này được duy trì bởi Max Kanat-Alexander (max -at- fedorafaq -dot- org) hoặc Avatraxiom tại #fedora trên FreeNode. Bí danh Sindre "foolish" Pedersen Bjordal là trợ lý biên tập (foolish -at- fedorafaq -dot- org).
Bạn có thể giúp chúng tôi cập nhật FAQ này! Nếu bạn phát hiện vấn đề nào đó mà chưa đè cập đến trong FAQ, tìm thấy các lỗi hay có các đề nghị xin vui lòng liên lạc với chúng tôi. Cảm ơn.
Mọi nhận xét, góp ý, sửa lỗi cho bản dịch tiếng Việt xin liên lạc với NGUYỄN-ĐẠI Quý (nguyendaiquy -at- gmail -dot- com) hoặc có thể trao đổi trực tiếp trên #vietlug hay VNOSS forum.
Cập nhật lúc 20:14:37 (CEST) ngày 5 tháng 8 năm 2004.
Giới thiệu và thông tin chung
Nguồn và tài nguyên mạng
Tính tương thích với các hệ điều hành khác
Hệ thống tập tin, đĩa, và ổ đĩa
Porting, biên dịch và lấy chương trình
Giải pháp cho các vấn đề linh tinh thông thường
Làm điều này như thế nào hoặc tìm hiểu cái kia ra sao...
Thông tin linh tinh và các câu hỏi được trả lời
Các thông báo lỗi thường gặp
X Window System
Tìm trợ giúp sâu hơn như thế nào



Tác giả : pclouds
Nguồn : VnoSS
Phiên bản 0.8 - Phát hành ngày 08/10/2004.

Việc cần thực hiện:

Xây dựng hệ thống tập tin gốc.

Cấu hình mạng cho môi trường UML.

UML dùng để làm gì?

Thuật ngữ

Hoàn thiện các phần đã viết.

Nội dung

1. Giới thiệu

2. Cơ chế hoạt động

3. Cài đặt UML

4. Khởi tạo môi trường UML

5. Xây dựng hệ thống tập tin gốc

6. Kết luận

7. Phụ lục

1. Giới thiệu

User-mode Linux là một bản vá cho hạt nhân linux, cho phép biên dịch hạt nhân linux thành một chương trình có khả năng chạy trong môi trường linux. Bằng "Chương trình hạt nhân" này người dùng có thể xây dựng một môi trường mới, hoạt động song song với môi trường hiện có (môi trường nền). Khi đó chương trình hạt nhân sẽ đóng vai trò là hạt nhân của môi trường mới, do vậy chương trình hạt nhân có thể được gọi cùng với một số tài nguyên "ảo" như: hệ thống tập tin gốc (root filesystem), không gian tráo đổi (swap space), và có thể có cấu hình phần cứng tách biệt so với một trường linux chạy nó.
UML dùng để làm gì?

Virtual hosting.

Kernel development and debug.

Process debugging.

Safely playing with the latest kernels.

Thử nghiệm các bản phân phối Linux (Linux distro).

Education.

Experimental development.

Poking around inside a running system.

As a secure sandbox or jail.

Virtual networking.

As a test environment.

Disaster recovery practice.

2. Cơ chế hoạt động của UML

Về cơ bản, một môi trường UML có thể thực thi bất cứ gì mà môi trường linux thông thường có thể làm. Hơn nữa nó đem đến cho người dùng khả năng chia nhỏ một chiếc máy tính ra thành một nhóm các máy ảo độc lập. Thông thường, hạt nhân linux đảm nhận các tác vụ giao tác với phần cứng (video card, keyboard, hard drives,...), và mọi chương trình muốn truy xuất, khai thác phần cứng đều thực hiện thông qua các dịch vụ của hạt nhân. Mô hình thông thường có thể minh hoạ theo sơ đồ sau:

+--------------+--------------+----+
| Tiến trình 1 | Tiến trình 2 | ...|
+--------------+--------------+----+
| Hạt nhân Linux |
+----------------------------------+
| Phần cứng |
+----------------------------------+

Cơ chế hoạt động của UML có chút khác biệt; Thay vì giao tác trực tiếp với phần cứng, chương trình hạt nhân UML sẽ giao tác với một hạt nhân Linux thực sự (kể từ đây chúng ta gọi là "hạt nhân nền"), giống như các chương trình khác. Trong mô hình hoạt động của UML, sẽ là không có sự khác biệt giữa các chương trình chạy trong môi trường UML với môi trường thông thường. Mô hình hoạt động có thể được mô tả như sau:

+-------------------+
| Tiến trình 2 | ...|
+--------------+-------------------+
| Tiến trình 1 | User-Mode Linux |
+----------------------------------+
| Hạt nhân Linux |
+----------------------------------+
| Phần cứng |
+----------------------------------+

3. Cài đặt UML Linux
3.1 Cài đặt và điều chỉnh môi trường nền

Để cài đặt UML Linux, chúng ta cần có một số điều chỉnh nhỏ cho môi trường nền, bao gồm: cài đặt các công cụ của UML linux và biên dịch lại hạt nhân với một bản vá SKAS (Separate Kernel Address Space) của dự án UML Linux (Bản vá này cho phép chương trình hạt nhân thực thi trong một không gian bộ nhớ tách biệt với không gian bộ nhớ của hạt nhân nền).
3.1.1 Vá và biên dịch hạt nhân

(Nếu bạn dùng UML ở chế độ theo dõi luồn - thread tracing mode - thì bước này không cần thiết)

Các bước tiến hành cài đặt:

Tải về mã nguồn của hạt nhân linux từ http://www.kernel.org, chúng ta cần phải lựa chọn phiên bản có khả năng làm việc tốt với UML, trong bài viết này chúng ta sử dụng phiên bản linux-2.6.8.1 (hay còn được gọi là vanilla kernel 2.6.8.1).

# cd ~/kernel/
# wget
ftp://ftp.us.kernel.org/pub/linux/kernel/v2.6/linux-2.6.8.1.tar.bz2

Tải bản vá SKAS cho hạt nhân nền. Chúng ta có thể tải về từ trang tải về của dự án UML. Tuy nhiên, bản vá này có thể tải về từ trang tải về của tác giả - trang này được cập nhật thường xuyên hơn. Với linux-2.6.8.1 chúng ta sử dụng bản vá mới nhất host-skas3-2.6.7-v5.patch, mặc dù đây là bản vá cho hạt nhân linux-2.6.7 nhưng nó vẫn làm việc tốt với hạt nhân linux-2.6.8.1:

# wget http://www.user-mode-linux.org/~blaisorblade/patches/host-skas3-2.6.7-v5.patch

Xả nén vào nới thích hợp. Thông thường mã nguồn của hạt nhân được đặt trong /usr/src, tuy nhiên nếu chúng ta muốn biên dịch hạt nhân bằng tài khoản thông thường, chúng ta có thể chọn một vị trí mà tài khoản đó có quyền ghi, ở đây chúng ta xả nén vào ~/kernel:

# tar jxvpf linux-2.6.8.1.tar.bz2

Tiến hành vá hạt nhân vanilla kernel linux-2.6.8.1:

# cd linux-2.6.8-1
# patch -p1 --dry-run < ../host-skas3-2.6.7-v4.patch
# patch -p1 < ../host-skas3-2.6.7-v4.patch


Cấu hình hạt nhân môi trường nền, quá trình được tiến hành thông thường tuy nhiên cần phải nhớ kích hoạt tính năng hỗ trợ /proc/mm trong mục "Processor type and features":

# make mrproper
# make menuconfig
# make all


(Chúng ta cũng có thể sử dụng các công cụ xconfig hoặc menuconfig)

Tiến hành cài đặt hạt nhân mới biên dịch vào hệ thống:

# su
# make modules_install
# mount /boot
# make install
# vi /boot/grub/grub.conf
(chỉnh lại cấu hình grub)

(Tùy vào từng môi trường/cá nhân mà các bước tiếng hành có thể tùy biến)
3.1.2 Cài đặt công cụ của UML Linux

Rất nhiều đặc điểm của hạt nhân UML cần được hỗ trợ bởi các chương trình chạy ở không gian người dùng (user space) của môi trường nền. Do vậy một số công cụ trợ giúp được xây dựng và phân phối trên trang chủ của UML. Người dùng cần phải tải về và cài đặt nhưng công cụ này trong môi trường nền. Những chương trình này bao gồm:

1. port-helper - được sử dụng bởi consoles để kết nối tới xterms hoặc ports
2. tunctl - Công cụ cấu hình dùng để thiết lập và xoá các thiết bị TAP
3. uml_net - Setuid binary chương trình tự động cấu hình thiết bị tap
4. uml_switch - bộ chuyển đổi ảo, sử dụng cho daemon transport

Lưu ý rằng mỗi bản vá của hạt nhân UML sẽ yêu cầu một phiên bản phân phối tương ứng của các công cụ uml. nếu bạn không theo dõi mailing lists,thì phải đảm bảo là bạn sử dụng phiên bản phát hành mới nhất nếu bạn gặp các vấn đề với hạt nhân UML thì cũng cần lưu ý tới vấn đề tương thích giữa công cụ trợ giúp và hạt nhân UML.

Tải về, biên dịch và cài đặt công cụ uml_utilities:

# wget http://ovh.dl.sourceforge.net/sourceforge/user-mode-linux/uml_utilities_20040406.tar.bz2
# tar jxvpf uml_ultilities_20040406.tar.bz2
# cd tools
# make && make install


3.2 Biên dịch và cài đặt "chương trình hạt nhân" UML
3.2.1 Tải về và tạo mã nguồn UML

Xả nén mã nguồn của hạt nhân vanilla linux-2.6.8.1 vào một vị trí khác:

# mkdir uml-2.6.8.1
# cd uml-2.6.8.1
# tar jxvpf ../linux-2.6.8.1.tar.bz2


Tải về bản vá UML mới nhất của dự án UML Linux:

# wget http://ovh.dl.sourceforge.net/sourceforge/user-mode-linux/uml-patch-2.6.8.1-1.bz2

(Người dùng nên vào trang tải về của dự án UML Linux để chọn một mirror gần nhất)

Và chúng ta cũng cần một bản vá nhỏ điểu chỉnh hệ thống tmpfs, bản vá này là cần thiết cho chương trình hạt nhân UML.

Để có mã nguồn của chương trình UML linux, Chúng ta tiến hành vá lần lượt từng bản vá:

# cd linux-2.6.8.1
# bzcat ../uml-patch-2.6.8.1-1.bz2 | patch -p1 --dry-run
# bzcat ../uml-patch-2.6.8.1-1.bz2 | patch -p1
# patch -p1 --dry-run < ../tmpfs.patch
# patch -p1 < ../tmpfs.patch


(khi vá bản vá tmpfs.patch chúng ta sẽ gặp một sỗ trục trặc, nhưng đơn giản là bỏ qua và tiếp tục tiến hành)
3.2.2 Tiến hành cấu hình và biên dịch chương trình hạt nhân UML

Để cấu hình hạt nhân uml, bạn có thể sử dụng các công cụ cấu hình thông thường như: oldconfig, menuconfig, xconfig. Tuy nhiên bạn cần chỉ rõ kiến trúc hệ thống bạn sẽ biên dịch, ở đây thay vì các kiến trúc thông thường: x86, ia64,.. . Bạn cần phải chỉ rõ kiến trúc biên dịch là "User Mode" thông qua tham số chỉ thị "ARCH=um".

# make ARCH=um xconfig

Quá trình biên dịch hạt nhân uml được tiến hành với tham số chỉ thị "ARCH=um" và mục tiêu biên dịch là "linux" thay vì bzImage, bzdisk,...:

# make ARCH=um linux

Quá trình biên dịch này sẽ cho kết quả là một tập tin nhị phân trong thư mục chính của mã nguồn hạt nhân uml:

# ll
........................
-rwxr-xr-x 1 tuanndh users 25M Thg 10 7 07:27 linux
........................


đây chính là chương trình hạt nhân uml, cùng với các tài nguyên "ảo" chương trình này sẽ đem tới cho bạn một môi trường uml linux mới. Như bạn thấy tập tin này có kích thước khá lớn, bạn có thể giảm nhỏ kích thước của tập tin này:

# strip linux
# ll
........................
-rwxr-xr-x 1 tuanndh users 3,0M Thg 10 7 07:29 linux
........................

Để thuận lợi trong sử dụng, bạn nên chép tập tin này vào một thư mục có trong biến môi trường $PATH của bạn:

# echo $PATH
/bin:/usr/bin:/usr/local/bin:/opt/bin:~/bin:
# copy linux /usr/local/bin


4. Khởi tạo môi trường UML
4.1 Khởi động môi trường UML

Để khởi tạo môi trường bạn cần phải có một hệ thống tập tin gốc, hệ thống tập tin gốc có thể là 1 phân vùng trên đĩa cứng của bạn hoặc là một tập tin ảnh. Hệ thống tập tin gốc này là một bản hoàn chỉnh của một hệ thống tập tin của một phiên bản linux, Tại trang tải về của dự án uml sẵn có một số tập tin ảnh của một số phiên bản linux, bạn có thể tải về và sử dụng. Chúng ta sẽ trở lại vấn đề này trong phần "Xây dựng hệ thống tập tin gốc".

Việc khởi động được thực hiện bằng chương trình hạt nhân uml - lệnh linux - bạn cần chỉ rõ hệ thống tập tin gốc, thông qua tham số ubd0=your_root_fs. Ngầm định, nếu bạn không chỉ rõ tham số này chương trình hạt nhân linux sẽ thử sử dụng tập tin root_fs nếu nó có mặt trong thư mục hiên tại.

Để minh hoạ cho quá trình khởi tạo môi trường UML, chúng ta sử dụng hệ thống tập tin gốc của Debian Linux sẵn có tại trang tải về của dự án UML:

# wget http://ovh.dl.sourceforge.net/sourceforge/user-mode-linux/Debian-3.0r0.ext2.bz2
# bzip2 -d Debian-3.0r0.ext2.bz2

Ngoài hệ thống tập tin gốc, giống như môi trường linux thông thường chúng ta cần phải có một không gian tráo đổi (swap space), chúng ta có thể tạo không gian tráo đổi có kích thướng 500MB như sau:

# dd if=/dev/zero of=swap_fs seek=500 count=1 bs=1M
# mkswap -f swap_fs


Tới đây chúng ta đã có thế khởi động môi trường uml linux với hệ thống tập tin gốc là tập tin Debian-3.0r0.ext2 như sau:

# linux ubd0=Debian-3.0r0.ext2 ubd1=swap_fs xterm=mlterm mem=128MB

Đăng nhập với tài khoản root (mật khẩu trống) và dạo một vòng trong môi trường mới của chúng ta smilie.

Lưu ý: để khởi động môi trường uml thành công, bạn phải đảm bảo là phân vùng /tmp (nếu có) của bạn không được gắn kết (mount) với tuỳ chọn "noexec".

Các tham số của chương trình hạt nhân uml có thể tham khảo trong phần trợ giúp ( #linux--help), dưới đây là một số lựa chọn thông dụng:

mem
mem=size - Chỉ rõ số bộ nhớ phân bổ cho môi trường uml. Kích thước được chỉ rõ bởi một số theo sao bới một trong các ký tự 'k' 'K' 'm' 'M' (tương ứng với Kilobytes và MegaBytes).

ubd
ubdX=filename - Chỉ rõ việc ấn định một thiết bị (trong môi trường uml) với một tập tin (trong môi trường nền). Thông thường tập tin này chứa một hệ thông thống tập tin, nhưng cũng không nhất thiết phải vậy. các thiết bị để gắn vào vùng tráo đổi của môi trường uml được ấn định bằng một tập tin có khuôn dạng của không gian tráo đổi tráo đổi. Chỉ số X phải nằm trong khoảng từ 0 tới 7.

xterm
xterm=trình đầu cuối, tiêu đề, tuỳ chọn - cho phép chúng ta chỉ rõ trình thiết bị đầu cuối nào sẽ được "chương trình hạt nhân" sử dụng trong môi trường Xwindow cho trình gỡ rối, consoles, và serial lines. Bạn có thể chọn một trong những trình thiết bị đầu cuối ưa thích của bạn như: xterm, mlterm, aterm, rxvt,...

4.2 Cấu hình mạng cho môi trường UML

Một bước khá quan trọng trong việc khởi tạo môi trường UML là cấu hình hệ thống mạng. Trong tài liệu về thiết lập mạng cho môi trường UML chỉ rõ năm loại kênh giao vận mạng có thể thiết lập để truyền thông giữa môi trương UML và các máy khác. Sau đây chúng ta sẽ thiết lập một kênh giao vận mạng dựa trên trình điều kiển TUN/TAP sẵn có trong hạt nhân linux.

TUN/TAP là trình điều kiển cho phép các chương trình chạy ở không gian người dùng có thể nhận/truyền gói tin, trình điều kiển này có thể đưọc xem như là một thiết bị ethernet (hoặc Point-to-Point) đơn giản, thiết bị này thay vì truyền/nhận gói tin từ đường truyền vật lý thì sẽ truyền/nhận gói tin từ một chương trình chạy ở không gian người dùng. Để sử dụng bạn phải kích hoạt trình điều kiển này trong khi cái cấu hình hạt nhân nền:

Code:
[*] Network device support
..........................
<M> Universal TUN/TAP device driver support
Ngoài ra bạn phải kích hoạt tính năng MASQUERADE trong cấu hình netfilter của hạt nhân linux:
Networking -->
IP: Netfilter Configuration -->
IP tables support -->
Full NAT -->
<M> MASQUERADE target support


Tại thời điểm này chúng ta có thể khởi động môi trường uml linux với hệ thống mạng đã sẵn sàng:
Để đơn giản, trong phần này chúng ta sẽ khởi tạo một môi trường UML Debian Linux có địa chỉ mạng là 192.168.0.100, nằm cùng mạng con (subnet) với môi trường nền 192.168.0.4

# linux ubd0=Debian_root_fs ubd1=swap_fs xterm=mlterm eth0=tuntap,,,192.168.0.4
...........................


Sau khi đăng nhập vào môi trường uml - Debian, chúng ta tiến hành kích hoạt giao diện mạng eth0:

# ifconfig eth0 192.168.0.200 up

Thử nghiệm giao diện mạng bằng cách ping tới môi trường nền:

# ping -c 2 192.168.0.4
PING 192.168.0.254 (192.168.0.4): 56 octets data
64 octets from 192.168.0.4: icmp_seq=0 ttl=255 time=0.8 ms
64 octets from 192.168.0.4: icmp_seq=1 ttl=255 time=0.6 ms

--- 192.168.0.4 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.6/0.7/0.8 ms

Cấu hình gateway cho môi trường uml - Debian:

# route add default gw 192.168.0.4

Kiểm tra bảng định tuyến:

# netstat -rn
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
192.168.0.0 0.0.0.0 255.255.255.0 U 40 0 0 eth0
0.0.0.0 192.168.0.4 0.0.0.0 UG 40 0 0 eth0


Chỉnh sửa cấu hình DNS:

# vi /etc/resolv.conf
# cat /etc/resolv.conf
nameserver 192.168.0.1
search mshome.net


Thử hệ thống mạng:

Code:
# ping -c 2 www.gentoo.org
PING www.gentoo.org (207.170.82.202): 56 octets data
64 octets from 207.170.82.202: icmp_seq=0 ttl=240 time=119.6 ms
64 octets from 207.170.82.202: icmp_seq=1 ttl=240 time=92.0 ms
--- www.gentoo.org ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 92.0/105.8/119.6 ms


Tất nhiên, sau khi cấu hình và thử nghiệm thành công, chúng ta cần phải tiến hành cấu hình theo cách chuẩn tắc của phiên bản linux sử dụng trong môi trường UML.
5. Xây dựng hệ thống tập tin gốc.
5.1 Fedora
5.2 Slackware

Người dùng có thể cái đặt một phiên bản của Slackware Linux trong môi trường ảo, trước hết chúng ta cần phải có đĩa cài đặt Slackware Linux, chúng ta có thể tải về tập tin iso từ trang chủ của Slackware Linux hoặc từ một mirror. Do có một số vấn đề về dò tìm phần cứng, đĩa cài đặt của Slackware không nhận được đĩa cứng ảo cũng như cdrom; do vậy để cài đặt Slackware bạn cần chỉnh sửa tập tin khởi động của đĩa cài đặt Slackware linux, tuy nhiên bạn có thể đơn giản là tải về tập tin initrd từ đây và tiến hành cài đặt:
6. Kết luận
7. Phụ lục
A. Các thuật ngữ sử dụng trong tài liệu

Hệ thống tập tin gốc (root filesystem)

Hạt nhân nền (host kernel)
Là hạt nhân được biên dịch để chạy hệ nền, nó là hạt nhân linux thông thường được vá thêm miếng vá SKAS
Chương trình hạt nhân uml, hạt nhân uml (user mode linux kernel)

Trang tải về (Download page)

Không gian người dùng (user space)

Không gian tráo đổi (swap space)

Gắn kết (mount)

B. Tài liệu tham khảo và tài nguyên

[1] Trang chủ của dự án User-Mode-Linux.

[2] User-Mode-Linux Howto.

[3] User-Mode-Linux User's mailist archive.

[4] Trang chủ của cộng đồng User-Mode-Linux.

[5] DatuX Use-Mode-Linux with Slackware 9.1 HOWTO.

[6] Hệ thống tập tin gốc và công cụ cho Slackware 9.1.

[7] Hệ thống tập tin gốc của Fedora Core 2 và RedHat 9.


- Nguyễn Đặng Hoàng Tuân
Qmail as a Mail Gateway - Phần 4

Chi tiết các hồ sơ cần điều chỉnh cho qmail cho vấn đề tối ưu hoá.

4.2 Danh mục các hồ sơ trong “qmail-control” cần thiết cho Qmail relay server:
Ngoại trừ bạn dùng Qmail để thiết lập một mail server hạng nặng và muốn xử dụng tối đa chức năng của mỗi chương trình trong Qmail suite, bạn sẽ hiếm khi phải xử dụng tới trọn bộ 28 hồ sơ ở trên. Với trường hợp Qmail là một relay server, bạn không cần quá một chục hồ sơ trong nhóm các hồ sơ thuộc “qmail-control”. Sau đây là danh sách các hồ sơ tôi dùng cho “qmail-control” và nội dụng của từng hồ sơ để giúp bạn hình dung dễ dàng hơn chức năng của từng hồ sơ:

4.2.1 Hồ sơ “me” thuộc qmail-send:
- Hồ sơ “me” là khởi điểm cho mọi hoạt động của Qmail, thiếu nó Qmail sẽ không chạy. Hồ sơ này được tạo ra từ bước 2.4.4 khi bạn chạy lệnh ./config để thiết lập hostname cho mail server của bạn. Hồ sơ này chỉ có một dòng chỉ định cho domain entry của mail relay server.

- Nội dung của hồ sơ này có dạng: mail.mydomain.com, trong đó: mail là hostname của mail relay server, mydomain.com là fully qualified domain name bạn có.

4.2.2 Hồ sơ “locals” thuộc qmail-send:
- Hồ sơ này dùng để chỉ định các địa chỉ e-mail được xem là “local” đối với mail relay server. Nếu không có entry nào trong “locals” thì qmail-send cho rằng chỉ có mỗi host trong “me” thuộc local. Trường hợp dùng Qmail như một mail relay server không cần “locals” nữa, nếu có, hồ sơ “locals” này có một dòng chỉ định y hệt như “me” vậy thôi.

4.2.3 Hồ sơ “concurincoming”(hay còn gọi là concurrencylocal) thuộc qmail-send:
- Hồ sơ này ấn định số lượng mail được chuyển giao cùng một lúc. Default có giá trị là 10, với giá trị này, Qmail đủ sức chuyển giao mail cho một server cỡ nhỏ đến cỡ trung. Nên tránh dùng giá trị quá nhỏ để đề phòng trường hợp bị “denial attack”. Tôi dùng giá trị là 20 cho một văn phòng cỡ 100 nhân viên (khoảng 140 e-mails tổng cộng, bao gồm các e-mail chung cho từng nhóm nhân viên).

4.2.4 Hồ sơ “defaultdomain” thuộc qmail-inject:
- Hồ sơ này dùng như một dạng bản mẫu, nếu vì một lý do gì đó mail client không dùng trọn bộ tên người dùng + tên domain như một e-mail thông thường ví dụ: me@mycom.com mà chỉ có tên người dùng là me thì “defaultdomain” được qmail dùng để “gắn” thêm cái đuôi tên domain trước khi nó gởi mail ra ngoài. Nếu qmail không tìm thấy “defaultdomain” nó sẽ tự động dùng entry trong hồ sơ “me” ở trên. Hồ sơ này không quá cần thiết, sự hiện diện của nó thường để loại trừ trường hợp mail client không gởi “sender” đúng và dùng để giao chuyển giữa các mail account trong cùng mail relay server.

- Hồ sơ này chỉ đơn giản có 1 entry là domain name của bạn, ví dụ: mycompany.com

4.2.5 Hồ sơ “queuelifetime” thuộc hồ sơ qmail-send:
- Hồ sơ này dùng để chỉ định thời gian (tính theo đơn vị giây) mail được giữ trong mail queue (vì lý do gì đó không chuyển gởi được) trước khi bị xoá. Khi mail đợi trong queue đến hạn cuối của “queuelifetime”, qmail sẽ chuyển gởi mail đó lần cuối trước khi thực sự xoá nó khỏi mail queue (nếu mail này vẫn không thể chuyển giao được).

- Giá trị default của hồ sơ “queuelifetime” là 604800 giây (tương đương với 1 tuần lễ). Giá trị này tùy thuộc vào môi trường của bạn mà thiết lập cho thích hợp. Ví dụ, mail relay server của bạn chỉ phục vụ cho một số ít người và thuộc mạng “chậm” thì nên thiết kết giá trị của “queuelifetime” cao hơn một tí để mail có cơ hội được chuyển giao trong trường hợp mạng bi nghẽn (thật ra queuelifetime cho 1 tuần là rất lâu). Tôi chọn giá trị 172800 (khoảng 48 giờ) vì mail relay server trong trường hợp tôi thiết kế phục vụ cho khá nhiều người và đường dẫn khá tốt.

4.2.6 Hồ sơ “badmailfrom” thuộc qmail-smtpd:
- Hồ sơ này là một trong những hồ sơ tiện dụng của qmail, nó dùng để chứa các e-mail bạn không cho phép qmail server nhận vào (nó thuộc qmail-smtpd nên thuộc phần “nhận”). Dù phương pháp chống “bom thư” hay spam này không được linh động cho lắm nhưng nó là một trong những chức năng chứng tỏ sự quan tâm của ông Bernstein khi viết Qmail trong vấn đề chống spam.

- Hồ sơ này chứa các e-mail hoặc trọn bộ domain bạn không muốn nhận bất cứ tin tức gì, mỗi e-mail phải nằm trên một dòng. Ví dụ:
spamboy@spamhouse.com (không nhận mail từ 1 địa chỉ này)
@spamhouse.com (không nhận mail từ trọn bộ domain này).

- Các phương pháp phòng chống “bom thư” linh động hơn sẽ được đi sâu hơn trong những phần tới.

4.2.7 Hồ sơ “rpcthosts” thuộc qmail-smtpd:
- Hồ sơ rcpthosts là một hồ sơ hết sức quan trọng đối với qmail-smtpd, nhất là cho một mail relay server. Hồ sơ này cung cấp dữ kiện cho qmail-smtpd, daemon này thay mặt các hosts và domains nào muốn nhận chuyển mail. Ví dụ bạn có 2 mail server trong LAN nội bộ có tên là domain1.com và domain2.com, hồ sơ rcpthosts phải có dữ kiện của 2 mail server này, nếu không, mail từ bên ngoài vào 2 server này sẽ bị qmail-smtpd từ chối chuyển nhận vào bên trong. Nên nhớ phải có ít nhất là một dữ kiện cho chính mail relay server không thì sẽ không có mail nào được vào (ngay cả cho chính mail relay server).

- Hồ sơ rcpthosts chứa các dữ kiện theo mặc định mỗi dòng một host/domain. Hồ sơ này có cấu trúc tương tự như sau:
mail.mydomain.com (mail là hostname của mail relay server và domain.com là fully qualified domain name. Ðây chính là dữ kiện thiết yếu và đầu tiên cho mail relay server).

exchange1.mydomain.com (exchange1 là hostname của MS exchange thuộc LAN nội bộ. Tất nhiên DNS của bạn (hoặc của ISP cung cấp cho bạn) phải có entry cho host exchange1 này và mail relay server phải biết được địa chỉ (bên trong) của host exchange1).

exchange2.mydomain.com (tương tự như exchange1 và nhiều mail server bên trong theo cấu trúc này nếu cần).

mydomain.net (giả sử bạn có thêm một domain name khác với đuôi .net và một trong những mail server thuộc LAN nội bộ đã thiết lập để nhận mail cho domain.net này, entry domain.net trong rcpthosts cần thiết để mail relay server biết domain.net được phép nhận mail từ bên ngoài thông qua mail relay server).

mail.myfriend.com (giả sử một người bạn có domain name là myfriend.com và anh ta bị trục trặc với mail server. Bạn có thể “tạm thời” giúp anh ta bằng cách cho phép mail relay server của bạn nhận các mail thuộc myfriend.com vào host mail để anh ta có thể dial in host mail này mà lấy mail (chẳng hạn). Kỹ thuật này còn có cái tên là “chuyển nhận có lựa chọn” (selective relay policy).

- Sự hiện diện của hồ sơ rpcthosts là một trong những đặc thù của qmail trong vấn đề phòng chống open-relay. Chỉ có những host/domain hiện diện trong rpcthosts được phép nhận mail từ mai relay server của bạn. Ðiều này có nghĩa, một người ở hostA (mang IP address xx.xx.xx.xx) có ý định dùng mail relay server của bạn để chuyển tới một mail server nào đó (có IP address zz.zz.zz.zz) ngoài giới hạn quy định của rpcthosts tuyệt đối không thể được. Phần “Thử nghiệm sau khi cài đặt” trong phần 6 sẽ đi xuyên qua một số bước kiểm tra cụ thể.

4.2.8 Hồ sơ “smtpgreeting” thuộc qmail-smtpd:
- Hồ sơ này trên mặt chức năng gần như không cần thiết nhưng trên mặt tâm lý nó mang ít nhiều tính chuyên nghiệp (professionalism) sự sắp xếp và hiện diện của một mail relay server trên Internet. Hồ sơ smtpgreeting không chứa gì ngoài một giòng thông điệp “chào mừng” những ai đến mail relay server này (bao gồm sự trao đổi giữa các mail relay servers và ngay cả các tay chuyên dùng telnet hoặc các loại dụng cụ thăm dò mail server lỗ hổng open-relay).

- Hồ sơ này tùy thuộc vào tinh thần của bạn mà hình thành một lời “chào mừng” đúng mức. Tôi đã từng thấy một số mail relay server có lời “chào mừng” khá thách thức chẳng hạn như: “Kiddies, this server is not your playground. Stay away or stick around for a challenge” (Tạm dịch: Mấy ông nhóc con, server này không phải là chỗ chơi của các ông. Tránh xa hay nhào vô mà thử thách). Dù cơ chế làm việc của qmail mang nặng tính bảo mật không có nghĩa là nó hoàn hảo và không cách gì phá được. Một thông điệp mang tính hoà nhã và nghiêm túc thường có tác dụng tốt đẹp hơn nhiều (bạn sẽ phải hối hận nếu lỡ buông lời thách thức trong thế giới bảo mật).

- Tôi giả định nên dùng một thông điệp ngắn gọn và rõ ràng như sau: “Welcome to company ABC mail server and have a nice time”. Xét cho cùng, bạn không muốn tạo nên phiền toái mà làm gì. Nếu một tay chuyên tìm open-relay thất vọng khi “đụng” phải mail server của bạn đã là một thành tựu; một thông điệp nhẹ nhàng sẽ giúp cho anh ta quyết định “để yên server” của bạn. Nên nhớ rằng, dù mail relay server của bạn không open-relay, những kẻ muốn phá vẫn có thể “flood” server của bạn được, tổn thất ở chỗ người dùng trong nội mạng không có cơ hội gởi và nhận mail trong khi mail relay server bị “flood”.

4.2.9 Hồ sơ “smtproutes” thuộc qmail-remote:
- Ðối với một mail server bình thường (qmail được thiết kế để trực tiếp nhận / gởi e-mail từ clients bên trong nội mạng và các mail server ngoại mạng), hồ sơ smtproutes không cần thiết. Tuy nhiên, để một qmail relay server làm việc, hồ sơ này không thể thiếu được. Hồ sơ này tương tự hồ sơ rcpthosts ở trên chỉ có thêm giá trị địa chỉ IP đi sau mỗi host (mail server trong nội mạng). Các IP của mail server trong nội mạng giúp mail relay server xác định được mail sẽ được chuyển về đâu và mỗi mail server nội mạng chịu trách nhiệm phân phát cho các clients theo đúng quy định. Ðây chính là cốt yếu khác biệt giữa một mail server bình thường và một mail relay server.

- Hồ sơ smtproutes có cấu trúc như sau: hostname.domain.com:[IP_ADDRESS]. Giả sử hai exchange mail servers trong nội mạng có tên là exchange1 (IP: 192.168.1.100) và exchange2 (IP: 192.168.1.200), dữ kiện được quy định trong smtproutes sẽ như sau:
exchange1.mydomain.com:[192.168.1.100]
exchange2.mydomain.com:[192.168.1.200]
mail.myfriend.com:[192.168.1.100] (dùng exchange1 để “nhận dùm” mail cho người bạn, tất nhiên exchange1 đã được thiết kế để tiếp nhận mail cho domain myfriend.com).

4.3 Mail server trong nội mạng (MS Exchange)
- Tôi chọn MS Exchange như một mail server nội mạng không phải vì khả năng chuyên biệt của MS Exchange mà vì tính phổ biến của nó trong môi trường văn phòng thường xử dụng MS Back Office. Cách điều chỉnh cho các loại mail server khác có những điểm tương tự như MS Exchange về phương diện mail đi ra / vào (thay vì đi vào trực tiếp từ mail server của ISP bạn dùng, MS Exchange hoặc mail server nào đó có thể đi vào từ Qmail mail relay server).

- Trong phần điều chỉnh Connections của MS Exchange, bạn chọn “Internetmail Service Properties”. Trong phần điều chỉnh này có một “tab” gọi là “Connection”, trong đó bạn có thể điều chỉnh hai dữ kiện để MS Exchange biết phải chuyển nhận mail từ Qmail mail relay server ở đâu:
Transfer mode chọn: “Inbound and Outbound”
Message delivery chọn: “Forward all messages to host” và IP của host chính là IP của mail relay server.

- Nếu Exchange server của bạn chịu trách nhiệm quản lý mail cho nhiều domain, bạn phải điều chỉnh “Reroute incoming SMTP mail” cho thích ứng trong “tab” Routing của “Internet Mai Properties. Những thiết lập này mang tính cụ thể cho từng loại mail server. Bạn nên tham khảo thêm tài liệu của mỗi loại mail server để đi sâu vào các chi tiết.
- Nguyên tắc làm việc trước và sau khi có mail relay server là:
* Các mail server thuộc nội mạng (hoặc DMZ) không còn truy cập trực tiếp đến mail server của ISP mà truy cập vào Qmail relay server.
* Cơ chế mail relay hoàn toàn do qmail server nắm giữ.
* Qmail relay server có thể được nằm trong DMZ hoặc nội mạng hoặc đằng sau một router miễn sao router + firewall có thể “foward” các thông tin từ bên ngoài vào mail relay server. Quyết định đặt để qmail relay server tùy thuộc vào cấu trúc của từng network.

Qmail as a Mail Gateway - Phần 4 (cuối)

Chi tiết nâng cao - vấn đề bom thư với qmail.
5. Ðiều chỉnh sau khi cài đặt

Trước đây, khi Internet còn giới hạn (chỉ phổ biến giữa các trường đại học và các nhóm nghiên cứu và rất ít người dùng bình thường), mail là một phương tiện tuyệt vời để liên lạc và trao đổi. Tính thương mại hoá hầu như chưa có cho đến khi loạt “SPAM” đầu tiên xuất hiện đã biến Internet mail trở nên một vấn đề gần như nan giải đối với các loạt mail “vô chủ” chuyên để quảng cáo.

Có hai trường hợp thường xảy ra trong vấn nạn “SPAM” đó là:
- Bị biến thành phương tiện để “SPAM” những nạn nhân khác nếu mail server không được điều chỉnh và kiểm soát đúng mức (bị relay).

- Bị “SPAM” (bom thư).

5.1 Chiến thuật relaying điện thư (để không biến mail server của mình trở thành phương tiện để “SPAM”
5.1.1 Tại sao cần relay?
Như đã đề cập đến trong phần 3.5 (Bộ quản trị SMTP Access Control), có những trường hợp bạn cần cho phép mail gateway của mình relay mail vì lý do nào đó (chuyển nhận mail dùng cho công ty bạn hoặc mail server của bạn dùng để relay mail cho nhiều domain khác nhau như một mail server của ISP). Nói một cách ngắn gọn, khả năng “mail relaying”của một mail server A là khả năng tiếp nhận mail từ host X và chuyển gởi mail này đến host Y hoặc những host nào đó trong chế độ định sẵn mà mail server phải đảm nhiệm.

5.1.2 Chuyện gì xảy ra nếu không relay?
Nếu mail gateway của bạn chỉ dành phục vụ cho một domain riêng của bạn thì vấn đề relay không còn cần thiết nữa và quyết định hoàn toàn không relay là cách an toàn nhất để ngăn ngừa trường hợp mail gateway của bạn bị biến thành một phương tiện để SPAM.

5.1.3 Cho phép relaying theo lựa chọn
Trong phần 3.5 đã đi sâu vào chi tiết sắp xếp cho phép relay một cách chọn lọc, một trong những variables cần phải chú tâm đến là: allow,RELAYCLIENT. Nên xem xét một cách kỹ lưỡng các giá trị “RELAYCLIENT” để nắm chắc bạn đã không cho phép một “client” nào đó được phép relay vì sơ ý.

5.1.4 Thử nghiệm relaying bằng tcprulescheck
Trong nhóm “ucspi-tcp” có một chương trình gọi là tcprulescheck cho phép bạn kiểm tra các “luật” relay trước khi ứng dụng Qmail như một mail relay server thực sự. tcprulescheck dùng 2 variables của môi trường để kiểm tra các “luật” relay, đó là: TCPREMOTEIP và TCPREMOTEHOST. Bạn có thể thay đổi các variables này cho quy trình kiểm tra.

Sau đây là một ví dụ đơn giản quy trình kiểm tra các “luật” relay bằng tcprulescheck. Giả sử chúng ta dùng ví dụ qmail-rules.txt từ phần 3.5.

Code:
127.:allow,RELAYCLIENT=””
192.168.1.:allow,RELAYCLIENT=””
10.10.10.50:allow,RELAYCLIENT=””
<a href="mailto:spamboy@spamhouse.com">spamboy@spamhouse.com</a>:deny
badhost.net:deny
.:deny


Chúng ta thử “cat” qmail-rules.txt và “pipe” nó xuyên qua chương trình tcprules để tạo ra hash của các rules thuộc “qmail-rules.txt” (nên nhớ smtpd daemon dùng hash của qmail-rules.txt, đó là hồ sơ tcp.smtp.cdb, nó không bao giờ dùng nguyên bản cleartext qmail-rules.txt):
# cat /etc/smtprules/qmail-rules.txt | tcprules /etc/tcp.smtp.cdb

Hash của các rules được chứa trong hồ sơ tcp.smtp.cdb và chúng ta sẽ dùng hồ sơ này để kiểm tra các “luật” relay.

a. Lệnh $ tcprulescheck /etc/tcp.smtp.cdb sẽ cho kết quả:
rule:
deny connection
Trường hợp ở trên tcprulescheck dùng giá trị mặc định (default) của “qmail-rules.txt” đó là .:deny. Bất cứ truy cập nào vào mail relay server của bạn, đầu tiên nó sẽ dùng giá trị mặc định để “deny” trước và sau đó dựa trên IP hoặc hostname của nơi gởi mail mà định đoạt “số phận” của mail này.

b. Thử lệnh trên một lần nữa trước khi chỉnh variable TCPREMOTEIP là 10.10.10.50 như đã cho phép trong “qmail-rules.txt” ở trên:
$ TCPREMOTEIP=10.10.10.50 ; export TCPREMOTEIP
$ tcprulescheck /etc/tcp.smtp.cdb sẽ cho kết quả:
rule: 10.10.10.50:
set environment variable RELAYCLIENT=
allow connection

Ở trên cho thấy qmail chấp nhận TCPREMOTEIP là 10.10.10.50 là vì IP này đã thuộc trong danh sách qmail-rules.txt và được thiết lập ở chế độ allow,RELAYCLIENT nên tcprulescheck trả lời: allow connection.

c. Thử lệnh trên với TCPREMOTEIP mang giá trị khác, giả sử như badhost.net có IP là 172.173.174.175 (được thiết lập ở chế độ deny trong qmail-rules.txt)
$ TCPREMOTEIP=172.173.174.175 ; export TCPREMOTEIP
$ tcprulescheck /etc/tcp.smtp.cdb sẽ cho kết quả:
rule: badhost.net:
deny connection

Ở trên cho thấy Qmail từ chối không nhận mail muốn được chuyển nhận đến server 172.173.174.175 (IP của badhost.com trong ví dụ này) vì địa chỉ này được ấn định là deny.

Cứ như vậy, bạn đi xuyên qua mỗi “rule” trong qmail-rules.txt để kiểm tra chức năng relay của các rules.

5.1.5 Thử nghiệm relaying bằng “telnet”
Phương pháp dùng “telnet” để truy cập vào một mail server ở port 25 (SMTP port) có lẽ là một phương pháp cổ điển và phổ biến nhất để kiểm tra tính năng “relay” của nó. Ðây cũng là một trong những phương pháp các tay chuyên tìm kiếm “open relay” để có thể SPAM, tất nhiên không bằng cách “telnet” từng mail server mà bằng cách “tự động hoá” qua một dạng scripting nào đó để có thể đi xuyên qua hàng loạt mail server trong một khoảng thời gian ngắn.

Ở đây tôi sẽ đưa ra hai ví dụ đơn giản để kiểm tra tính năng “relay” của mail server của bạn. Ðòi hỏi đơn giản chỉ cần có chương trình “telnet” trong máy. Tính năng “relay” dựa trên hồ sơ “rcpthosts” (trong phần 4.2.7) có các giá trị như sau:
mail.mydomain.com
exchange1.mydomain.com
exchange2.mydomain.com
mydomain.net
mail.myfriend.com

Khởi động telnet trên một command prompt (Windows hoặc *nix tùy chọn). Giả sử mail gateway server của tôi có địa chỉ là 192.168.1.200 với hostname là mail.mydomain.com chẳng hạn, tôi sẽ làm các bước như sau:

Code:
1 telnet 192.168.1.200 25
2 220 My company mail server - Welcome ESMTP
3 HELO
4 250 My company mail server – Welcome
5 MAIL FROM: <spamboy@spamhouse.com>
6 250 ok
7 RCPT TO: <reciepient@someonecompany.com>
8 553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)


Dòng 1: Dùng telnet với các thông số là IP 192.168.1.200 và SMTP port 25.

Dòng 2: Nếu mail server của tôi đang hoạt động bình thường, tôi sẽ nhận được lời chào (bạn còn nhớ hồ sơ “smtpgreeting” trong phần 4.2.8? đây chính là lời chào lấy từ hồ sơ “smtpgreeting” này).

Dòng 3: Tôi thử lệnh HELO, một lệnh căn bản của SMTP.

Dòng 4: Mail server của tôi sẽ trả lời với thông điệp lấy từ “smtpgreeting”.

Dòng 5: Tôi “mạo danh” là spamboy@spamhouse.com qua lệnh MAIL FROM:

Dòng 6: Mail server trả lời 250 ok bởi vì tôi chưa cho mail server của tôi biết là người nhận sẽ là ai và người nhận thuộc domain nào.

Dòng 7: Tôi dùng lệnh RCPT TO: và cho mail server biết người nhận là reciepient thuộc domain someonecompany.com; một domain không hề có trong rcpthosts.

Dòng 8: Qmail sẽ từ chối ngay lập tức.

Hãy thử kiểm tra relaying bằng telnet dùng các giá trị người nhận thuộc domain có trong hồ sơ “rcpthosts”. Quy trình này tương tự như sau:

Code:
1 telnet 192.168.1.200 25
2 220 My company mail server - Welcome ESMTP
3 HELO
4 250 My company mail server – Welcome
5 MAIL FROM: <spamboy@spamhouse.com>
6 250 ok
7 RCPT TO: <someone@mydomain.net>
8 250 ok
9 DATA
10 354 go ahead
11 From: <a href="mailto:spamboy@spamhouse.com">spamboy@spamhouse.com</a>
12 To: <a href="mailto:someone@mydomain.net">someone@mydomain.net</a>
13 Subject: a relay test
14 This is only a test for open relay
15 .
16 250 ok 1041050865 qp 12150
17 QUIT
18 221 My company mail server – Welcome
19
20 Connection to host lost.


Dòng 1 đến dòng 6: tương tự như ví dụ ở trên

Dòng 7: Lệnh RCPT TO: gởi đến người nhận thuộc domain mydomain.net, domain này có trong danh sách rcpthosts

Dòng 8: Mail server tiếp nhận và trả lời với SMTP code 250. Sở dĩ mail server tiếp nhận trong trường hợp này là vì domain mydomain.net hiện diện trong rcpthosts

Dòng 9: Lệnh DATA để báo với mail server dự định gởi thông điệp

Dòng 10: Mail server tiếp nhận và trả lời với SMTP code 354

Dòng 11 đến dòng 13: Các “message header” From, To và Subject thông thường để mail client có thể hiển thị những thông tin này

Dòng 14: Nội dung của thông điệp. Nội dung này có thể trải ra thành nhiều dòng nếu cần

Dòng 15: Dấu chấm (.) để kết thúc thông điệp

Dòng 16: Mail server trả lời kết thúc một “xuất” gởi thông điệp

Dòng 17: Lệnh QUIT dùng để dừng truy cập đến mail server bằng telnet

Dòng 18: Mail server trả lời với SMTP code 221, ngưng truy cập vào mail server thành công

Dòng 19 và dòng 20: Dòng trống trên console và thông điệp telnet báo không còn truy cập đến mail server nữa.

Ở trên bạn thấy người gởi “spamboy@spamhouse.com” vẫn có thể gởi mail đến “someone@mydomain.net” vì domain mydomain.net hiện diện trong hồ sơ “rpcthost”. Nếu trong hồ sơ “qmail-rules.txt” có dữ kiện dùng để “deny” người gởi này, chắc chắn mail ở trên không thể đi vào mail server của bạn được. Ví dụ trên một phần nào minh hoạ quan hệ giữa “qmail-rules.txt” và “rcpthosts” trên phương diện chống relay và chống spam.

Qua hai phần thử nghiệm 5.1.4 và 5.1.5 chúng ta có thể rút tỉa được một số điểm quan trọng như sau:

- Hồ sơ “qmail-rules.txt” dùng để xác định các host được phép relay và được phép dùng mail gateway để chuyển mail. Nó còn có trách nhiệm giúp Qmail quyết định mail đến và đi từ các host nào sẽ có số phận ra sao. Ðịnh nghĩa ÐẾN và ÐI ở đây có nghĩa là mail đi từ bên ngoài domain của bạn hoặc bên ngoài những domain bạn cho phép relay. Ngoài hồ sơ “badmailfrom” (xem lại trong phần 4.2.6), “qmail-rules.txt” là nơi để xác định những domains, hosts và các e-mail bạn không muốn tiếp nhận (qua phương thức :deny).

- Hồ sơ “rpcthost” dùng để xác định các domain nào được Qmail relay server giao chuyển mail. Ðiều này có nghĩa, Qmail dựa trên những dữ liệu của “rpcthosts” để tiếp nhận mail từ một nơi nào đó đến một mail server nào mà nó đã chịu trách nhiệm relay.

5.2 Chiến thuật chống bom thư với Qmail
Các bước 5.14 và 5.1.5 ở trên dùng để kiểm tra lại những lỗ hổng “relay” trên bình diện mail gateway được dùng để relay (hoặc mail gateway được làm phương tiện để spam các hòm thư). Hồ sơ “qmail-rules.txt” có thể dùng để quy định những e-mail, domains hoặc một chuỗi địa chỉ bạn không muốn nhận mail. Ðây là có thể là một cách chống bom thư nhưng thiếu tính “tự động hoá” vì bạn phải thường xuyên theo dõi, cập nhật các dữ kiện trong hồ sơ này.

Ðể nâng cao khả năng chống bom mail với tính “tự động hoá”, trong phần này chúng ta bàn về vấn đề dùng các RBL (realtime black list) database phối hợp với “qmail-rules.txt” để chống bom thư một cách hữu hiệu hơn.

Trong phần 3.4.2 trước đây, chúng ta nói đến chương trình “tcpserver” được sử dụng trong script “run” cho qmail-smtpd. Hãy xem lại đoạn script chạy “tcpserver” của phần 3.4.2:

Code:
#!/bin/sh
# concurincoming is not standard qmail control file
# it is created manually to specify the allowed concurrent incoming messages
#
QMAILDUID=`id -u qmaild`
NOFILESGID=`id -g qmaild`
MAXSMTPD=`cat /var/qmail/control/concurincoming`
if [ -z "$QMAILDUID" -o -z "$NOFILESGID" -o -z "$MAXSMTPD" ]; then
echo QMAILDUID, NOFILESGID, or MAXSMTPD is not set in
echo /var/qmail/supervise/qmail-smtpd/run
echo “Have you set qmaild UID & qmaild GID yet?”
exit 1
fi
exec /usr/local/bin/softlimit -m 6291456 \
/usr/local/bin/tcpserver -v -p -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \
-u "$QMAILDUID" -g "$NOFILESGID" 0 smtp /var/qmail/bin/qmail-smtpd 2>&1
Ở trên tcpserver chỉ dùng “tcp.smtp.cdb”, hồ sơ này được “hash” từ “qmail-rules.txt” để chống relay và bom thư theo dạng đơn giản. Cũng với cơ chế này, chúng ta có thể dùng “rblsmtpd” cùng với “tcpserver” để báo cho qmail server biết nó có trách nhiệm phải kiểm tra các mail đi xuyên qua mail gateway có thuộc dạng “SPAM” trước khi được chấp nhận. Phương thức kiểm tra bằng cách đối chiếu dữ kiện ở một trong những RBL servers. Có một số RBL database miễn phí trên internet. Có hai RBL cá nhân tôi dùng là: ordb.org và osirusoft.com (bạn có thể đọc thêm một số tin tức về RBL từ hai site này).
Cách dùng rblsmtpd trong script run của “qmail-smtpd” đơn giản như sau:
exec /usr/local/bin/softlimit -m 6291456 \
/usr/local/bin/tcpserver -v -p -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \
-u "$QMAILDUID" -g "$NOFILESGID" 0 smtp /usr/local/bin/rblsmtpd -r relays.ordb.org -r relays.osirusoft.com /var/qmail/bin/qmail-smtpd >> /var/log/qmail/rblsmtpd.log 2>&1


Chương trình rblsmtpd ở trên dùng hai tham số “relays.ordb.org” và “relays.osirusoft.com” chính là hai RBL database mà qmail phải đối chiếu mỗi khi nhận mail vào. Nếu Qmail nhận được dữ kiện từ một trong hai RBL database trên cho biết mail nào đó thuộc dạng “SPAM”, nó sẽ không tiếp nhận. Bạn có thể thêm các tham số cho rblsmtpd tùy thích.

Có lẽ bạn sẽ tự hỏi: vậy cứ mỗi lần mail đi vào đều phải được kiểm tra từ RBL thì chắc phải chậm lắm? Ðây là câu hỏi đã được đặt ra nhiều lần. Cá nhân tôi không thấy mức độ hoạt động của Qmail giảm sút khi đi qua giai đoạn kiểm tra này vì thật sự đây chỉ là một quy trình đối chiếu đơn giản. Nói cho cùng, dẫu có chậm hơn một tí vẫn còn nhanh hơn thời gian bạn phải ngồi xoá những bom thư bằng tay.

Một điểm cần lưu ý khi dùng các RBL database là nên theo dõi sự hiện diện của các RBL này. Lý do, các RBL này thường hoạt động theo tính thiện nguyện trên căn bản không lợi nhuận hoặc rất ít lợi nhuận nên tính trường tồn của chúng có phần bấp bênh. Nếu một trong những RBL bạn đang dùng không còn tồn tại thì nên cập nhật run script của “qmai-smtpd” nếu muốn duy trì nhiệm vụ kiểm tra SPAM của rblsmtpd. Tất nhiên bạn cũng có thể dùng RBL thương mại (phải trả tiền để dùng RBL database). Ðể cho tiện theo dõi, đây là danh sách cách RBL dabase cho chính Dan Bernstein, người viết Qmail và các phần mềm ứng dụng cho Qmail: http://cr.yp.to/ucspi-tcp/rblsmtpd.html

Hy vọng bạn sẽ hình thành một mail relay server bằng Qmail một cách hữu hiệu và tiện ích.

(kết thúc)
hnd, vninformatics.com / diendantinhoc.net 13/01/2003
Qmail as a Mail Gateway - Phần 3

Các điều chỉnh quan trọng cho qmail.

3.4.2 Thư mục “qmail-smtpd” trong supervise
- Tương tự như trên, bạn tạo ra hồ sơ có tên là run trong thư mục /var/qmail/supervise/qmail-smtpd. Hồ sơ run này có trách nhiệm gọi một số phân bộ quan trọng của qmail để thi hành các chức năng trực thuộc smtp. Hồ sơ “run” này có chi tiết như sau:
Code:
#!/bin/sh
# concurincoming is not standard qmail control file
# it is created manually to specify the allowed concurrent incoming messages
#
QMAILDUID=`id -u qmaild`
NOFILESGID=`id -g qmaild`
MAXSMTPD=`cat /var/qmail/control/concurincoming`
if [ -z "$QMAILDUID" -o -z "$NOFILESGID" -o -z "$MAXSMTPD" ]; then
echo QMAILDUID, NOFILESGID, or MAXSMTPD is not set in
echo /var/qmail/supervise/qmail-smtpd/run
echo “Have you set qmaild UID & qmaild GID yet?”
exit 1
fi
exec /usr/local/bin/softlimit -m 6291456 \
/usr/local/bin/tcpserver -v -p -x /etc/tcp.smtp.cdb -c "$MAXSMTPD" \
-u "$QMAILDUID" -g "$NOFILESGID" 0 smtp /var/qmail/bin/qmail-smtpd 2>&1


Hồ sơ này sẽ có thêm một vài thông số quan trọng cho vấn đề chống “SPAM” sẽ được đi sâu hơn trong phần 5.4 sau này. Ở đây, bạn chỉ cần nắm bắt một vài chi tiết quan trọng đó là:
- softlimit -m $MEMSIZE trong đó, $MEMSIZE là số lượng memory thích hợp cho các phân bộ của qmail để xử lý khối lượng mail cao nhất trong khoảng thời gian bận rộn nhất.

- tcpserver và các thông số -p -x trong đó, -p chỉ định cho tình trạng “hoảng” (paranoid) dùng để kiểm tra IP của host gởi mail đến xem domain, MX record và IP của nó có giá trị hay không (tránh tình trạng SPAM theo phương thức đơn giản). -x chỉ định cho tcpserver dùng database (trong phần 3.4 sau đây) để kiểm tra chế độ nhận hoặc từ chối mail từ người gởi dựa trên database này.

- concurincoming variable trong hồ sơ “run” dùng để chỉ định số lượng mail được “đi vào” mail gateway mỗi lần. Bạn có thể cho nó một con số thích đáng tùy theo nhu cầu. Tuy nhiên, không nên cho concurincoming có giá trị quá cao để phòng ngừa khả năng bị DOS. Tôi chọn giá trị là 20 cho concurincoming, giá trị này đủ sức xử lý vài trăm đến vài ngàn mail mỗi giờ (tùy theo dung tích của mail đi xuyên qua mail gateway).
# echo 20 > /var/qmail/control/concurincoming
# chmod 644 /var/qmail/control/concurincoming


- Ðừng quên đổi hồ sơ “run” này thành “executable”:
# chmod 755 /var/qmail/supervise/qmail-smtpd/run

- Bước kế tiếp là tạo ra hồ sơ “run” trong thư mục /var/qmail/supervise/qmail-smtpd/log. Hồ sơ này gọi multilog thi hành nhiệm vụ logging cho các lưu thông thuộc phần hành smtp, multilog chuyển các log thuộc smtp vào thư mục /var/log/qmail/smtpd; nó có chi tiết như sau:
Code:
#!/bin/sh
# set user id and group id for qmail smtp daemon
exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t s5000000000 /var/log/qmail/smtpd


- Ðừng quên đổi hồ sơ “run” này thành “executable”:
# chmod 755 /var/qmail/supervise/qmail-smtpd/log/run

- Cuối cùng là tạo thư mục log cho qmail-smtpd:
# mkdir -p /var/log/qmail/smtpd

- Và đổi chủ quyền của thư mục này cho qmaill (bạn còn nhớ phần tạo tài khoản nhân dụng và nhóm nhân dụng ở phần 2.4.3?):
# chown qmaill /var/log/qmail /var/log/qmail/smtpd

3.5 Bộ quản trị “SMTP Access Control”
Trong qmailctl có một function chuyên chịu trách nhiệm cho phần SMTP access control. Bạn xem lại qmailctl sẽ thấy có dòng như sau thuộc function cdb:
cat /etc/smtprules/qmail-rules.txt | tcprules /etc/tcp.smtp.cdb

Lệnh trên có hai phần: copy qmail-rules.txt và pipe nó sang tcprules để biến nó thành hash database. Database này chứa các thông tin để kiểm tra chế độ nhận hoặc từ chối mail từ người gởi như đã đề cập trong phần 3.4.2 ở trên.

Bạn có thể tạo một hồ sơ có tên là qmail-rules.txt trong thư mục /etc/smtprules và có chi tiết như sau:
- Tạo thư mục /etc/smtprules trước:
# mkdir – p /etc/smtprules

- Ðưa chi tiết vào hồ sơ qmail-rules.txt:
# echo '127.:allow,RELAYCLIENT=””' >> /etc/smtprules/qmail-rules.txt
Lệnh trên đưa vào policy cho phép các host thuộc loopback được phép relay, nếu không Qmail không làm việc được.

# echo '192.168.1.:allow,RELAYCLIENT=””' >> /etc/smtprules/qmail-rules.txt
Lệnh trên đưa vào policy cho phép trọn bộ các client thuộc subnet 192.168.1.0/24 được quyền gởi mail đến Qmail gateway

# echo '10.10.10.50:allow,RELAYCLIENT=””' >> /etc/smtprules/qmail-rules.txt
Lệnh trên đưa vào policy cho phép một IP address (có thể là MS Exchange Server bên trong một subnet của LAN) được quyền relay.

# echo 'spamboy@spamhouse.com:deny' >> /etc/smtprules/qmail-rules.txt
Lệnh trên đưa vào policy từ chối mail từ người gởi có tên spamboy từ domain spamhouse.com. Cách này là cách đơn giản đề phóng chống bomb mail. Trên thực tế ứng dụng có nhiều phương pháp hữu hiệu hơn (sẽ bàn sâu hơn trong phần 5.4 sau này).

# echo 'badhost.net:deny' >> /etc/smtprules/qmail-rules.txt
Lệnh trên đưa vào policy từ chối mail của trọn bộ domain badhost.com. Bạn có thể dùng phương cách :allow hoặc :deny một cách linh động cho thích hợp với nhu cầu riêng. Và cuối cùng của hồ sơ qmail-rules.txt này, bạn luôn luôn cần một dòng như sau:
.:deny (# echo '.:deny' >> /etc/smtprules/qmail-rules.txt) với tác dụng từ chối tất cả các trường hợp còn lại.

Hồ sơ qmail-rules.txt đến đây tương tự như sau:

Code:
127.:allow,RELAYCLIENT=””
192.168.1.:allow,RELAYCLIENT=””
10.10.10.50:allow,RELAYCLIENT=””
<a href="mailto:spamboy@spamhouse.com">spamboy@spamhouse.com</a>:deny
badhost.net:deny
.:deny


Sau khi đã hoàn tất hồ sơ qmail-rules.txt như ý (đúng syntax như trên cho :allow, :deny) bạn có thể dùng function cdb của qmailctl:
# qmailctl cdb

Hoặc kiểu “dài dòng”:
# cat /etc/smtprules/qmail-rules.txt | tcprules /etc/tcp.smtp.cdb

Cũng nên đi vào chi tiết của tcprules syntax để giúp bạn tạo thêm các rules theo ý muốn và tránh những sai sót có thể xảy ra. Syntax của tcprules rất đơn giản như sau:
address:action,variable

Trong đó,
address có thể là một internet address (192.168.1.1), một chuỗi subnet (192.168.1.), một e-mail address (spamboy@spamhouse.com), một domain host (badhost.net) hoặc nếu không chỉ định một address nào thì bất cứ address cũng ứng dụng. Các variables của address có thể tóm gọn như sau:
$TCPREMOTEINFO@$TCPREMOTEIP (spamboy@192.168.1.1)
$TCPREMOTEINFO@$TCPREMOTEHOST (spamboy@spamhouse.com)
$TCPREMOTEIP (192.168.1.1)
$TCPREMOTEHOST (box.spamhouse.com)
Một phần của $TCPREMOTEIP (192.168.1)
Một phần của $TCPREMOTEHOST (spamhouse.com)
Không để address (bất cứ address nào cũng ứng dụng)

action là một trong hai trường hợp allow dành để cho phép address đã định hoặc deny dành để từ chối address đã định.

variable đi sau action được tách ra bởi dấu phẩy (,) (comma separated) thông thường là variable RELAYCLIENT với giá trị là một empty string (RELAYCLIENT=””)


3.6 Tạo ảo dụng “alias” cho Qmail
“alias” đóng vai trò quan trọng trong vấn đề quản lý mail server, điều này có nghĩa mỗi “alias” là một “ảo nhân” chịu trách nhiệm cho một số trường hợp điển hình của các hoạt động trên một mail server. Sau đây là 3 “alias” cần thiết nhất :
- postmaster (theo đúng RFC 2821) chỉ cho Administrator của mail server
- mailer-daemon một loại người dùng bán tiêu chuẩn để nhận các mail bị dội (bounce)
- root dùng để chuyển các loại mail mang tính chủ quyền đến system administrator

Giả sử bạn muốn mailbox của chính mình lo luôn cả 3 alias ở trên, bạn cần ra các lệnh sau:
# echo myname > /var/qmail/alias/.qmail-root
# echo myname > /var/qmail/alias/.qmai-postmaster
# ln -s /var/qmail/alias/.postmaster /var/qmail/alias/.qmail-mailer-daemon
# chmod 644 /var/qmail/alias/.qmail-root /var/qmail/alias/.qmail-postmaster


Nên nhớ các alias trên đều là hồ sơ “dấu” (hidden files) nên chúng đều có dấu chấm (.) đằng trước tên của alias. Các alias này có thể dùng để chuyển mail đến các user trên Unix (hoặc Linux), tôi không đi sâu vào vấn đề này vì chủ đề của bài viết là dùng Qmail như một mail gateway để forward mail vào một MTA bên trong LAN (như MS Exchange chẳng hạn).
Ðến đây Qmail có thể hoạt động được. Tuy nhiên, có một số vấn đề còn phải thử nghiệm và điều chỉnh để hoàn thiện các configuration của Qmail và daemontools. Ðây là các bước quan trọng và sẽ được đi sâu trong phần kế tiếp.

(kết thúc phần 3)
hnd, vninformatics.com / diendantinhoc.net 11/10/2002
Qmail as a Mail Gateway - Phần 2
Thiết lập ứng dụng qmail như một mail gateway.

[/b]3. Thiết lập ứng dụng Qmail[/b]
3.1 Hồ sơ rc và “defaultdelivery”
Hồ sơ “rc” là boot script của qmail ấn định phương thức chuyển giao mail tùy theo cách sắp xếp và chọn lựa của từng hệ thống. Trong thư mục /var/qmail/boot có sẵn một số script cho từng trường hợp.

Nếu bạn không dùng daemontools mà dùng splogger của qmail để gởi log xuyên qua syslog (tiêu chuẩn Unix) và binmail để chuyển giao thông điệp theo phương thức /var/spool/mail/$USER thì “rc” script tương tự như sau:

Ví dụ thứ nhất:

Code:
#!/bin/sh
# Dùng splogger để chuyển log xuyên qua syslog
# Dùng binmail để chuyển giao thông điệp đến /var/spool/mail/$USER theo default
# Dùng V7 binmail interface: /bin/mail -f
exec env – PATH=”/var/qmail/bin:$PATH” \
qmail-start \
`|preline -f /bin/mail -f "${SENDER:-MAILER-DAEMON}" -d "$USER"` \
splogger mail


Trong đó,
- Phương thức chuyển giao mail đến /var/spool/mail/$USER chính là phương thức chuyển giao mail theo truyền thống Unix.Nếu bạn muốn hiểu rõ hơn, nên tham khảo thêm phương thức chuyển giao mail của Unix.
- Các dấu back-slash (\) chỉ cho sự nối tiếp trong câu lệnh (\ là return character)
- Phần lệnh preline -f /bin/mail -f của người gởi là MAILER-DAEMON đến $USER nằm trong dấu backquote (`) chớ không phải là singlequote ('). Nên phân biệt rõ các dấu quote này khi đánh lệnh trên trong script “rc” (backquote dùng để ứng thế một cụm lệnh, singlequote chỉ là một singlequote). Nếu bạn muốn hiểu rõ hơn về khả năng “command subtitution” trên Unix, nên đọc thêm phần này.

Dĩ nhiên bạn có thể tạo nên một “rc” như trên và dùng splogger. Tuy nhiên, nếu đã install daemontools, tại sao không tận dụng chức năng của nó? Hồ sơ “rc” của tôi như sau:

Ví dụ thứ nhì:

Code:
#!/bin/sh
# Dùng multilog của daemontools để gởi log đến /var/log/qmail
# Dùng /var/qmail/control/defaultdelivery làm hồ sơ configuration
# Dùng ./Mailbox làm phương thức chuyển giao thông điệp
exec env – PATH=”/var/qmail/bin:$PATH” \
qmail-start “`cat /var/qmail/control/defaultdelivery`”


- So với hồ sơ “rc” ở trên dùng splogger và hồ sơ “rc” dùng daemontools này thì hồ sơ “rc” này giản tiện hơn nhiều.
- Lệnh exec env xác định môi trường qmail và qmail-start chỉ đơn giản khởi động theo thông số đã định sẵn trong defaultdelivery.
- defaultdelivery không phải là một hồ sơ tiêu chuẩn của qmail. Nó đơn giản chỉ là một phương tiện gởi thông số cho qmail-start.

Sau khi đã tạo ra hồ sơ “rc” trong thư mục /var/qmail, có hai việc cần làm là:
- Thay “mod” của hồ sơ này thành “executable: # chmod 755 /var/qmail/rc để script rc này có thể “khởi động” được khi cần.
- Tạo ra thư mục /var/log/qmail để daemontools gởi log của qmail vào vị trí này: # mkdir /var/log/qmail (nếu bạn không muốn dùng daemontools mà chỉ dùng rc như phần ví dụ thứ nhất thì không cần tạo ra thư mục này vì splogger sẽ dùng syslog).

Ðến đây có lẽ bạn sẽ hỏi: defaultdelivery ở đâu ra và trong hồ sơ này chứa những gì? Như đã đề cập ở trên, defaultdelivery chỉ đơn giản là một phương tiện gởi thông số cho qmail-start; nó giúp qmail-start xác định phương thức chuyển gởi mail (nếu không muốn dùng .qmail). Có 3 phương thức chuyển gởi mail thông thường trên Unix như sau:

Format Vị trí defaultdelivery Lợi điểm
maildir $HOME ./Maildir/ Ðáng tin cậy nhưng ít MUA hỗ trợ
mbox $HOME ./Mailbox Phổ biến và được các MUA hỗ trợ
username /var/spool/mail xem thêm INSTALL.vsm Mail tiêu chuẩn Unix.

Dựa vào bảng phân tích trên, bạn có thể chọn phương thức thích hợp cho mình. Trong thư mục mã nguồn có kèm các hồ sơ INSTALL.mbox, INSTALL.maildir và INSTALL.vsm giải thích rất chi tiết các ưu khuyết điểm của từng phương thức nếu bạn muốn tìm hiểu sâu hơn. Cá nhân tôi chọn ./Mailbox vì muốn tạo tiện dụng cho các MUA (Mail User Agent).

Vậy, để tạo ra defaultdelivery, bạn chỉ cần chọn một phương thức và dùng lệnh echo để đính phương thức đã chọn, giả sử như:
# echo ./Mailbox > /var/qmail/control/defaultdelivery

Trong đó,
- ./Mailbox là phương thức.
- hồ sơ defaultdelivery được nằm trong thư mục /var/qmail/control, nơi trọn bộ các configuration thuộc qmail được lưu trữ.
- lệnh echo đính dòng ./Mailbox (>smilie vào hồ sơ defaultdelivery.

3.2 Hồ sơ khởi động “qmailctl” của hệ điều hành
Ðến đây, bạn đã có thể khởi động qmail bằng cách chạy script “rc” đã tạo ở trên. Tuy nhiên, để qmail được ứng dụng như một mail gateway có khả năng tự khởi động và tự tắt theo đúng quy chế thì “rc” không có khả năng này. Hơn nữa, các chức năng tiện dụng của phần daemontools không được ứng dụng đầy đủ nếu chỉ dùng script “rc” ở trên. Hồ sơ “rc” sẽ được dùng như một phân bộ trong cơ chế chuyển gởi thông điệp (qua smtp), các phần kế tiếp sẽ đi sâu hơn.

Vì lý do trên, hồ sơ khởi động qmailctl được hình thành để quản lý các phân bộ của qmail và daemontools đúng hệ thống. Trước khi đi sâu vào nội dung của hồ sơ qmailctl, bạn cần biết qua một số binaries và các chức năng của chúng trong phần mềm hỗ trợ “daemontools” để dễ hình dung cơ chế làm việc của hồ sơ qmailctl.

Sau khi compile và build daemontools thành công, phần mềm này có 14 binaries được lưu trữ trong /usr/local/bin, bạn chỉ cần biết đến một số binaries và chức năng của chúng như sau:

Tên binary Chức năng
supervise: Dùng để khởi động và theo dõi một process. Có khả năng tái khởi động process đó nếu nó bị “chết”
svok: Dùng để kiểm tra xem supervise đang thao tác hay không
svc: Dùng để điều khiển một process được khởi động bởi supervise, binary này cho phép Admin ngưng và tái khởi động một process nào đó.
svstat: Dùng để báo cáo tình hình của một process được khởi động bởi supervise
svscan: Dùng để khởi động vào theo dõi một nhóm process được supervise tạo ra

Theo đây là một bản mẫu của hồ sơ qmailctl, bạn có thể dùng nó cho hệ thống của mình nếu không muốn tự tạo một “qmailctl” riêng:
Code:
#!/bin/sh
# Người dùng RedHat có thể giản tiện chu trình sắp xếp
# “runlevel” với lệnh “chkconfig”
# chkconfig: - 80 30
# description: qmail as MTA
# Phần kế tiếp dùng để chỉnh user environment
PATH=/var/qmail/bin:/bin:/usr/bin:/usr/local/bin:/usr/local/sbin
export PATH
# Xác định variables cho qmail daemon ID và user group ID
QMAILDUID=`id -u qmaild`
NOFILESGID-`id -g qmaild`
# Bắt đầu tạo ra các trường hợp hoạt dụng cho supervise
case “$1” in
start)
echo -n “Starting qmail: svscan”
cd /var/qmail/supervise
env – PATH=”$PATH” svscan &
echo $! > /var/run/svscan.pid
echo “.”
;;
stop)
echo -n “Stopping qmail: svscan
kill `cat /var/run/svscan.pid`
echo -n “ qmail down”
svc -dx /var/qmail/supervise/*
echo -n “ logging down too”
svc -dx /var/qmail/supervise/*/log
echo “.”
;;
stat)
cd /var/qmail/supervise
svstat * */log
;;
doqueue)
echo “Sending ALRM signal to qmail-send”
svc -a /var/qmail/supervise/qmail-send
;;
queue)
qmail-qstat
qmail-qread
reload)
echo “Sending HUP signal to qmail-send”
svc -h /var/qmail/supervise/qmail-send
;;
pause)
echo “Pausing qmail-send”
svc -p /var/qmail/supervise/qmail-send
echo “Pausing qmail-smtpd”
svc -p /var/qmail/supervise/qmail-smtpd
;;
cont)
echo “Continuing qmail-send”
svc -c /var/qmail/supervise/qmail-send
echo “Continuing qmail-smtpd”
svc -c /var/qmail/supervise/qmail-smtpd”
;;
restart)
echo “Restarting qmail:”
echo “* Stopping qmail-smtpd”
svc -d /var/qmail/supervise/qmail-smtpd
echo “* Sending qmail-send SIGTERM and restarting”
svc -t /var/qmail/supervise/qmail-send
echo “* Restarting qmail-smtpd”
svc -u /var/qmail/supervise/qmail-smtpd
;;
cdb)
echo “Do not forget to modify /etc/smtprules/qmail-rules.txt or it will use the old cdb”
cat /etc/smtprules/qmail-rules.txt | tcprules /etc/tcp.smtp.cdb /tmp/tcp.smtp.tmp
chmod 644 /etc/tcp.smtp*
echo “/etc/tcp.smtp.cdb is reloaded”
;;
help)
cat <<HELP
stop -- stops mail service (smtp connections refused, nothing goes out)
start -- starts mail service (smtp connection accepted, mail can go out)
pause -- temporarily stops mail service (connections accepted, nothing leaves)
cont -- continues paused mail service
stat -- displays status of mail service
cdb -- rebuild the tcpserver cdb file for smtp
restart -- stops and restarts smtp, sends qmail-send a TERM & restarts it
doqueue -- sends qmail-send ALRM, scheduling queued messages for delivery
reload -- sends qmail-send HUP, rereading locals and virtualdomains
queue -- shows status of queue
HELP
;;
*)
echo “Usage: $0 {start|stop|restart|doqueue|reload|stat|pause|cont|cdb|queue|help}”
exit 1
;;
esac
exit 0


Ðến đây có lẽ bạn sẽ thấy là binary svc được dùng rất nhiều trong hồ sơ qmailctl và sẽ thắc mắc các thông số -a, -h, -t, -u.... của binary này có những chức năng nào?

Như đã đề cập ở trên về một số binaries của daemontools và các chức năng của chúng; svc dùng để điều khiển một process được khởi động bởi supervise, binary này cho phép Admin ngưng và tái khởi động một process nào đó. Việc ứng dụng chức năng “tái khởi động một process nào đó” của svc hết sức quan trọng vì nó bảo đảm sự hoạt động liên tục của qmail và các phân bộ của qmail (nếu không mail sẽ bị bounce và không chuyển gởi được khi một trong những phân bộ của qmail bị ngưng).

Sau đây là bảng tóm gọn các thông số của svc (cho trường hợp bạn cần đào sâu), bạn có thể dùng bảng thông số của svc và đối chiếu với phần script trong hồ sơ qmailctl để hiểu rõ hơn các functions của nó:

Thông số Chức năng

-a Alarm – Dùng để gởi tín hiệu ALRM đến service
-c Continue – Dùng để gởi tín hiệu CONT đến service
-d Down – Dùng để gởi tín hiệu TERM và CONT đến service (nếu service này đang chạy) và không cho phép supervise tái khởi động service này.
-h Hangup – Dùng để gởi tín hiệu HUP đến service
-i Interrupt – Dùng để gởi tín hiệu INT đến service
-k Kill – Dùng để gởi tín hiệu KILL đến service
-o Once – Dùng để khởi động service nếu service này chưa khởi động, nếu service này ngừng sau đó, once ngăn chặn supervise tái khởi động nó.
-p Pause – Dùng để gởi tín hiệu STOP đến service
-t Terminate – Dùng để gởi tín hiệu TERM đến service
-u Up – Nếu service đang ngưng, thông số này khởi động service
-x Exit – Ðình chỉ supervise ngay sau khi service down.

Có hai cách sắp xếp cho hồ sơ “qmailctl” ở trên tự động chạy khi Linux (Unix) system đi xuyên qua “run level”. Linux và các Unix System V xử dụng init.d thư mục để chứa các shell scripts cho các run level, thông thường thư mục init.d có cấu trúc như:
/etc/init.d hoặc,
/etc/rc.d/init.d tùy theo cách sắp xếp và ứng dụng của mỗi Linux distro và Unix System V.
a. Cách “lười” (trên RedHat và một số distro có ứng dụng chkconfig):
- Tạo hồ sơ qmailctl như trên trong /var/qmail/bin (cho tiện)
- Làm cho qmailctl “chạy được” và tạo “soft link” từ hồ sơ qmailctl này vào /etc/rc.d/init.d (hoặc /etc/init.d tùy theo) và /usr/bin
# chmod 755 /var/qmail/bin/qmailctl
# ln -s /var/qmail/bin/qmailctl /etc/rc.d/init.d/qmail
# ln -s /var/qmail/bin/qmailctl /usr/bin


- Chuyển vào thư mục /etc/rc.d/init.d
# cd /etc/rc.d/init.d

- Chạy lệnh chkconfig để đưa các “soft links” vào đúng các “run level”
# chkconfig –add qmail

Nên nhớ phải có phần #chkconfig: - 80 30 và # description: ở phần đầu của qmailctl không thì lệnh chkconfig sẽ không chạy được. 80 và 30 là enable level và disable level của qmail (xem thêm các tài liệu về runlevel trên Sys V)

b. Cách “cổ điển” (trên tất cả các distro và System V):
Cách “cổ điển” để tạo ra runlevel cho System V sau đây rất căn bản và thông thường.
Sau khi tạo hồ sơ qmailctl trong /var/qmail/bin và làm nó “chạy được” với chmod như trên phần “lười”, bạn tạo ra các soft link từ qmailctl đến tới từng runlevel như sau:

# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc0.d/K30qmail
# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc1.d/K30qmail
# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc2.d/S80qmail
# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc3.d/S80qmail
# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc4.d/S80qmail
# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc5.d/S80qmail
# ln -s /var/qmail/bin/qmailctl /etc/rc.d/rc6.d/K30qmail


Ở trên cho thấy các symbolic links từ /var/qmail/bin/qmailctl đến mỗi runlevel (của các rcX.d) với chỉ định: qmail ngưng hoạt động ở rc0.d, rc1.d và rc6.d và hoạt động ở rc2.d, rc3.d, rc4.d và rc5.d (ký hiệu K dùng cho Stop và ký hiệu S dùng cho Start trong runlevel). Ở đây tôi chọn S80 và K30 dựa trên runlevel (by default) của Sendmail, bạn có thể chọn chỉ số khác thích hợp cho yêu cầu riêng. Tuy nhiên, nên sắp xếp runlevel theo đúng trình tự và ưu tiên của mỗi daemon không thì sẽ tạo ra sự cố cho các daemon của system.

3.3 Stop Sendmail và link Sendmail
Có lẽ bạn sẽ tự hỏi tại sao lại có Sendmail ở đây và tại sao phải Stop Sendmail rồi link Sendmail? Câu trả lời như sau: Sendmail gần như là một MTA default cho các Linux Distro cũng như đa số các Unix flavor cho nên cơ hội Sendmail daemon đang chạy và chiếm cứ port 25 trên máy của bạn rất cao. Ðiều này dẫn đến nhiều trục trặc tai quái khi qmail bắt đầu khởi động (cho dù bạn vẫn có thể chỉnh định cho Sendmail và Qmail cùng chạy trên một host nếu sắp xếp cẩn thận). Bước Stop Sendmail và Link Sendmail theo tôi, là một bước hết sức quan trọng và cần thiết. Tất nhiên, nếu bạn không hề có Sendmail trên máy thì bước này không cần phải đi xuyên qua.

3.3.1 Stop Sendmail:
- Thông thường, Stop Sendmail cách đơn giản nhất là dùng runlevel script trong /etc/rc.d/init.d/sendmail để Stop:
# /etc/rc.d/init.d/sendmail stop

- Cách “dã chiến” là kill process ID nào của Sendmail nếu Sendmail đang chạy (hoặc system của bạn không dùng runlevel hoặc Sendmail được khởi động kiểu “dã chiến”...). Dùng lệnh ps để in ra các process nào của Sendmail:
# ps -ef | grep sendmail

- Sau khi ps cho bạn danh sách các process thuộc Sendmail, bạn chỉ đơn giản “kill”:
# kill PID-of-Sendmail

- Cho an toàn, bạn nên tháo bỏ trọn bộ Sendmail nếu đã quyết định không dùng nó nữa hoặc ít nhất là tháo bỏ các symbolic link cho runlevel của Sendmail trong /etc/rc.d/rcX.d. Ðể tháo bỏ các runlevel theo phương pháp tiện dụng chkconfig (trên RedHat và các distro có ứng dụng chkconfig này):
# chkconfig –del sendmail

- Ðể tháo bỏ các symbolic links cho runlevel của Sendmail theo kiểu “dã chiến”:
# mv /etc/rc.d/init.d/sendmail /etc/rc.d/init.d/sendmail.old
# rm -f /etc/rc.d/rc0.d/K30sendmail
# rm -f /etc/rc.d/rc1.d/K30sendmail
# rm -f /etc/rc.d/rc2.d/S80sendmail
# rm -f /etc/rc.d/rc3.d/S80sendmail
# rm -f /etc/rc.d/rc4.d/S80sendmail
# rm -f /etc/rc.d/rc5.d/S80sendmail
# rm -f /etc/rc.d/rc6.d/K30sendmail


- Ðể tháo bỏ luôn cả binaries của Sendmail, trên RedHat hoặc distro nào dùng RPM bằng cách:
# rpm -e –nodeps sendmail

- Hoặc đi vào từng thư mục /usr/sbin hoặc /usr/local/sbin (hoặc /usr/lib, /usr/local/lib) để manually rename từng binary thuộc về Sendmail (nếu Sendmail được cài vào máy theo phương thức “compile and build” tổng quát.

3.3.2 Link Sendmail
Ðã muốn xoá luôn Sendmail vậy sao còn link Sendmail là sao? Có rất nhiều chương trình trên Linux và Unix “gọi” Sendmail để chuyển gởi thông điệp theo “default”. Nếu Sendmail binary bị hoàn toàn tháo gỡ thì không chóng thì chầy bạn sẽ lâm vào nhiều trục trặc bí ẩn smilie. Cách loại trừ những trục trặc “bí ẩn” có thể xảy ra là dùng phương thức Link Sendmail. Link Sendmail ở đây là link một copy có tên là Sendmail từ binary của Qmail thay vì dùng nguyên bản binary của Sendmail.

- Ðổi tên của nguyên bản binary Sendmail:
# mv /usr/sbin/sendmail /usr/sbin/sendmail.old
# mv /usr/lib/sendmail /usr/lib/sendmail.old


- Link bản Sendmail của Qmail vào các thư mục /usr/sbin và /usr/lib:
# ln -s /var/qmail/bin/sendmail /usr/lib
# ln -s /var/qmail/bin/sendmail /usr/sbin


3.4 Thư mục “supervise” và các ứng động trong thư mục này
Ðến đây, bạn cần tạo các thư mục và một số hồ sơ “supervise” cho qmailctl làm việc (bạn xem lại qmailctl có rất nhiều phần svc dùng /var/qmail/supervise/qmail-send hoặc /var/qmail/supervise/qmail-smtpd). Các bước kế tiếp rất đơn giản, tuy nhiên bạn nên cẩn thận với các chi tiết không thì sẽ gặp những trục trặc sau này.
Ðầu tiên, bạn tạo ra 2 thư mục:
# mkdir -p /var/qmail/supervise/qmail-send/log
# mkdir -p /var/qmail/supervise/qmail-smtpd/log


Trong đó, thông số -p (parents) dùng để tạo các thư mục từ trên xuống dưới (từ supervise đến qmail-send và log tương tự cho qmail-smtpd và log). Ðiều này có nghĩa trước khi mkdir tạo ra thư mục log bên trong thư mục qmail-send, nó kiểm tra xem thư mục qmail-send có sẵn hay không và tạo ra thư mục này nếu cần. Tương tự nó kiểm tra xem thư mục supervise có sẵn hay không.... (Dùng # mkdir –help để xem thêm chi tiết)

3.4.1 Thư mục “qmail-send” trong supervise
Sau khi tạo ra các thư mục /var/qmail/supervise/qmail-send/log như trên, bạn phải đi qua các bước như sau:
- Tạo một hồ sơ gọi là run trong /var/qmail/supervise/qmail-send (hồ sơ run nằm trong thư mục qmail-send – chú ý vị trí của các hồ sơ trong các thư mục). Hồ sơ run này có chi tiết như sau:
#!/bin/sh
exec /var/qmail/rc


Bạn còn nhớ hồ sơ “rc” ở phần 3.1 không? Ðây chính là nơi “rc” được gọi và thi hành nhiệm vụ trong trọn bộ cơ chế hoạt động của qmail và daemontools. Sau khi tạo ra hồ sơ run này, bạn phải đổi “mod” của nó thành “executable”:
# chmod 755 /var/qmail/supervise/qmail-send/run

- Tạo một hồ sơ khác cũng có tên là run nhưng nằm trong thư mục log của thư mục qmail-send). Hồ sơ run này có trách nhiệm gọi multilog thi hành nhiệm vụ logging của những gì qmail-send gởi đi; nó có chi tiết như sau:
#!/bin/sh
exec /usr/local/bin/setuidgid qmaill /usr/local/bin/multilog t s5000000000 /var/log/qmail


- Ðừng quan tâm lắm đến các thông số của shell script “run” lúc này. Các chi tiết sẽ đưọc đào sâu thêm trong những phần sau. Nếu bạn quan sát kỹ sẽ thấy mọi bước ăn khớp với nhau từ giai đoạn tạo ra thư mục cho log và thư mục này đến đây được dùng như một thông số trong shell script “run” ở trên. Sau khi tạo ra hồ sơ run này, bạn phải đổi “mod” của nó thành “executable”:
# chmod 755 /var/qmail/supervise/qmail-send/log/run

(kết thúc phần 2)
hnd, vninformatics.com / diendantinhoc.net 04/10/2002
Qmail as a Mail Gateway - Phần 1

Giới thiệu tổng quát về Qmail và phương thức tải, biên dịch và chuẩn bị cài đặt Qmail server.
1. Giới thiệu về Qmail

1.1 Tài liệu dành cho ai?
Tài liệu này dành cho những ai muốn dùng Qmail như một MTA cho hệ thống mail. Ðiều cần thiết là người đọc phải có kiến thức căn bản sử dụng một hệ thống *nix (cách sử dụng các lệnh và cách truy cập / tạo vào các thư mục). Người viết tài liệu không chịu trách nhiệm cho bất cứ hư hại đến máy của người dùng cũng như sự phiền não, bực dọc, mất ngủ .... đến người dùng tài liệu này smilie

Tài liệu này đào sâu ở mức độ có hạn. Mọi ứng dụng tùy thuộc vào nhu cầu và khả năng thiết lập của người dùng. Qmail không phải là một MTA phức tạp. Tuy nhiên nó mang một số khái niệm điều hành độc lập giữa các thành phần để tạo nên một MTA làm việc hoàn chỉnh, do đó, người đọc nên nghiên cứu kỹ trước khi bắt tay vào việc thiết kế một hệ MTA dùng Qmail.

Tài liệu này ứng dụng mô hình qmail làm mail gateway để nhận mail từ Internet và chuyển mail đến một hoặc nhiều mail servers bên trong mạng riêng. Người viết không ứng dụng mô hình qmail như là một mail server phục vụ tất cả các mail protocol khác như IMAP, POP3... vì lý do bảo mật. Có hai điểm tối quan trọng của mô hình mail gateway là:

- Ổn định và hiệu năng: qmail có khả năng chuyển nhận hàng triệu thông điệp một ngày (dựa vào tài liệu trên web site của qmail.org). Tuy nhiên, nếu biến nó thành một mail server phục vụ tất cả các mail protocol thì bị giới hạn trong vấn đề kiểm dịch (authentication). Nếu mail server thuộc một mạng dùng hoàn toàn Unix thì giới hạn này có thể khắc phục dễ dàng. Không may trên thực tế hiện nay, không còn nhiều mạng “thuần” Unix hoặc “thuần” một hệ điều hành nào khác. Bởi vậy, qmail hoạt động như một mail gateway chỉ có trách nhiệm chuyển mail đến các mail servers khác (trong giới hạn cho phép domain) mà không phải lo vấn đề authentication, do đó, ngoài tính bảo mật, tính hiệu năng được nâng cao đáng kể.

-Tính bảo mật: Như đã nêu ra ở trên những khó khăn trong cơ chế quản lý kiểm dịch của một (hoặc nhiều) mạng có đa hệ điều hành không những giảm sút tính hiệu năng mà còn ảnh hưởng lớn đến tính bảo mật. Lý do, quản lý một trung tâm tài nguyên nhân dụng (central user database) dễ dàng và ổn định hơn nhiều user database. Hơn thế, cơ chế Internet <--> Mail Gateway <--> Firewall <--> Internal Mail Servers <--> Users chặc chẽ và an toàn hơn. Ðó là chưa kể ứng dụng kiểm soát / ngăn chặn viruses, trojans và cách loại scripts mang tính phá hoại trên một Unix Mail Gateway trước khi thông điệp được chuyển vào một Mail Server bên trong (Microsoft Exchange hoặc IBM Lotus chẳng hạn). Các ứng dụng cho POP3 hoặc IMAP được thiết lập một cách độc lập trên internal mail servers và người dùng có thể truy cập qua một cơ chế firewalling nào đó.

1.2 Sơ lược về Qmail
Qmail được viết bởi Tiến sĩ toán của trường đại học Illinois, Chicago, tiến sĩ Dan Bernstein. Qmail ra đời vào tháng Giêng năm 1996 với một phiên bản Beta 0.70 và sau đó phiên bản Gamma 0.90 được cập nhật vào tháng 8 năm 1996. Phiên bản ổn định 1.0 được ra mắt vào tháng 2 năm 1997. Phiên bản được lưu hành hiện nay là 1.03 được phát hành vào tháng 6 năm 1997.

1.3 Tại sao dùng Qmail?
Có rất nhiều MTA trên môi trường *nix hiện nay và mỗi khi nhắc đến MTA chúng ta phải nhắc đến Sendmail. Tuy nhiên, Dan Bernstein viết Qmail vì ông ta thấy rằng Sendmail thừa hưởng nhiều lỗi bảo mật từ các phiên bản trước đây và phần mềm này rất cồng kềnh, cho dù những năm gần đây, nhóm Sendmail không ngừng điều chỉnh và cải tiến phần mềm này để giảm thiểu những yếu điểm. Khi viết Qmail, ngoài ưu tiên cho vấn đề bảo mật, Dan Bernstein chú trọng rất nhiều đến khả năng hoạt động và tính dễ dùng của nó. Qmail mang tính truyền thống của các hoạt trình Unix: mỗi tiểu ứng trình có khả năng đảm đương trọn vẹn một chức năng chuyên biệt và các tiểu ứng trình này có thể chuyền (pipe) sang các tiểu ứng trình khác để đáp ứng các quy trình phức tạp. Bởi thể, Qmail bao gồm nhiều binaries tạo thành một dây chuyền hoạt động. Ðây là một điển hình nặng tính bảo mật và tính hiệu năng trong cơ chế điều hành của một MTA.

2. Cài đặt Qmail
2.1 Cài từ “gói” (RPM) hay từ tar ball?
Qmail thuộc dạng mở-nguồn nên bạn có thể tải mã nguồn của Qmail về để compile và thiết kế nó cho thích hợp với hệ điều hành của mình. Có một số RPM cho RedHat trên Internet (dùng http://rpmfind.net để tìm). Tuy nhiên, có ít nhiều hạn chế khi dùng RPM và không phải các “gói” này luôn luôn có sẵn cho các hệ điều hành.

RPM thường buộc người dùng cài đặt binaries vào một nơi trong những thư mục và đôi khi sự ép buộc này không tiện cho cách tổ chức thư mục đã có sẵn của bạn. RPM không giải quyết được các trường hợp bị thiếu hoặc sai “thư viện lệ thuộc” (dependencies). Bởi thế, phương cách compile và build từ mã nguồn xem ra là một phương cách khả thi nhất. Hơn nữa, nó sẽ tạo cơ hội cho bạn hiểu rõ hơn cơ chế làm việc của Qmail sau quá trình cài đặt. Tài liệu này sẽ chỉ chuyên chú vào quy trình compile và build từ mã nguồn.

2.2 Yêu cầu để cài đặt Qmail
Ðể có thể cài đặt Qmail thành công, sau đây là các yêu cầu tối yếu:

- Một C compiler, các thư mục header và các thư viện cho hệ thống lập trình. Nếu bạn dùng trong một phiên bản Linux, compiler của bạn hẳn là gcc.

- Có đủ nơi chứa cho quá trình build và các binaries và các tài liệu sau khi Qmail được build. Ổ chứa tuyệt đối cần thiết cho Qmail lưu trữ và xử lý mail trong các điểm “xếp hàng” (mail queues).

- Domain name của bạn. Qmail chỉ làm việc (đúng) khi bạn có một domain hợp pháp (fully qualified domain name FQDN). Liên hệ với dịch vụ Internet của bạn cho vấn đề này nếu bạn không rõ.

- Qmail được thiết kế như một MTA hạng nặng. Ðiều này có nghĩa máy chạy Qmail phải có băng thông ổn định và rộng đủ để tải và nhận mail. Nếu bạn có dự định thiết lập một MTA xuyên qua modem, có lẽ serialmail là một phần mềm thích hợp hơn http://cr.yp.to/software/serialmail-0.75.tar.gz).

2.3 Những điều cần chuẩn bị
Qmail không phải là một phần mềm MTA phức tạp. Tuy nhiên, cách an toàn nhất nên thử cài đặt trên một máy tách biệt từ hệ thống mail đang làm việc của bạn và thâu thập kinh nghiệm trước khi cài đặt trên máy chính thức.

Thực ra quá trình compile và build qmail sẽ không ảnh hưởng gì đến hệ thống mail đang làm việc của bạn. Tuy nhiên, bước kiểm nghiệm Qmail sẽ làm gián đoạn hệ thống mail đang có. Ðề nghị trên đơn giản là một cách nhắc nhở mang tính an toàn.
Nếu bạn có dụng ý chuyển đổi (migrate) từ một MTA khác sang Qmail, cũng như bao nhiêu quy trình chuyển đổi khác, giai đoạn hình thành một chiến thuật chuyển đổi (từng bước một) là một điều hết sức cần thiết và giai đoạn “thử” Qmail sẽ giúp bạn hình thành chiến thuật này chính xác hơn và hữu hiệu hơn.

2.4 Tải mã nguồn từ đâu
- Mã nguồn Qmail có thể được tải về từ: ftp://cr.yp.to/software/qmail-1.03.tar.gz hoặc theo đường dẫn của site http://cr.yp.to/software.html (site chính thức của mã nguồn Qmail).
- Ngoài mã nguồn của Qmail ở trên, bạn cần thêm ít nhất hai phần mềm phụ nhưng tuyệt đối cần thiết cho Qmail (chi tiết hoạt động của các phần mềm phụ này sẽ được trình bày trong quy trình thiết lập Qmail). Hai phần mềm phụ nói trên là: ftp://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz (cho uscpi-tcp) và ftp://cr.yp.to/daemontools/daemontoo...76.tar.gz (cho daemontols).

2.4 Từng bước cài đặt
2.4.1 Xả nén mã nguồn
Các bước cài đặt cần chủ quyền root nên trước khi xả nén vào tạo các hồ sơ thư mục, bạn nên chuyển chủ quyền sang super user. Theo quy định chung của System V, các nguồn và binaries do người dùng thêm vào system nên cho vào /usr/local/src, cho nên chúng ta cứ theo vậy mà làm.
- chuyển thành super user:
myshell$ su
(đánh mật mã của root)

- đổi umask thành 022 cho bảo đảm
# umask 022

- tạo thư mục /usr/local/src (nếu nó chưa có sẵn)
# mkdir -p /usr/local/src

- dời các source của qmail vào trong /usr/local/src
# mv qmail-1.03.tar.gz ucspi-tcp-0.88.tar.gz daemontools-0.76.tar.gz /usr/local/src

- vào thư mục /usr/local/src để xả nén cái gói qmail, uscpi-tcp và daemontools
# cd /usr/local/src
# gunzip *
# tar -xpvf qmail-1.03.tar
# tar -xpvf ucspi-tcp-0.88.tar
# tar -xpvf daemontools-0.76.tar


2.4.2 Tạo hồ sơ thư mục
Ðến đây bạn đã có một nhóm thư mục như sau:
/usr/local/src/qmail-1.03, /usr/loca/src/ucspi-tcp-0.88 và /usr/local/src/admin/daemontools-0.76.

- Bước kế tiếp tạo thư mục chủ cho Qmail, đây là nơi trọn bộ binary và configuration cho qmail được cất giữ và điều hành.
# mkdir /var/qmail

- Tạo thư mục bin trong thư mục chủ của qmail, nơi chứa các binaries
# mkdir /var/qmail/bin

- Tạo thư mục control trong thư mục chủ của qmail, nơi chứa các hồ sơ chỉnh liệu
# mkdir /var/qmail/control

- Tạo thư mục alias trong thư mục chủ của qmail, nơi chứa các hồ sơ ảo
# mkdir /var/qmail/alias

- Tạo thư mục man trong thư mục chủ của qmail, nơi chứa các tài liệu cho qmail
# mkdir /var/qmail/man

2.4.3 Tạo tài khoản nhân dụng và nhóm nhân dụng
Vấn đề tạo tài khoản nhân dụng và nhóm nhân dụng hết sức quan trọng cho qmail trong vấn đề hoạt động vào bảo mật. Tài khoản nhân dụng cho phép qmail hoạt động trong giới hạn trách nhiệm của nó. Ðiều này có nghĩa, trường hợp qmail bị “hack”, tài khoản nhân dụng của qmail không thể dùng (hoặc rất khó) để xâm nhập hệ thống sâu hơn.

Có một số phương thức khác nhau để tạo tài khoản nhân dụng và nhóm nhân dụng. Nhiều người xử dụng qmail đã tạo ra một số scripts để thực hiện bước này một cách nhanh chóng và dễ dàng. Tuy nhiên ở đây chúng ta nên đi xuyên qua các bước này một cách cụ thể để có thể hiểu sâu hơn vấn đề tài khoản nhân dụng và bảo mật trong quá trình tạo tài khoản nhân dụng.

- Tạo nhóm nhân dụng nofiles
# groupadd nofiles

- Tạo tài khoản nhân dụng cho nhóm nofiles này
# useradd alias -g nofiles -d /var/qmail/alias -s /bin/true
# useradd qmaild -g nofiles -d /var/qmail -s /bin/true
# useradd qmaill -g nofiles -d /var/qmail -s /bin/true
# useradd qmailp -g nofiles -d /var/qmail -s /bin/true


Như các bạn thấy, chuỗi lệnh ở trên là lệnh căn bản tạo tài khoản nhân dụng cho các user alias, qmaild, qmaill và qmailp có cùng một nhóm nhân dụng là nofiles. Ðặc biệt các lệnh trên không cho những user này một shell nào cả (-s /bin/true – lệnh true thực sự không làm gì cả) vì lý do các user này là các “nhân viên” hoạt động của qmail và chúng không hề cần shell. Một điểm cần nhớ trong quá trình tạo tài khoản nhân dụng: khi “người dùng” không cần một shell để thi hành trách nhiệm thì không nên cho họ một shell. Trường hợp một tài khoản nhân dụng bị hack, tin tặc khó có thể đi sâu hơn nếu tài khoản nhân dụng đó không được phép xử dụng bất cứ một shell nào.

- Tương tự, tạo nhóm nhân dụng qmail như sau:
# groupadd qmail

- Tạo tài khoản nhân dụng cho nhóm nhân dụng qmail này:
# useradd qmailq -g qmail -d /var/qmail -s /bin/true
# useradd qmailr -g qmail -d /var/qmail -s /bin/true
# useradd qmails -g qmail -d /var/qmail -s /bin/true


Một lần nữa, các “người dùng” qmailq, qmailr và qmails thuộc nhóm qmail này không cần shell. Lý do phải tạo các người dùng như trên sẽ được giải thích trong những bước sau.

Bước kế tiếp rất quan trọng. Bước này kiểm nghiệm chủ quyền và nhóm nhân dụng của các “người dùng” vừa tạo ra ở trên.

- Dùng vihoặc bất cứ text editor nào vào /etc/group và viết xuống mã hiệu (GID hay group ID) của nhóm nhân dụng nofiles và qmail.

- Ví dụ group nofiles có mã hiệu là 2004 và group qmail là 2005. Bạn dùng vi vào /etc/passwd và kiểm lại xem các entry cho alias, qmaild, qmaill, qmailp, qmailq, qmailr và qmails có đúng nhóm nhân dụng và shell của họ là /bin/true hay không. Những entry này tương tự như:
alias:*:1005:2004::/var/qmail/alias:/bin/true
qmaild:*:1006:2004::/var/qmail:/bin/true
qmaill:*:1007:2004::/var/qmail:/bin/true
qmailp:*:1008:2004::/var/qmail:/bin/true
qmailq:*:1009:2005::/var/qmail:/bin/true
qmailr:*:1010:2005::/var/qmail:/bin/true
qmails:*:1011:2005::/var/qmail:/bin/true


Trong các entry ở trên mỗi user có riêng một mã hiệu và thuộc vào nhóm nhân dụng khác nhau.

2.4.4 Build binaries từ mã nguồn
Ðến đây bạn đã sẵn sàng thực hiện bước compile và build qmail. Các bước build qmail như sau:
- cd vào thư mục chứa mã nguồn của qmail
# cd /usr/local/src/qmail-1.03

- Ðánh lệnh make buộc compiler biên dịch mã nguồn của qmail dựa trên chỉnh định của hồ sơ Makefile
# make

- Ðánh các lệnh make setup check. Ðây là 2 lệnh gom lại thành một.. Lệnh thứ nhất make setup chuyển các binaries đã được build ở trên vào đúng nơi của nó. Lệnh thứ nhì make check là lệnh dùng để kiểm tra lại thực tính của các hồ sơ và binaries được build.
# make setup check

- Bước kế tiếp là bước hiệu chỉnh DNS cho qmail. Nếu DNS server (fully qualified) của bạn đã sẵn sàng, bạn chỉ cần chạy lệnh:
# ./config

Lệnh này kiểm tra DNS server của bạn, nếu không có gì trở ngại nó đặt domain name của bạn vào /var/qmail/control/defaultdomain và /var/qmail/control/plusdomain (plusdomain dành cho một binary của qmail “qmail-inject” để thêm vào entry của plusdomain khi cần. Xem thêm ở phần 4: Hồ sơ điều chỉnh của Qmail trong “qmail-control”). Lệnh này cũng thêm vào các entry cần thiết cho /var/qmail/control/locals và /var/qmail/control/rcphosts.

Vì một lý do trục trặc nào đó thuộc DNS làm cho lệnh ./config ở trên không thể lấy được DNS entry để điều chỉnh các hồ sơ trên, bạn phải dùng lệnh ./config-fast để cài các entry cần thiết vào /var/qmail/control/

- Ðánh lệnh ./config-fast với thông số là domain name của bạn
# ./config-fast mydomain.com

mydomain.com phải là một domain name hoàn toàn hợp pháp và đã đăng ký với Internic (xem ở bước 2.2: Yêu cầu để cài đặt qmail ở trên). Lệnh ./config-fast của bước này sẽ cài các entry cần thiết với domain name bạn đã cho (như thông số ở trên); chắc chắn bạn sẽ không bị trở ngại gì trong bước này. Tuy nhiên, những bước sau này bạn sẽ gặp trở ngại nếu như bạn không cung cấp một domain name hợp pháp. Bước này chỉ buộc ./config-fast cài vào entry bạn cung cấp mà không bảo đảm (không kiểm nghiệm) là domain name đó giá trị hay không.


2.4.5 Cài ucspi-tcp
ucspi-tcp là phần mềm Dr. Dan Bernstein viết với mục đích thay thế cho inet daemon của Unix. Inet daemon được dùng rộng rãi trên các ứng trình Unix và gần đây, xinet ra đời để nâng cao tính năng của inet. Theo Dr Bernstein, phần mềm ucspi-tcp (dùng Unix Client-Server Program Interface cũng của ông) gọn nhẹ, hiệu quả và an toàn hơn inet rất nhiều. Bản thân người viết tài liệu này đã thử cả hai ứng dụng trên xinetd và uscpi-tcp và thấy rõ ưu điểm của ucspi-tcp trên bình diện hiệu năng. Ucspi-tcp được tạo ra với quan tâm bảo mật nên cách xử lý socket giữa client và server rất hiệu quả. Thực tế cho thấy ucspi-tcp ứng hoạt khít khao với qmail.

- Ðể compile và build uscpi-tcp, bạn cd vào thư mục uscpi-tcp
# cd /usr/local/src/ucspi-tcp-0.88

- Ðánh lệnh make buộc compiler biên dịch mã nguồn của ucspi-tcp dựa trên chỉnh định của hồ sơ Makefile
# make

- Ðánh các lệnh make setup check. Ðây là 2 lệnh gom lại thành một.. Lệnh thứ nhất make setup chuyển các binaries đã được build ở trên vào đúng nơi của nó. Lệnh thứ nhì make check là lệnh dùng để kiểm tra lại thực tính của các hồ sơ và binaries được build.
# make setup check

Nếu quy trình này không bị trở ngại gì, bạn đã compile và build xong ucspi-tcp.

2.4.6 Cài daemontols
Daemontools là một phần mềm giúp bạn rất nhiều trong quy trình quản lý và điều hành qmail server. Bạn có thể dùng qmail mà không cần đến daemontools. Tuy nhiên, khi đã dùng qmail nhiều hơn, bạn sẽ khám phá daemontools là một thứ đồ nghề không thể thiếu được.

Ðể compile và build daemontools, chỉ đơn giản cd vào thư mục của daemontools-0.76
# cd /usr/local/src/admin/daemontools-0.76

- Thư mục này có hai thư mục con, bạn không cần vào các thư mục con mà chỉ cần đánh lệnh
# package/install


(kết thúc phần 1)
hnd, vninformatics.com / diendantinhoc.net 09/09/2002
Xin chào các bạn ghé thăm box thảo luận về hệ điều hành linux của HVA.
Để bảo vệ và phát huy sân chơi của chúng ta được tốt đẹp hơn, trước tiên xin các bạn đọc và tuân thủ http://www.htmlforum.net/hvaonline/posts/list/137.html.

Những điểm cần lưu ý khi sinh hoạt trong box *nix :
1. Nhằm mục đích bảo vệ quyền lợi của tác giả, khi sưu tập các bài viết đăng lên diễn đàn HVA, không được sửa nội dung bài viết và phải đăng tên tác giả và nguồn gốc của bài viết. riêng việc sửa format để cho dễ nhìn được ngoại lệ, nhưng khi có khiếu nại từ phía tác giả, xin sửa lại theo đúng yêu cầu của tác giả.

2. Trước khi đặt câu hỏi xin dùng chức năng search của diễn đàn kiểm tra xem thắc mắc của bạn đã được giải đáp trên diễn đàn hay không.

3. Có trách nhiệm với topic và bài viết tạo ra và hãy theo dõi đến cùng.

4. Đặt tiêu đề rõ ràng cho người đọc hiểu bạn muốn nói gì trong bài viết.

5. Lấy tiêu đề làm trọng điểm triển khai khi thảo luận, không đặt câu hỏi không liên quan ghép chung lại trong một đề tài để thảo luận.

Ngoài ra, nếu cần thiết bạn có thể liên hệ trực tiếp đến 1 trong những mod trực tiếp quản lý box *nix bên dưới để biết thêm chi tiết .

Danh sách mod trực tiếp quản lý box *nix .
http://hvaonline.net/hvaonline/pm/sendTo/67588.html
http://hvaonline.net/hvaonline/pm/sendTo/94689.html
http://hvaonline.net/hvaonline/pm/sendTo/83486.html
http://hvaonline.net/hvaonline/pm/sendTo/124987.html
http://hvaonline.net/hvaonline/pm/sendTo/25267.html
http://hvaonline.net/hvaonline/pm/sendTo/110647.html

Xin cám ơn các bạn.
Kiện Toàn Bảo Mật Cho Apache - Phần 2

Chỉnh lý Apache
Bước đầu tiên là tháo bỏ hồ sơ /chroot/httpd/usr/local/apache/conf/httpd.conf và tạo một hồ sơ mới thay thế vào với nội dung tương tự như sau:

Code:
# =================================================
# Basic settings
# =================================================
ServerType standalone
ServerRoot "/usr/local/apache"
PidFile /usr/local/apache/logs/httpd.pid
ScoreBoardFile /usr/local/apache/logs/httpd.scoreboard
ResourceConfig /dev/null
AccessConfig /dev/null
# =================================================
# Performance settings
# =================================================
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 15
MinSpareServers 5
MaxSpareServers 10
StartServers 5
MaxClients 150
MaxRequestsPerChild 0
# =================================================
# Apache's modules
# =================================================
ClearModuleList
AddModule mod_log_config.c
AddModule mod_mime.c
AddModule mod_dir.c
AddModule mod_access.c
AddModule mod_auth.c
# =================================================
# General settings
# =================================================
Port 80
User apache
Group apache
ServerAdmin Webmaster@www.ebank.lab
UseCanonicalName Off
ServerSignature Off
HostnameLookups Off
ServerTokens Prod
<IfModule mod_dir.c>
DirectoryIndex index.html
</IfModule>
DocumentRoot "/www/vhosts"
# =================================================
# Access control
# =================================================
<Directory />
Options None
AllowOverride None
Order deny,allow
Deny from all
</Directory>
<Directory "/www/vhosts/www.ebank.lab">
Order allow,deny
Allow from all
</Directory>
<Directory "/www/vhosts/www.test.lab">
Order allow,deny
Allow from all
</Directory>
# =================================================
# MIME encoding
# =================================================
<IfModule mod_mime.c>
TypesConfig /usr/local/apache/conf/mime.types
</IfModule>
DefaultType text/plain
<IfModule mod_mime.c>
AddEncoding x-compress Z
AddEncoding x-gzip gz tgz
AddType application/x-tar .tgz
</IfModule>
# =================================================
# Logs
# =================================================
LogLevel warn
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
ErrorLog /usr/local/apache/logs/error_log
CustomLog /usr/local/apache/logs/access_log combined
# =================================================
# Virtual hosts
# =================================================
NameVirtualHost *
<VirtualHost *>
DocumentRoot "/www/vhosts/www.ebank.lab"
ServerName "www.ebank.lab"
ServerAlias "www.e-bank.lab"
ErrorLog logs/www.ebank.lab/error_log
CustomLog logs/www.ebank.lab/access_log combined
</VirtualHost>
<VirtualHost *>
DocumentRoot "/www/vhosts/www.test.lab"
ServerName "www.test.lab"
ErrorLog logs/www.test.lab/error_log
CustomLog logs/www.test.lab/access_log combined
</VirtualHost>


Cấu hình trên chỉ có những lệnh cần thiết để thoả mãn chức năng hoạt động và các trù bị bảo mật. Trong cấu hình đưa ra ở trên có hai hosts ảo được Web server hỗ trợ:

- www.ebank.lab www.e-bank.lab)
- www.test.lab


Nội dung của các Web site trên được chứa trong các thư mục:

- /chroot/httpd/www/vhosts/www.ebank.lab
- /chroot/httpd/www/vhosts/www.test.lab



Mỗi Web site có riêng log files được chứa trong các thư mục:

- /chroot/httpd/usr/local/apache/logs/www.ebank.lab
- /chroot/httpd/usr/local/apache/logs/www.test.lab


Các thư mục trên phải được tạo ra trước khi Apache hoạt động lần đầu tiên - nếu không Apache sẽ không làm việc đúng mức. Chủ nhân của các thư mục trên nên là root:sys, và chủ quyền nên chỉnh thành 0755.

So sánh với hồ sơ cấu hình mặc định của Apache, có những thay đổi sau:

* Số modules được ứng động đã giảm thiểu đáng kể,
* Apache không tiết lộ thông tin version number (phiên bản) (dùng các directives: ServerTokens, ServerSignature),
*
Các process của Apache (ngoại trừ process của root) được chỉnh định bằng chủ quyền riêng biệt của user/group bình thường (dùng các directives: User, Group),
*
Apache chỉ cho phép truy cập vào các thư mục, các thư mục con và các hồ sơ đã được quy định cụ thể trong hồ sơ cấu hình (dùng các directives: Directory, Allow); mọi requests khác đều bị từ chối theo mặc định,
*
Apache sẽ log nhiều thông tin hơn với các HTTP requests.

Lời bàn và mở rộng:
Configuration trên của Artur Maj triển khai theo lối "blank paper", có nghĩa là bắt đầu từ trang giấy trắng. Ðây là lối khai triển rất hay cho các config đòi hỏi tính bảo mật cao. Lý do: dùng config mặc định có sẵn của Apache sẽ có nhiều cơ hội thiếu sót những điểm quan trọng vì config mặc định của Apache chứa quá nhiều thông tin, mở cửa cho quá nhiều thứ có thể tạo lỗ hổng. Ðiều đáng nêu ra là configuration này rất gọn gàng và khoa học cho các phần của cấu hình. Khi cần phải thêm bớt và thay đổi, một cấu hình gọn gàng giúp cho vấn đề quản lý dễ dàng và chính xác hơn, tất nhiên cũng sẽ giảm thiểu những lỗi (ít khi nhận thấy được) trong quá trình chỉnh định.

Một điểm quan trọng khác cũng nên nhắc đến là các chi tiết về "Directives" tác giả bài viết đề cập trong phần giải thích. Tác giả đã không khai triển và giải thích chi tiết tác dụng của các "directives" này, có lẽ, ông ta giả định người dùng ở mức độ quan tâm đến bảo mật cho Apache hẳn phải nắm vững cơ chế làm việc của Apache và những "directives" dùng trong configuration của Apache. Ở điểm này, cá nhân tôi cho rằng việc tham khảo và nghiên cứu kỹ lưỡng các "directives" dùng trong Apache là một việc tối cần thiết nếu muốn bảo đảm hoạt tính và mật tính của Apache. Bạn có thể tham khảo chi tiết các "directives" trên website của Apache ở:
http://httpd.apache.org/docs/mod/directives.html (cho Apache 1.3.x)

http://httpd.apache.org/docs-2.0/mod/quickreference.html (cho Apache 2.x)

Ứng dụng các directives trong cấu hình của Apache một cách khoa học và thích hợp với nhu cầu là một điều không đơn giản. Việc đầu tiên giúp cho quá trình ứng dụng này là tạo cho mình một thói quen chuẩn bị cẩn thận và chính xác những phần tố cần dùng. Nếu bạn đã quen cách chỉnh định một server cho "nhanh" và có để "chạy liền" thì nên điều chỉnh lại thói quen này một khi đã dấn thân vào những điều thuộc về bảo mật.

Apache cũng cung cấp một số tài liệu cho vấn đề kiện toàn bảo mật cho Apache server, bạn nên tham khảo thêm ở:
http://httpd.apache.org/docs/misc/security_tips.html (cho Apache 1.3.x)

http://httpd.apache.org/docs-2.0/misc/security_tips.html (cho Apache 2.x)
Hai tài liệu trên gần giống nhau, tuy nhiên có những tiểu tiết quan trọng cần tham khảo kỹ lưỡng.

Bước cuối
Cuối cùng chúng ta nên tạo một đoạn "script" khởi động "apache.sh" với nội dung tương tự như sau:

Code:
#!/bin/sh
CHROOT=/chroot/httpd/
HTTPD=/usr/local/apache/bin/httpd
PIDFILE=/usr/local/apache/logs/httpd.pid
echo -n " apache"
case "$1" in
start)
/usr/sbin/chroot $CHROOT $HTTPD
;;
stop)
kill `cat ${CHROOT}/${PIDFILE}`
;;
*)
echo ""
echo "Usage: `basename $0` {start|stop}" >&2
exit 64
;;
esac
exit 0


Ðoạn script trên nên được đưa vào đúng thư mục (tùy hệ thống UNIX nào), nơi các script khởi động mặc định được cất giữ. Trong trường hợp dùng FreeBSD, script này nằm ở thư mục /usr/local/etc/rc.d

Lời bàn và mở rộng:
Ðối với những ai quen dùng *nix, đoạn script trên có lẽ rất đơn giản và dễ hiểu. Ðiều đáng đề cập ở đây là một cái script đơn giản nhưng lại quan trọng vì nó "ép" Apache khởi động trong môi trường "jail", dùng binary và tạo log thuộc môi trường "jail" này.

Trên Linux và một số system V thì "startup script" này nên đặt trong /etc/rc.d/init.d (hoặc /etc/init.d) và tạo symbolic link vào đúng "run level", bạn có thể tham khảo thêm chi tiết tùy loại *nix nào đang dùng. Tất nhiên bạn có thể điều chỉnh tùy thích "startup script" này nhưng điều quan trọng là phải nắm vững tinh thần "jail" được nêu ra ở trên.

Tổng kết
Các phương pháp trên cho phép tạo nên mức bảo mật chặt chẽ hơn cho Apache so với cấu hình mặc định có sẵn sau khi cài đặt.

Bằng phương pháp chỉ cho phép những modules tuyệt đối cần thiết cho Apache hoạt động, server của chúng ta không hẳn bị nhân nhượng khi một yếu điểm nào đó bị khám phá trong nhóm các modules của Apache. Dấu version number của Apache, "chrooting" và hạn chế cấu hình của Apache làm cho các trường hợp đột phá đến server trở nên rất khó khăn. Một môi trường "chrooted" còn có thêm một ưu điểm quan trọng - miễn nhiễm đến số lớn các loại tấn công, lý do chính là vì thiếu "shell" (/bin/sh, /bin/csh vâng vâng...). Ngay cả nếu tin tặc thao tác thành công các lệnh trên hệ thống, nhưng để thoát ra khỏi môi trường "chroot" là vấn đề không đơn giản.

Lời bàn và mở rộng:
Ngoài những điểm Artur Maj tổng kết ở trên, có lẽ điều cần mở rộng vài vấn đề bên ngoài phạm vi Apache. Trên thực tế, việc kiện toàn chính Apache phải đi song song với việc kiện toàn trọn bộ server mà Apache chạy. Nếu tin tặc không tấn công và đột nhập được qua môi trường "chrooted" của Apache, vẫn có thể đột nhập qua ngõ khác nếu server chạy Apache không được kiện toàn. Cực đoan hơn, cho dù Apache server được một firewall bảo vệ vẫn không thể phó mặc cho firewall mà lơ là chuyện kiện toàn server mà Apache chạy. Kiện toàn bảo mật đúng nghĩa là một công tác đòi hỏi một cách nhìn tổng quát cho trọn bộ môi trường hoạt động.

Trước khi kết thúc, tôi xin nhấn mạnh một điều quan trọng cho vấn đề bảo mật nói chung đó là: luôn luôn theo dõi, cập nhật software và thường xuyên kiểm soát cấu hình cũng như hoạt động của server. Không có software nào không có bugs và yếu điểm. Cho nên, việc theo dõi và bảo trì là một công tác hàng đầu trong vấn đề bảo mật. Kiện toàn bảo mật không thích hợp với tư duy "set and forget" (chỉnh lý rồi phó mặc). Kiện toàn bảo mật có lẽ cũng không nên theo tư duy theo kiểu "marketing hype" (quảng cáo sản phẩm một cách quá đáng ) ví dụ như "keep intruders at bay" hoặc "unbreakable systems"... Ðiều chắc chắn bạn có thể thực hiện là làm chậm bước tấn công và đột phá của tin tặc để có thể đối phó kịp thời.

Mọi góp ý xin gởi lên Diễn Đàn Tin Học - VNInformatics.
Hẹn gặp lại các bạn!
Kiện Toàn Bảo Mật Cho Apache - Phần 1

Bảo mật Apache: từng bước.
Artur Maj

Tài liệu này theo dạng chỉ dẫn từng bước cách cài đặt và chỉnh lý Apache 1.3.x web server với mục đích xử lý và phòng tránh các trường hợp đột nhập lúc những yếu điểm của chương trình này được khám phá.

Chức năng
Trước khi bắt đầu kiện toàn bảo mật Apache, chúng ta phải xác định rõ chức năng cần thiết nào của server sẽ được xử dụng. Tính đa năng của Apache tạo ra những khó khăn để thực hiện một mô thức tổng quát với mục đích kiện toàn bảo mật cho server trong mọi trường hợp có thể được. Ðây là lý do tài liệu này dựa trên các chức năng sau:

* Web server có thể truy cập từ Internet; và,
* Chỉ những trang HTML tĩnh (static HTML pages) sẽ được phục vụ,
* Server hỗ trợ tên miền cho cơ chế dịch vụ ảo,
* Các trang web đã ấn định chỉ có thể truy cập từ các cụm IP addresses hoặc người dùng (khai báo căn bản),
* Server sẽ tường trình trọn bộ các thỉnh cầu (bao gồm những thông tin về các web browsers).

Ðiều đáng nhấn mạnh ở đây là mô hình trên không hỗ trợ PHP, JSP, CGI hoặc bất cứ công nghệ nào khác có thể tạo cơ hội tương tác đến các dịch vụ Web. Ứng dụng cho những công nghệ trên có thể dẫn đến những đe dọa to lớn cho vấn đề bảo mật, dù chỉ là một đoạn script nhỏ, kín đáo cũng có thể giảm thiểu mức triệt để bảo mật của server. Tại sao? trước hết, các ứng trình ASP/CGI có thể chứa những yếu điểm bảo mật (ví dụ SQL injection, cross-site-scripting). Kế tiếp, chính các kỹ nghệ ấy có thể nguy hiểm (các yếu điểm trong PHP, các module của Perl v..v..). Ðó là lý do tại sao tôi mạnh mẽ đề nghị xử dụng những công nghệ ấy chỉ khi nào nhu cầu tương tác với một web site hoàn toàn cần thiết mà thôi.

Lời bàn và mở rộng:
Việc kiện toàn bảo mật cho một web server liên quan đến nhiều thủ thuật ở nhiều mức độ khác nhau. Tác giả chuộng nguyên tắc "tối thiểu" để giảm thiểu những lỗ hổng bảo mật có thể hiện diện trên một web server. Lý thuyết mà nói, nguyên tắc này đưa đến những ứng dụng và chỉnh định chặt chẽ hơn cho vấn đề bảo mật. Tuy nhiên, hoạt tính và nhu cầu làm việc của một web server không thể dừng lại ở khuôn khổ "tối thiểu" và bị áp đặt trong giới hạn các trang static HTML được. Thiết kế một chương trình làm việc cho web với yêu cầu đa năng và đa hoạt là một trong những yêu cầu hàng đầu. Một web site chỉ chuyên chú ở khuôn khổ các trang static HTML không những giới hạn tính năng của các trang web này một cách đáng kể, mà còn sa lầy trên mặt thực dụng và giá trị kinh tế lẫn giá thành xây dựng và bảo trì cho website. Giải pháp tối ưu có lẽ là sự cân bằng giữa kiến thức kiện toàn bảo mật cho web server cộng với khả năng thiết kế web một cách khoa học và vững chãi về mặt tính năng, hoạt động lẫn mặt giảm thiểu lỗi thiết kế, lỗi lập trình.

Một trong những hạn chế hay đúng hơn là lối mòn thường gặp trong các thiết kế ứng dụng web là việc pha trộn lẫn lộn các phân đoạn làm việc với nhau. Nói một cách khác, các thiết kế gia và các lập trình viên không đầu tư đủ thời gian để nghiên cứu, phân tích và áp dụng các mẫu thiết kế hợp lý cho công trình của mình mà thường đi thẳng vào bước thực hiện. Các bước "đi thẳng" thường thiếu độ chín chắn trong bước thiết kế, dẫn đến tính năng hạn hẹp và mở cửa cho các lỗi bảo mật nghiêm trọng. Trên thực tế, sự khác biệt giữa việc làm cho một web site chạy được và làm cho một web site chạy được, chạy có hiệu xuất, có khả năng mở rộng và bảo đảm mật tính là chuyện khác nhau một trời một vực. Thói quen "xào nấu" các lệnh điều tác cho một hệ điều hành hoặc các lệnh tương tác đến database trực tiếp từ một trang html trần trụi, nhúng các lệnh điều tác vào php, jsp, asp... là chuyện rất thường gặp. Ðây là một ví dụ điển hình cho cái gọi là "chạy được nhưng thiếu hiệu xuất, thiếu khả năng mở rộng và mở cửa cho các lỗi bảo mật quan trọng".

Vì khuôn khổ bài viết không tiện đi sâu vào các mẫu thiết kế cho những ứng dụng web, các bạn nên nghiên cứu thêm về những thiết kế này ở một số url sau tùy theo công nghệ bạn đang dùng:
http://www.object-arts.com/EducationCentre/Overviews/MVC.htm
http://www.enode.com/x/markup/tutorial/mvc.html
http://www.phppatterns.com/index.php/article/articleview/19/1/1/
http://www.dmbcllc.com/asp_mvc.aspx
http://www.jdance.com/jsparchitecture.shtm
http://www.redbooks.ibm.com/abstracts/sg245755.html
http://www.redbooks.ibm.com/abstracts/sg245754.html
Bạn có thể dùng google để search thêm các tài liệu về MVC với keyword: "MVC Pattern" hoặc tham khảo một số tài liệu chuyên ngành từ các website lớn như http://java.sun.comhoặc http://www.ibm.com.

Những trù bị bảo mật
Một trong những nhân tố quan trọng nhất cho mọi công trình điện toán là việc xác thực các trù bị bảo mật. Ðiều này phải được thoả mãn trước khi công trình được ứng tạo. Các trù bị bảo mật cho web server của chúng ta như sau:

* Hệ điều hành phải được kiện toàn càng chặt chẽ càng tốt, bao gồm việc phòng bị cho những tấn công từ bên ngoài lẫn bên trong,
* Server không được cung cấp bất cứ dịch vụ nào khác ngoại trừ HTTP: (80/TCP),
*
Truy cập từ xa đến server phải được khiển tác bởi tường lửa, thiết bị này chặn trọn bộ những tiếp nối cho lối ra và cho phép những tiếp nối cho lối vào đến cổng 80/TCP của web server mà thôi,
*
Web server Apache là dịch vụ duy nhất hiện hữu trên hệ thống,
*
Chỉ có những modules nào tuyệt đối cần thiết mới được cho phép hoạt động,
*
Các trang web dùng cho công tác chẩn xét và tự động hoá mục lục phải được tắt bỏ,
*
Srver nên giảm thiểu tối đa vấn đề tiết lộ những thông tin của chính server (mật tính qua ẩn tính),
*
Apache server phải chạy bằng UID/GID riêng biệt (tín chỉ cá nhân, tín chỉ nhóm), không được dùng bất cứ process nào khác của hệ thống,
*
Các process của Apache phải có giới hạn nhất định đến hệ thư mục (chrooting); và,
*
Không có bất cứ chương trình dạng shell nào hiện hữu trong môi trường chrooted (/bin/sh, /bin/csh, v..v..).

Lời bàn và mở rộng:
Một lần nữa tác giả đẩy mạnh tính "tối thiểu". Tuy nhiên, điểm khác biệt trong tính "tối thiểu" ở phần này thuộc bình diện môi trường hơn là giảm thiểu hoạt tính của web server Apache.

Bước kiện toàn bằng cách chỉ cho phép port 80/TCP trên server chạy Apache là thao tác căn bản cần phải làm vì nếu tấn công, tin tặc chỉ có một cổng để tấn công và để phòng thủ, người bảo vệ chỉ tập trung đến một cổng. Hơn thế, với cơ chế kiểm soát của tường lửa như tác giả đề nghị, tính bảo mật chắc chắn sẽ được nâng cao. Ở đây tác giả không đề cập một cách cụ thể loại tường lửa nào nên dùng vì quy trình chọn lựa, chỉnh định một tường lửa cho thích hợp phụ thuộc vào nhiều yếu tố khá phức tạp. Ðể mở rộng chi tiết này, tôi tin rằng sự hiện diện của một stateful firewall vừa có khả năng kiểm soát state ở tầng IP vừa có khả năng kiểm soát nội dung ở tầng application là cách tốt nhất. Nếu điều kiện tài chính cho phép, một stateful firewall như CheckPoint FW-1 hoặc Cisco PIX có thể đóng vai trò quan trọng này. Nếu điều kiện tài chính không cho phép, phương pháp tích hợp một số chương trình mở nguồn để đạt được khả năng tương tự vẫn có thể được, tuy nhiên sẽ mất nhiều nhân lực và thời gian hơn để điều chỉnh và thử nghiệm nếu chưa có nhiều kinh nghiệm trong lĩnh vực này.

Cài đặt hệ điều hành
Trước khi cài đặt Apache, chúng ta phải chọn lấy một hệ điều hành, đó là môi trường Apache sẽ hoạt động. Ở đây chúng ta có khá nhiều chọn lựa vì Apache có thể được biên dịch và cài đặt trên hầu hết các hệ điều hành. Phần còn lại của tài liệu này chỉ dẫn cách bảo mật Apache server trên nền FreeBSD (4.7), tuy nhiên các phương pháp được mô tả ở đây có thể ứng dụng trong hầu hết các hệ điều hành UNIX/LINUX. Chỉ có một hệ điều hành duy nhất tôi không giới thiệu là MS Windows - lý do chính là vì hệ điều hành này bị giới hạn khả năng kiện toàn bảo mật cho Apache.

Bước đầu tiên trong vấn đề bảo mật Web server là kiện toàn hệ điều hành. Các thảo luận kiện toàn hệ điều hành vượt quá khuôn khổ tài liệu này. Tuy vậy, có rất nhiều tài liệu trên Net miêu tả cách thực hiện vấn đề ấy. Ðộc giả được khuyến khích khai phá các vấn đề liên hệ đến phạm vi này.

Sau khi hệ thống được cài đặt và kiện toàn, chúng ta cần thêm một nhóm và một người dùng thông thường gọi là "apache" tương tự như thế này (một ví dụ từ FreeBDS):

pw groupadd apache
pw useradd apache -c "Apache Server" -d /dev/null -g apache -s /sbin/nologin

Theo mặc định, các process thuộc Apache chạy với chủ quyền của người dùng nobody (ngoại trừ process chính phải chạy với chủ quyền root) và GID thuộc nhóm nogroup. Ðiều này có thể dẫn đến những đe dọa bảo mật nghiêm trọng. Trong trường hợp đột nhập thành công, tin tặc có thể lấy được quyền truy dụng đến những process khác chạy cùng UID/GID. Bởi thế, giải pháp tối ưu là cho Apache chạy bằng UID/GID từ nhóm riêng biệt, chuyên chú đến software ấy thôi.

Lời bàn và mở rộng:
Ðối với những ai quen dùng *nix hẳn không lạ gì với khái niệm UID/GID thuộc chế độ "file permission". Tuy nhiên, chi tiết này nên mở rộng một tí cho những bạn đọc chưa quen thuộc với UID/GID. Phần tạo nhóm (group) và người dùng (user) riêng cho Apache ở trên có hai chi tiết cần chú ý là:
-d /dev/null: không cho phép user Apache có thư mục $HOME nhưng những user bình thường khác
-s /sbin/nologin: không cho user Apache dùng bất cứ một shell nào cả. Có một số trường hợp dùng -s /bin/true thay vì nologin ở trên, true là một lệnh không thực thi gì cả và hoàn toàn vô hại.

Lý do không cho phép user Apache có thư mục $HOME và không được cấp một "shell" nào cả vì nếu account Apache này bị nhân nhượng, tin tặc cũng không có cơ hội tiếp cận với system ở mức độ cần thiết cho thủ thuật gia tăng chủ quyền. Trên môi trường *nix nói chung, "shell" là giao diện giữa người dùng và hệ thống, không có shell thì không có cơ hội tiếp cận xa hơn.

Chuẩn bị software
Bước kế tiếp là bước tải phiên bản Apache mới nhất từ web site Apache http://httpd.apache.org). Chỉ có một số chọn lựa tiện ích được phép hoạt động trong quá trình biên dịch mà thôi, bởi thể, quyết định tải mã nguồn về biên dịch thay vì tải bản nhị phân (binary) là điều hết sức quan trọng.

Sau khi tải software về, chúng ta phải xả nén. Kế tiếp, chúng ta quyết định modules nào được phép hoạt động. Bản tường trình tổng quan về các modules hiện hữu cho phiên bản mới nhất của Apache 1.3.x (1.3.27 [1]) có ở: http://httpd.apache.org/docs/mod/

Những modules của Apache
Chọn lựa các modules là một trong những bước quan trọng nhất trong vấn đề bảo mật Apache. Chúng ta nên theo luật: càng ít càng tốt. Ðể thoả mãn chức năng và những trù bị bảo mật, các modules sau cần được cho phép:

Tên module
httpd_core: Chứa các chức năng cốt lõi của Apache, cần thiết cho bất cứ Apache nào.

mod_access: Cung cấp chế độ khiển tác dựa trên tên máy, địa chỉ IP, hoặc các tính chất yêu cầu thuộc về các clients. Bởi vì module này cần cho các chỉ phối (directive) "order", "allow" và "deny", nó cần được cho phép.

mod_auth: Cần thiết để ứng dụng vấn đề khai báo người dùng cho việc sử dụng các hồ sơ nguyên bản (khai báo căn bản cho HTTP), được chỉ định trong chức năng trù bị.

mod_dir: Cần thiết để tìm kiếm và phục vụ các hồ sơ thư mục: "index.html", "default.htm", v..v..

mod_log_config: Cần thiết để ứng hiệu báo cáo những yêu cầu thực hiện đến server.

mod_mime: Cần thiết để chỉnh lý nhóm chữ cái, mã hoá nội dung, tùy tác, ngôn ngữ nội dung và các loại MIME đại diện cho các loại tài liệu.

Tất cả các modules khác của Apache phải được tắt bỏ. Chúng ta có thể tắt bỏ chúng một cách an toàn bởi vì chúng ta không cần đến chúng. Do tắt bỏ những modules không cần thiết, chúng ta tránh được trường hợp có thể bị đột phá khi những yếu điểm bảo mật vừa được khám phá thuộc về một trong những modules này.

Cũng nên nhắc đến là có hai modules của Apache có thể nguy hiểm hơn các modules khác là: mod_autoindex và mod_info. Module thứ nhất cung cấp chức năng tự động sắp xếp thư mục và module này được phép chạy theo mặc định. Có thể dễ dàng dùng nó để xác định xem Apache được dùng trên một server nào đó hay không (ví dụ: http://server_name/icons/) và để lấy nội dung của các thư mục trên Web server dẫu không có các mục lục trong những thư mục này. Module thứ nhì, mod_info không nên cho phép truy cập từ Internet chính vì lý do nó tiết lộ cấu hình của Apache.

Câu hỏi kế tiếp là làm sao biên dịch các modules. Phương pháp tĩnh được xem là lựa chọn tốt hơn hết. Nếu những yếu điểm của Apache vừa được khám phá, có lẽ chúng ta sẽ không những tái biên dịch các modules bị lỗi mà sẽ tái biên dịch trọn bộ software. Chọn phương pháp tĩnh, chúng ta triệt tiêu nhu cầu của thêm một module nữa - mod_so.

Lời bàn và mở rộng:
Chọn lựa các modules cho Apache server thích hợp với từng nhu cầu là một việc khó khăn và mất thời gian. Chọn lựa đúng module và bảo đảm tính bảo mật lại càng khó khăn hơn. Ðể xác định module nào cần thiết và bảo đảm, việc chọn lựa và theo dõi "bug track" cho từng module là một điều rất cần thiết. Hiện nay có trên 200 modules lớn nhỏ, đủ loại chức năng cho Apache server. Bạn nên tham khảo thông tin ở website này cho công tác lựa chọn: http://modules.apache.org/

Website trên có sẵn search engine giúp bạn trong việc khảo sát và lựa chọn modules.

Biên dịch software
Trước tiên - nếu có bất cứ miếng vá (patch) nào cho bảo mật thì phải thực hiện ngay. Sau đó, server được biên dịch và cài đặt như sau:

Code:
./configure --prefix=/usr/local/apache --disable-module=all --server-uid=apache --server-gid=apache --enable-module=access --enable-module=log_config --enable-module=dir --enable-module=mime --enable-module=auth

(lệnh trên trải dài trong 1 dòng, không tách rời ra thành nhiều dòng)

make
su
umask 022
make install
chown -R root:sys /usr/local/apache


Lời bàn và mở rộng:
Ðối với các bạn chưa làm quen hoặc chỉ mới bắt đầu làm quen đến *nix, khái niệm biên dịch software có lẽ khá mới mẻ và lạ lẫm. Tuy nhiên, cảm giác này chỉ ở bước đầu trong quá trình làm quen mà thôi. Hầu như các bước trong phân đoạn "biên dịch software" cho các software khác nhau đều tương tự như nhau.

Ðiều lý thú trong vấn đề "biên dịch software" trên phương diện bảo mật ở đây, ngoài cơ hội có thể xem mã nguồn, tìm lỗi, tìm lổ hổng từ mã nguồn, bạn còn có cơ hội thiết lập và biên dịch software mình cần theo ý muốn. Trong đoạn lệnh ./configure ở trên minh hoạ cụ thể tính "tự do" ở chỗ bạn có toàn quyền muốn thêm hoặc bớt module tùy thích. Tính linh động trong vấn đề biên dịch software và tính đóng kín khi dùng một "installshield" trở nên hiển nhiên khi đem ra so sánh. Khi bạn phải cài một software gồm các binaries đã được biên dịch (theo khuôn khổ nào đó) sẵn, bạn không có nhiều cơ hội quyết định hoặc chọn lựa theo ý muốn nữa. Ðây là một trong những nguyên tắc khá quan trọng cho những ai quan tâm hoặc làm việc trực tiếp đến vấn đề bảo mật.

Ðổi "root" của server
Bước kế tiếp giới hạn các process của Apache truy dụng vào các hệ thống hồ sơ. Chúng ta có thể thực hiện vấn đề này bằng cách "chrooting" phần daemon chính của server (httpd). Tổng thể mà nói, thủ thuật "chrooting" có nghĩa là tạo một cấu trúc nguồn thư mục mới, dời chuyển các hồ sơ daemon vào đó và chạy các daemon thích ứng trong môi trường mới này. Nhờ vào đó, daemon (và cái process con) chỉ sẽ truy dụng đến cấu trúc thư mục mới.

Chúng ta bắt đầu chu trình này bằng cách tạo ra một thư mục mới bên trong thư mục /chroot/httpd:

mkdir -p /chroot/httpd/dev
mkdir -p /chroot/httpd/etc
mkdir -p /chroot/httpd/var/run
mkdir -p /chroot/httpd/usr/lib
mkdir -p /chroot/httpd/usr/libexec
mkdir -p /chroot/httpd/usr/local/apache/bin
mkdir -p /chroot/httpd/usr/local/apache/logs
mkdir -p /chroot/httpd/usr/local/apache/conf
mkdir -p /chroot/httpd/www


Chủ nhân của các thư mục trên phải là root và quyền truy dụng nên chỉnh lý ở mức 0755. Kế tiếp, chúng ta tạo hồ sơ thiết bị đặc biệt /dev/null:

ls -al /dev/null
(crw-rw-rw- 1 root wheel 2, 2 Mar 14 12:53 /dev/null)
mknod /chroot/httpd/dev/null c 2 2
chown root:sys /chroot/httpd/dev/null
chmod 666 /chroot/httpd/dev/null


Một phương pháp khác cần dùng để tạo thiết bị /chroot/httpd/dev/log, thiết bị này cần thiết để server làm việc đúng mức. Trong trường hợp hệ thống FreeBSD, cần thêm dòng sau đây vào /etc/rc.conf:

syslogd_flags="-l /chroot/httpd/dev/log"

Chúng ta phải tái khởi động hệ thống hoặc chính syslogd daemon để ứng tác các thay đổi. Ðể tạo thiết bị /chroot/httpd/dev/log trên các hệ điều hành khác, chúng ta phải xem các phần chỉ dẫn thích đáng (man syslogd).

Bước kế tiếp là bước sao chép chương trình httpd chính vào cấu trúc cây mới tạo ở trên, bao gồm các hồ sơ nhị phân và các thư viện cần thiết. Ðể thực hiện bước này, chúng ta phải chuẩn bị danh sách của các hồ sơ cần thiết. Chúng ta có thể tạo nên danh sách ấy bằng cách sử dụng lệnh như sau (tùy theo mỗi hệ điều hành mà các hồ sơ này hiện diện hay không):

Lệnh
Code:
ldd (All): lists dynamic dependencies of executable files or shared libraries
ktrace/ktruss/kdump (*BSD): Enables kernel process tracing, Displays kernel trace data
sotruss (Solaris): Traces shared library procedure calls
strace/ltrace (Linux): Traces system calls and signals
strings (All): Finds the printable strings in binary files
trace (AIX): Records selected system events
trace (freeware) (HP-UX <10.20): Print system call and kernal traces of processes
truss (FreeBSD, Solaris, AIX 5L, SCO Unixware): Traces system calls and signals
tusc (freeware) (HP-UX>11): Traces the system calls a process invokes in HP-UX 11


Ví dụ dùng các lệnh ldd, strings và truss như sau:

localhost# ldd /usr/local/apache/bin/httpd
/usr/local/apache/bin/httpd:
libcrypt.so.2 => /usr/lib/libcrypt.so.2 (0x280bd000)
libc.so.4 => /usr/lib/libc.so.4 (0x280d6000)

localhost# strings /usr/local/apache/bin/httpd | grep lib
/usr/libexec/ld-elf.so.1
libcrypt.so.2
libc.so.4

localhost# truss /usr/local/apache/bin/httpd | grep open
(...)
open("/var/run/ld-elf.so.hints",0,00) = 3 (0x3)
open("/usr/lib/libcrypt.so.2",0,027757775370) = 3 (0x3)
open("/usr/lib/libc.so.4",0,027757775370) = 3 (0x3)
open("/etc/spwd.db",0,00) = 3 (0x3)
open("/etc/group",0,0666) = 3 (0x3)
open("/usr/local/apache/conf/httpd.conf",0,0666) = 3 (0x3)
(...)

Các lệnh trên nên được áp dụng không cho chương trình httpd mà còn cho trọn bộ các thư viện và các nhị phân cần thiết (các thư viện thường đòi hỏi các thư viện khác). Ðối với trường hợp hệ thống FreeBSD, các hồ sau cần được sao chép vào cấu trúc thư mục mới:

cp /usr/local/apache/bin/httpd /chroot/httpd/usr/local/apache/bin/
cp /var/run/ld-elf.so.hints /chroot/httpd/var/run/
cp /usr/lib/libcrypt.so.2 /chroot/httpd/usr/lib/
cp /usr/lib/libc.so.4 /chroot/httpd/usr/lib/
cp /usr/libexec/ld-elf.so.1 /chroot/httpd/usr/libexec/


Bằng cách sử dụng lệnh truss, chúng ta cũng có thể khám phá được các hồ sơ chỉnh dụng sau cần được hiện diện trong môi trường chrooted:

cp /etc/hosts /chroot/httpd/etc/
cp /etc/host.conf /chroot/httpd/etc/
cp /etc/resolv.conf /chroot/httpd/etc/
cp /etc/group /chroot/httpd/etc/
cp /etc/master.passwd /chroot/httpd/etc/passwords
cp /usr/local/apache/conf/mime.types /chroot/httpd/usr/local/apache/conf/


Nên nhớ rằng từ hồ sơ /chroot/httpd/etc/passwords, chúng ta phải tháo bỏ hết các dòng ngoại trừ "nobody" và "apache". Tương tự, chúng ta cũng phải tháo bỏ hết các dòng ngoại trừ "nobody" và "apache" trong /chroot/httpd/etc/group. Kế tiếp chúng ta phải dựng database cho mật mã như sau:

cd /chroot/httpd/etc
pwd_mkdb -d /chroot/httpd/etc passwords
rm -rf /chroot/httpd/etc/master.passwd


Bước kế tiếp dùng để thử nghiệm httpd server xem nó chạy đúng mức trong môi trường chroot mới. Ðể thao tác vấn đề này, chúng ta phải sao chép hồ sơ chỉnh dụng mặc định của Apache và bản mẫu index.html:

cp /usr/local/apache/conf/httpd.conf /chroot/httpd/usr/local/apache/conf/
cp /usr/local/apache/htdocs/index.html.en /chroot/httpd/www/index.html


Sau khi sao chép các hồ sơ đề cập trên, chúng ta phải thay đổi chỉ phối DocumentRoot như được trình bày bên dưới (trong /chroot/httpd/usr/local/apache/conf/httpd.conf):

DocumentRoot "/www"

Tiếp theo chúng ta có thể thử chạy server:

chroot /chroot/httpd /usr/local/apache/bin/httpd

Nếu có trở ngại gì, tôi đề nghị phương thức phân tích log của Apache một cách sâu sát (/chroot/httpd/usr/local/apache/logs). Một cách khác là dùng lệnh sau:

truss chroot /chroot/httpd /usr/local/apache/bin/httpd

Chương trình truss chắc chắn sẽ chỉ ra nguyên nhân của các trở ngại. Sau khi triệt tiêu những lỗi còn lại, chúng ta có thể thiết lập Apache server.

Lời bàn và mở rộng:
Trên tinh thần bảo mật, đoạn trên là một trong những đoạn có thể cho là quan trọng nhất trong quá trình thiết lập một Apache web server. Câu hỏi được đặt ra: "tại sao chroot lại quan trọng đến thế?"

Ðối với những ai đã quen thuộc với cấu trúc filesystem trên một *nix nào đó, thì trả lời cho câu hỏi này khá dễ dàng. Tuy nhiên, đối với những ai chưa nắm rõ cấu trúc này thì hơi khó hơn một tí. Từ câu nói ở trên "Tổng thể mà nói, thủ thuật "chrooting" có nghĩa là tạo một cấu trúc nguồn thư mục mới, dời chuyển các hồ sơ daemon vào đó và chạy các daemon thích ứng trong môi trường mới này. Nhờ vào đó, daemon (và cái process con) chỉ sẽ truy dụng đến cấu trúc thư mục mới." có thể diễn giải như sau:

- cấu trúc filesystem của *nix nói chung (có những điểm tương đồng và dị biệt, nhưng ở đây chỉ đề cập đến những điểm khái quát mà thôi), root của filesystem là điểm khởi đầu của một cấu trúc "cây" (tree hierachy):

Code:
/
|--bin
|--boot
|--dev
|--etc
|--lib
|--mnt
|--opt
|--sbin
|--tmp
|--usr
|--var
|......

trong đó / (root của filesystem) chứa các thư mục khác và trong các thư mục này chứa các loại software, công cụ, thông tin, cấu hình... cho cả một *nix system.

- nếu một user có quyền truy cập đến / (root của filesystem) thì user ấy có cơ hội truy dụng các thông tin và công cụ trong những thư mục thuộc /. Ðể giảm thiểu và quản lý quyền truy cập của một user như Apache ở trên là điều rất khó kiện toàn cho nên "chroot" là phương tiện để ép người dùng chỉ được quyền truy cập và hoạt động trong một vùng nhất định nào đó, loại bỏ các trường hợp thiếu sót trong cơ chế quản lý quyền truy dụng.

- sau khi áp đặt "chroot" cho user Apache, thay vì "hắn" có thể thấy và truy cập vào các thư mục thuộc loại "cấm kị", "hắn" chỉ có thể làm việc trong khuôn khổ:

Code:
/apache-root
|--httpd
|--dev
|--etc
|--var
| |--run
|--usr
| |--lib
| |--libexec
| |--local
| | |--apache
| | | |--bin
| | | |--logs
| | | |--conf
|--www

như quá trình xác định trong phần bài viết trên. User Apache không có cơ hội truy cập vào các thư mục quan trọng như /etc, /bin, /sbin... sau khi đã được "chroot". User Apache chỉ có thể xử dụng những thông tin nào cần thiết và vừa đủ để web server này hoạt động mà thôi. Thủ thuật "chroot" đôi khi còn được gọi là "jail" (cầm tù) theo đúng tinh thần chroot.

Mọi góp ý xin gởi lên Diễn Đàn Tin Học - VNInformatics.
Hẹn gặp lại các bạn!

1. "Phiên bản mới nhất" được tính vào thời điểm bài viết được đăng.
Case 1 - iptables và máy đơn
Trường hợp điển hình thứ nhất trong việc ứng dụng iptables để bảo vệ.

1. Trường hợp:
Firewall đơn giản cho một máy đơn.

2. Nhu cầu:
Bảo vệ máy đơn không bị rà và truy cập trong khi kết nối vào Internet. Máy đơn này không cung cấp dịch vụ cho những máy bên ngoài truy cập vào.

3. Phương pháp kết nối:
Modem, xDSL, Cable.

Đòi hỏi tối thiểu:
Đã hoàn tất thành công quy trình kết nối vào Internet (xuyên qua modem, xDSL, cable....) và có thể duyệt Internet hoàn chỉnh.


- nếu là modem, ppp0 là external interface.
- nếu là xDSL, có hai trường hợp: ppp0 là external interface (nếu ISP ứng dụng PPPOE) hoặc eth0 là external interface (nếu ISP dùng DHCPD để assign IP cho user).
- nếu là cable, eth0 là external interface, IP address thường được phân bố qua DHCP.

5. Nhóm luật:

Code:
1. IF=`/sbin/route | grep -i 'default' | awk '{print $8}'`
2. IP=`/sbin/ifconfig $IF | grep "inet addr" | awk -F":" '{print $2}' | awk '{print $1}'`
3. IPT="/usr/local/sbin/iptables"
4.
5. $IPT -F
6. $IPT -P INPUT DROP
7. $IPT -P OUTPUT DROP
8. $IPT -P FORWARD DROP
9.
10. $IPT -A OUTPUT -o $IF -s $IP -j ACCEPT
11. $IPT -A INPUT -i $IF -d $IP -m state --state ESTABLISHED,RELATED -j ACCEPT



6. Phân tích:
- Dòng 1: Ấn định giá trị của biến IF bằng chuỗi lệnh ngầm, chuỗi lệnh này xác định network interface nào được gán với default gateway. Khi IF này ứng động và được phân bố một địa chỉ IP, nó cũng chính là default gateway ra vào của các packets trong quá trình truy cập Internet.

- Dòng 2: Ấn định giá trị của biến IP bằng chuỗi lệnh ngầm. Giá trị này được hiện hữu khi interface ở trên ứng động và kết nối vào dịch vụ cung cấp Internet. Đây là một chuỗi lệnh dùng để "tách" lấy giá trị IP hiện có trên IF. Nó tiện dụng vì bạn không cần phải điều chỉnh firewall script này mỗi khi IP address thay đổi.

- Dòng 3: Ấn định giá trị của biến IPT chỉ cho vị trí chứa iptables binary. Dùng cách này có hai điểm tiện là không phải gõ trọn bộ đường dẫn đến nơi chứa iptables và nếu nơi chứa iptables thay đổi vì lý do nào đó thì chỉ cần thay đổi ở biến này.

- Dòng 4: Dòng trống có chủ ý cho dễ nhìn.

- Dòng 5: Lệnh iptables với thông số -F có tác dụng xoá dội các chains còn vương vãi đâu đó (nếu có) khi firewall script này khởi tác. Đây là một lệnh thuộc dạng "house-keeping" (bảo trì) để gìn giữ tính trung thực và chính xác của các "rules" do iptables tạo ra. -F (flush) là một bước nên thực hiện vì mỗi lượt firewall script này được chạy, những rules cần thiết sẽ được ứng dụng và những rules không cần dùng (và còn vương vãi trên memory) sẽ bị loại bỏ.

- Dòng 6-7-8: Ba dòng trông đơn giản này kỳ thật đóng vai trò tối quan trọng. Tác dụng của mục tiêu DROP ở đây với thông số -P dùng để thiết lập chế độ (policy) cản mọi lưu thông trước khi cho phép loại lưu thông cụ thể nào đó được ra hoặc vào. DROP Policy là phương cách ngăn chặn vững nhất bởi vì những gì không cho phép sẽ bị cản. Chỉ có những gì được cho phép một cách cụ thể thì mới được đi qua. Hay nói một cách khác, khi một packet đi vào (hoặc đi ra) mà không có rule nào thích ứng cụ thể cho tính chất của packet này thì nó sẽ bị cản (DROP) theo chế độ chung của firewall.

Diễn dịch luật này thành ngôn ngữ bình thường như sau: theo chế độ mặc định (-P), các chains INPUT, OUTPUT và FORWARD hoàn toàn từ chối (DROP) mọi lưu thông.

- Dòng 9: Dòng trống có chủ ý cho dễ nhìn.

- Dòng 10: Đây là dòng xác định OUTPUT rule cho mọi packet đi ra từ IP và IF (đã xác định ở dòng 1 và 2). Rule này cho phép mọi packet, mọi loại giao thức (protocol) đi từ IP xuyên qua IF được phép đi ra ngoài. Với iptables, nếu bạn không xác định cụ thể loại giao thức (-p) trong một rule thì nó mang giá trị ngầm là mọi giao thức. Đây là một rule rất thư giãn vì nó hoàn toàn không giới hạn cho những packet đi ra, miễn sao nó đi ra từ IP và xuyên qua IF đã định. Đối với người dùng cá nhân, rule này rất thích hợp vì bạn không muốn tự hạn chế đường ra (ngoại trừ bạn có dụng ý bảo mật khác).

Diễn dịch luật này thành ngôn ngữ bình thường như sau: mọi packets từ IP hiện dụng (-s $IP) xuyên qua interface eth0 (-o $IF) đi ra ngoài thì được chấp nhận (-j ACCEPT).

- Dòng 11: Đây là dòng xác định INPUT rule cho mọi packet đi đến IP và IF (đã xác định ở dòng 1 và 2). Rule này chỉ khác OUTPUT rule ở thông số và giá trị thông số -m state --state ESTABLISHED,RELATED. Điểm tối quan trọng cũng nằm ở đây. Nếu rule trên không có thông số và giá trị của thông số -m state thì firewall này hoàn toàn vô dụng bởi vì nó cho phép bất cứ giao thức nào, ở tình trạng nào cũng có thể lưu thông. Với -m state, packets đi vào sẽ được kiểm duyệt tình trạng của packets thoả mãn điều kiện ESTABLISHED hoặc RELATED. Cũng nên đào sâu vài điểm về tình trạng ESTABLISHED và RELATED ở đây:

- Một packet ở tình trạng ESTABLISHED có nghĩa nó thuộc một xuất truy cập (connection) đã hình thành và xuất truy cập này đã có diễn tiến trao đổi các packet từ hai phía "gởi và nhận". Với các luật ở dòng 10 và 11, chúng ta dễ thấy chỉ có packet từ firewall đi ra mới có thể ở tình trạng NEW để khởi tạo một xuất truy cập. Hay nói một cách khác, firewall của bạn "hỏi" thì đối tượng nào đó từ Internet mới "trả lời". Packet ở tình trạng ESTABLISHED có nghĩa là nó đã thông qua giai đoạn "hỏi / trả lời" một cách hợp thức. Điều này cũng có nghĩa, packets từ bên ngoài đi đến $IP xuyên qua $IF sẽ không được tiếp nhận ở tình trạng NEW và INVALID cho nên các packets nào "hỏi" (NEW) hoặc "chen ngang" (INVALID) từ bên ngoài đến firewall sẽ bị chặn (tham khảo thêm tài liệu căn bản về iptables cho 4 states được sử dụng).

- Packet ở tình trạng RELATED không thấy nhiều như packet ở tình trạng ESTABLISHED bởi vì RELATED packet chỉ xuất hiện khi một xuất truy cập mới cần được thiết lập dựa trên tình trạng một xuất truy cập đang có đã được thiết lập một cách hợp pháp. Loại packet này có thể thấy ở giao thức FTP sau khi phân đoạn kết nối và xác minh người dùng (authentication) trên cổng 21 đã hoàn thành và cần thiết lập cổng dữ liệu 20 để chuyển tải dữ liệu. Ở đây, vì giao thức qua cổng 21 ở dạng ESTABLISHED cho nên cổng 20 được phép thiết lập thêm và phân đoạn này tạo ra packet thuộc dạng RELATED. Packet ở tình trạng RELATED cũng thường thấy ở các ICMP packets ở dạng trả lời (replies).

- -m state ở trên là một trong những tính năng thuộc dạng SPI -1- (stateful packet inspection - kiểm soát đa thể trạng) của iptables. Trước đây, với kernel 2.2.x series và ipchains (tiền thân của iptables), các packets được kiểm soát ở giới hạn loại packet và không thể kiểm soát ở biên độ tình trạng packet. Tính năng đa thể trạng này không những giúp bạn đơn giản hoá nhóm luật cho firewall của mình mà còn tạo nên một firewall linh động và vững vàng hơn rất nhiều. Nếu không dùng -m state ở đây, ít nhất bạn phải mở một loạt cổng nào đó (dãy 32000 - 64000 chẳng hạn) để các packets từ bên ngoài có thể đi vào để "trả lời" các requests bạn tạo ra. Đây là một phương thức có thể tạo những điểm yếu cho firewall, đó là chưa kể đến tính luộm thuộm khi phải cho phép chuỗi cổng cho mỗi loại giao thức (tcp / udp) và loại icmp ra vào cho thích hợp.

Diễn dịch luật này thành ngôn ngữ bình thường như sau: mọi packets từ bên ngoài Internet đi vào IP hiện dụng (-s $IP) xuyên qua interface eth0 (-i $IF) vào trong máy ở chế độ ESTABLISHED,RELATED thì được chấp nhận (-j ACCEPT).

7. Tổng lượt dạng firewall trên:
Nhìn vào vài dòng luật của firewall trên, chắc chắn có người sẽ thắc mắc và sẽ hỏi chỉ có vậy thôi sao?.

Câu trả lời ngắn: chỉ có vậy nếu chỉ cần như vậy.

Câu trả lời dài: cho một máy đơn và người dùng được quyền gởi bất cứ yêu cầu truy cập trên bất cứ giao thức nào từ bên trong máy ra ngoài cũng như cản bất cứ yêu cầu truy cập trên mọi giao thức từ bên ngoài vào thì vài dòng luật như vậy là đủ. Như bạn biết, trong khi máy chạy trên Linux sẽ có một số dịch vụ đang lắng nghe (LISTEN). Những dịch vụ này chỉ phục vụ cho riêng bạn và bạn không muốn bất cứ ai từ Internet truy cập vào các dịch vụ này. Luật ở dòng 11 ấn định: các packet đi vào (INPUT) chỉ có thể ở dạng ESTABLISHED và RELATED cho nên một đòi hỏi truy cập mới (new request) từ Internet vào không thể được hình thành. Khi một packet như vậy đi vào firewall, firewall sẽ kiểm tra xem có luật INPUT nào thích hợp cho phép nó đi vào, nếu không firewall sẽ cản nó theo quy định của quy chế mặc định (-P) là DROP. Ở đây bạn có một luật INPUT duy nhất và luật này quy định rất cụ thể tình trạng packet được cho phép vào. Khi packet từ bên ngoài Internet vào, firewall sẽ kiểm tra packet này:
- nếu nó hoàn toàn mới và không hề hiện diện trong bản tình trạng (conntrack table) của netfilter -2- thì packet này bị cản.
- nếu nó đã hiện diện trong state table của netfilter thì nó được tiếp tục đi vào.

8. Mở rộng:
8.1. Vấn đề logging:
Với các luật firewall trên, khi xét kỹ, bạn sẽ thấy thiếu một yếu tố rất quan trọng đó là thông tin logging. Nếu bạn muốn biết có bao nhiêu trường hợp các packets "vi phạm" (bên ngoài các luật cho phép của firewall trên), bạn cần dùng target LOG. Vậy đưa vào các luật để thâu thập các thông tin vi phạm ở đâu? Bạn chỉ cần thêm vài dòng tiếp theo sau dòng 11 ở trên như sau:

Code:
12. $IPT -A INPUT -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_INPUT: "
13. $IPT -A INPUT -i $IF -d $IP -j DROP
14. $IPT -A OUTPUT -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_OUTPUT: "
15. $IPT -A OUTPUT -o $IF -d $IP -j DROP
16. $IPT -A FORWARD -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_FORWARD: "
17. $IPT -A FORWARD -i $IF -d $IP -j DROP



- Các luật trên đôi khi còn được gọi là "clean-up rules", nói theo thuật ngữ chuyên môn của firewall. Lý do chúng được gọi là "clean-up rules" vì chúng đóng vai trò "dọn dẹp" cho các luật đứng trước chúng. Các luật ở dòng 12, 13, 14, 15 ,16 và 17 có chức năng tương tự nhau, chỉ khác ở một điểm là mỗi cặp 12-13, 14-15, 16-17 có tác dụng cho các chains (INPUT, OUTPUT và FORWARD) riêng biệt.

- Diễn dịch luật ở dòng 12 thành ngôn ngữ bình thường như sau: mọi packets đi vào thuộc chain INPUT, xuyên qua interface $IF đến địa chỉ $IP sẽ được log với prefix là "BAD_INPUT" ở chế độ --log-level 5 và ở giới hạn là 1 giây.
- Kế tiếp, ở dòng 13: vào thuộc chain INPUT, xuyên qua interface $IF đến địa chỉ $IP sẽ bị cản (sau khi bị LOG ở trên).
- Dòng 14, 15, 16 và 17 tương tự như trên cho chain OUTPUT và FORWARD.

Vậy điểm cần nhấn mạnh ở đây là vị trí của các luật trong một nhóm luật. Nếu các luật ở dòng 12-17 nằm trên các luật ở dòng 10-11 thì chắc chắn firewall của bạn trở nên vô dụng vì không có bất cứ packets nào có thể đi vào và đi ra vì, hễ một packet nào đi vào và đi ra đều "trùng" với luật đã ấn định (và đã diễn dịch ở trên). Tuy nhiên, khi các luật ở dòng 12-17 nằm dưới các luật dòng 10-11 thì chúng trở thành ích lợi. Một packet đi vào theo trình tự các luật đặt sẵn trong firewall trên, chúng ta sẽ thấy:
- nếu packet đó đi vào để "trả lời" cho một đòi hỏi từ firewall khởi tạo trước thì nó được phép đi vào (áp đặt bởi luật dòng 11).
- nếu packet đó đi vào mà không thoả mãn luật ở dòng 11, nó tiếp tục "bị" xét duyệt bởi các luật đi theo sau. Ở đây, dòng 12 và 13 chắc chắn sẽ "tóm" được packet vi phạm và sẽ được xử lý theo ấn định cho các packet đi vào (thuộc chain INPUT).
- nếu không có các luật đưa ra ở dòng 12, 13, 14, 15, 16 và 17 thì các packet không thoả mãn được luật đã ấn định của firewall cũng sẽ bị cản bằng chế độ đưa ra ở dòng 6, 7, 8 nhưng cản một cách im lặng. Điểm khác biệt ở đây là luật cụ thể ở dòng 12, 13, 14, 15, 16 và 17 sẽ tạo ra log trong /var/log/messages (theo mặc định) cho những packet vi phạm và sẽ cản chúng một cách cụ thể.

8.2. Cản các lưu thông cụ thể
Đối với các lưu thông đi vào INPUT chain, luật ở dòng 11 đã khá vững vì không có gói tin nào từ bên ngoài có thể đi vào nếu như bạn không gởi "request" ra trước. Cho nên, chúng ta chỉ mở rộng ở OUTPUT chain ở đây.

8.2.1 Cản trọn bộ trước, cho phép cụ thể sau
Câu hỏi được đặt ra là các loại lưu thông cụ thể nào cần được cản? Vấn đề này phụ thuộc vào mức cẩn thận (hoặc paraniod)hoặc nhu cầu của từng người dùng. Với một cá nhân muốn truy cập bất cứ nơi đâu, bằng bất cứ giao thức nào thì dòng 10 thuộc phần 5 ở trên hoàn toàn đáp ứng nhu cầu này. Tuy nhiên, với một cá nhân chỉ cần duyệt web và chat bằng Yahoo Instance Messenger chẳng hạn thì giới hạn này có thể thu hẹp lại rất nhiều. Trong trường hợp này, dòng 10 thuộc phần 5 ở trên có thể được thay thế bởi một dòng như sau:

Code:
$IPT -A OUTPUT -o $IF -s $IP -p tcp -d any/0 -m multiport --dport 80,443,5050 -j ACCEPT



Dòng trên có thể được diễn dịch nôm na: các lưu thông đi đến bất cứ địa chỉ nào (-d any/0) bằng giao thức tcp (-p tcp đến cổng 80 (cổng 443 và cổng 5050) (--dport 80,443,5050) -3- thì được chấp nhận. Dòng trên không đề cập đến vấn đề "state" của các gói tin (-m state) như ở dòng 11 thuộc phần 5, điều này có nghĩa các lưu thông này có thể đi ra ngoài ở bất cứ state nào tùy thích. Tuy nhiên, nếu bạn paranoid hơn nữa thì chêm vào một đoạn -m state thì càng vững hơn, ví dụ:

Code:
$IPT -A OUTPUT -o $IF -s $IP -p tcp -d any/0 -m multiport --dport 80,443,5050 -m state state NEW,ESTABLISHED -j ACCEPT



Dòng trên tương tự như ví dụ trước nhưng chỉ định thêm là các gói tin ở tình trạng NEW và ESTABLISHED thì mới được đi ra ngoài; những gói tin ở dạng RELATED và INVALID sẽ bị cản. Lý do, giao thức http và giao thức dành cho YIM không cần đến tình trạng RELATED và các gói tin ở tình trạng INVALID thì càng nên không cho phép lưu thông. Tất nhiên nếu bạn muốn dùng POP3 và SMTP thì phải thêm giá trị 25 và 110 cho chuỗi --dport ở trên.

Nếu đã thực sự "paranoid" như vậy thì tại sao không xác lập thêm một luật cho giao thức UDP? Nếu bạn không có nhu cầu gì đặc biệt thì có lẽ cổng 53 cho DNS là cổng cần thiết nhất:

Code:
$IPT -A OUTPUT -o $IF -s $IP -p udp -d <DNS_của_ISP> --dport 53 -m state state NEW,ESTABLISHED -j ACCEPT


8.2.2 Cho phép trọn bộ trước, cản các cổng cụ thể sau
Trường hợp người dùng muốn tự do truy cập bất cứ nơi đâu, bằng bất cứ giao thức nào nhưng không muốn máy của mình "tự động" truy cập đến các cổng "nguy hại" (ví dụ như máy vô tình bị nhiễm trojan và bị biến thành zombie -4- để tham gia trong các cuộc tấn công từ chối dịch vụ chẳng hạn). Trong trường hợp này, cách giản tiện nhất là thêm hai dòng phía trên dòng 10 thuộc phần 5:

Code:
$IPT -A OUTPUT -o $IF -s $IP -p tcp -d any/0 -m multiport --dport 54321,12345 -j DROP
$IPT -A OUTPUT -o $IF -s $IP -p udp -d any/0 -m multiport --dport 54321,12345 -j DROP


Hai dòng trên chỉ định các gói tin đi ra ngoài và đến các cổng trong chuỗi -5- ở trên sẽ bị cản (các cổng nêu ra ở đây chỉ là một ví dụ, không cụ thể áp đặt tính nguy hại của các cổng trên trên thực tế). Lý do chúng ta phải thiết lập hai dòng luật tách biệt vì mỗi dòng dành riêng cho mỗi giao thức và lý do hai dòng trên phải được đặt trước dòng thứ 10 vì những gói tin đi ra phải được kiểm tra trước khi có thể đi ra. Như đã đề cập ở phần 8.1, vị trí các luật là một yếu tố tối quan trọng, đây là yếu tố quyết định các luật của firewall hữu dụng hay vô dụng.


9. Thử nghiệm:
9.1 Thử nghiệm 1:
Giả sử bạn có một dịch vụ đang chạy trên máy (telnet chẳng hạn, hoặc bất cứ dịch vụ nào hiện có trên máy). Sau khi đã ứng động firewall trên, bạn thử nhờ một người bạn nào khác tìm cách truy cập vào dịch vụ telnet này. Tất nhiên bạn phải cung cấp địa chỉ IP cho người bạn ấy.
- người bạn ấy sẽ thử: telnet <địa_chỉ_IP_của_bạn> 23 --> việc này sẽ tạo SYN packet từ bên ngoài vào cổng 23 đã được cản (filtered port) vì firewall trên không hề cho phép bất cứ truy cập nào khởi tạo từ bên ngoài.

- bạn xem thử syslog: tail -f /var/log/message | grep '<địa_chỉ_IP_của_người_bạn>'
- bạn xem /proc/net/ip_conntrack: cat /proc/net/ip_conntrack | grep '<địa_chỉ_IP_của_người_bạn>'
- bạn theo dõi tcpdump: tcpdump tcp port 23


9.2 Thử nghiệm 2:
Giả sử bạn đã ứng dụng các luật "paranoid" ở phần 8.2.1, chỉ cho phép từ máy truy cập đến cổng 80, 443 và 5050 cho tcp và cổng 53 cho udp. Sau khi ứng động firewall trên, bạn thử:
- truy cập đến một website không dùng cổng 80 tiêu chuẩn mà dùng cổng khác như 8000, 8080 chẳng hạn, ví dụ: http://www.awebsite.com:8000.
- bạn xem thử syslog: tail -f /var/log/message | grep '<địa_chỉ_IP_của_website_bạn_truy_cập>'
- bạn xem /proc/net/ip_conntrack: cat /proc/net/ip_conntrack | grep '<địa_chỉ_IP_của_website_bạn_truy_cập>'
- bạn theo dõi tcpdump: tcpdump tcp port <cổng_website_dùng>


Qua hai thử nghiệm trên, chắc chắn bạn sẽ tìm thấy rất nhiều thông tin mới lạ và đây chính là cánh cửa mở rộng cho những điều đằng sau một nhúm firewall script đơn giản như trên.

10. Kết luận:
iptables thật sự không phức tạp. Điều thật sự phức tạp là quá trình phân tích và xác định chức năng của một firewall cho một nhu cầu cụ thể nào đó. Trong quá trinh phân tích và xác định này, bạn sẽ phải đi sâu vào vấn đề khảo sát và thu thập những thông tin cần thiết để hoàn thành một nhóm luật bảo vệ máy của mình. Đây cũng chính là điểm lý thú và bổ ích trong suốt quá trình thiết lập bởi vì chắc chắn bạn sẽ không chỉ dừng lại ở phạm vi một firewall và firewall đó làm được gì. Bài viết này tôi chủ ý đào sâu vào tính năng "stateful" của iptables và bỏ qua những chi tiết thuộc kỹ năng tạo shell script, run level script... Tùy bạn chọn lựa cách điều chỉnh script theo ý mình và chỉnh init script (run level) tùy môi trường.

11. Bị chú:
-1- SPI: Stateful Packet Inspection hay dịch nôm na sang tiếng Việt là "kiểm soát đa thể trạng", một khái niệm được đưa ra vào những năm đầu của thập niên 90 và được ứng dụng rộng rãi cho các firewall "hiện đại". Tính "stateful" được khai triển dựa trên tính chất của giao thức TCP. Riêng với iptables, tính "stateful" này không những ứng dụng cho TCP mà còn cho UDP (được biết như một giao thức có tính stateless) và icmp. Dựa trên tính chất của từng loại giao thức, iptables / netfilter lưu trữ tình trạng diễn tiến của các packets trong bảng theo dõi (state table).

-2- netfilter thuộc kernel side, iptables thuộc user side. Xem thêm các thông tin này trên website http://www.iptables.org

-4- zombie: một bán thuật ngữ bảo mật ngầm chỉnh định cho các máy bị nhân nhượng và có thể được sai khiến từ một hoặc nhiều máy từ xa để thực hiện các ý định cụ thể nào đó.

-3,5- iptables cho phép 15 cổng trong chuỗi comma delimeter (,) cho giá trị --dport (destination port) và --sport (source port) nếu dùng match -m multiport. Dùng cách này hiệu năng hơn cách dùng từng dòng luật cho mỗi cổng cần cản hoặc cần cho phép.

Liệt kê nhóm luật "paranoid" cho phần 8.2.1:

Code:
1. IF=`/sbin/route | grep -i 'default' | awk '{print $8}'`
2. IP=`/sbin/ifconfig $IF | grep "inet addr" | awk -F":" '{print $2}' | awk '{print $1}'`
3. IPT="/usr/local/sbin/iptables"
4. ISP_DNS="xxx.xxx.xxx.xxx"
5. $IPT -F
6. $IPT -P INPUT DROP
7. $IPT -P OUTPUT DROP
8. $IPT -P FORWARD DROP
9. $IPT -A OUTPUT -o $IF -s $IP -p tcp -d any/0 -m multiport --dport 80,443,5050 -m state state NEW,ESTABLISHED -j ACCEPT
10. $IPT -A OUTPUT -o $IF -s $IP -p udp -d $ISP_DNS --dport 53 -m state state NEW,ESTABLISHED -j ACCEPT
11. $IPT -A INPUT -i $IF -d $IP -m state --state ESTABLISHED,RELATED -j ACCEPT
12. $IPT -A INPUT -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_INPUT: "
13. $IPT -A INPUT -i $IF -d $IP -j DROP
14. $IPT -A OUTPUT -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_OUTPUT: "
15. $IPT -A OUTPUT -o $IF -d $IP -j DROP
16. $IPT -A FORWARD -i $IF -d $IP -m limit --limit 1/s -j LOG --log-level 5 --log-prefix "BAD_FORWARD: "
17. $IPT -A FORWARD -i $IF -d $IP -j DROP



Tác giả : Conmale(hnd)
Nguồn : www.diendantinhoc.net

=========================================================
quanta: Tớ chèn thêm 1 khoảng trắng vào giữa print$x để bài viết chính xác hơn.
Bài viết này sẽ hướng dẫn cấu hình máy Linux sử dụng samba và cups cho việc dùng máy in đang nối vào máy Windows trong mạng nội bộ.

1. Trên máy Linux:

a. Phần mềm CUPS:
. Tập tin /etc/cups/printers.conf có nội dung như bên dưới:
(DefaultPrinter officejet)
Info remote
Location remote
DeviceURI smb://guest@MSWIN/192.168.1.4/officejet
State Idle
Accepting Yes
JobSheets none none
QuotaPeriod 0
PageLimit 0
KLimit 0
(/Printer)

Thay ngoặc đơn, DefaultPrinter officejet và /Printer, với ngoặc mũi tên. officejet là tên máy in trên Windows, MSWIN là tên WORKGROUP, 192.168.1.4 là địa chỉ máy Windows. Máy Windows dĩ nhiên phải cho phép guest đăng nhập (không có mật khẩu). Nếu máy Windows dùng tài khoản người dùng thì bạn có thể dùng
DeviceURI smb://id:password@MSWIN/192.168.1.4/officejet

b. Phần mềm Samba:
. Nội dung của tập tin /etc/samba/smb.conf:
Bạn có thể tải về tập tin smb.conf từ đây và lưu lại trong /etc/samba thành smb.conf

c. Chạy dịch vụ samba và cups

2. Trên máy Windows:

Bạn chỉ việc cho phép máy in Sharing, với tên là officejet (xem hình bên dưới), nếu bạn định dùng tài khoản guest thì nên xem lại đã mở tài khoản này.








Để quản lý máy in từ Linux, bạn có thể dùng phần mềm quản lý máy in có sẵn. Nếu không bạn cũng có thể dùng CUPS để quản lý bằng cách mở browser và gõ vào http://localhost:631 với người dùng root và mật khẩu.

larry - vnlinux.org
Thiết kế mạng không dây: Dùng Linux làm Access Point

Có lẽ chẳng còn lâu nữa mạng không dây [1] sẽ được sử dụng rộng rãi khắp nơi. Từ thư viện đến quán cà phê, từ trạm xe điện đến sân bay, khách sạn, từ nhà bạn đến nhà hàng xóm, mọi người sẽ sử dụng mạng không dây. Bạn có biết là nếu nhà bạn có mạng không dây thi hàng xóm sẽ có thể 'share' mạng với bạn mà không cần có một internet account? Hoặc nếu bạn chuẩn bị thiết kế mạng cho nhiều văn phòng trong một tòa nhà, hoặc từ tòa nhà này sang tòa nhà khác (cách nhau trong khoảng 457m hay 1500ft) mà chưa có dây cáp thì có lẽ mạng không dây là một trong những thiết kế có thể sử dụng. Nhưng bác Larry ơi mạng không dây đắt tiền lắm. Không hẵn! Bạn Chương Đào có nói độ này card mạng cho mạng không dây có thể mua khoảng $27 (loại USB) hoặc thấp hơn.

Bài viết sau sẽ giải thích cách cài đặt mạng không dây 802.11b sử dụng Linux. Có rất nhiều loại mạng không dây khác nhau nhưng bài viết này sẽ dùng 802.11b và trong vòng nữa giờ bạn có thể sử dụng mạng không dây để đọc VietLUG mailing list smilie

Muốn thiết kế mạng không dây bạn cần có:

1. Một máy chạy Windows sẽ làm Access Point (AP)

2. Một card mạng cho mạng không dây

3. Một internet connection (dsl, cable modem, dial-up modem)

4. Và dĩ nhiên một máy làm client.


À quên số 1. nên viết là 'Một máy chạy Linux sẽ làm Access Point' chứ không phải Windows.

Muốn dùng máy Linux để làm AP thì bạn cần phải sử dụng card mạng sử dụng chipset Intersil's Prism2/2.5/3. Thế cái chương trình gì cho phép Linux làm Access Point được vậy? Nó là HostAP viết bởi Jouni Malinen. Cho mục đích của bài viết mình sẽ sử dụng hai máy:

1. Access Point là máy Gentoo với card mạng NetGear PCI MA311

2. Wireless client là máy xách tay Mandrake với card mạng NetGear MA401.


Một số cards cũng sử dụng Prism2 chipset là Compaq WL100 and WL200, D-Link DWL-650 (not 650A nor 650B), and Linksys WPC11 (loại cũ), Orinoco/Lucent/Agere/Avaya cards. Nên nhớ bạn chỉ cần cái máy AP xài Prism2/2.5/3 chipset còn máy clients thì lam sao cards chạy đu+ợc trên Linux là đủ. Xem thêm danh sách của Prism2 cards tại đây [2]

Những bước chuẩn bị cho Access Point trên máy Gentoo:

1. Cài đặt hostap bằng lệnh:

emerge hostap

Nếu bạn không xài Gentoo thì có thể download HostAP driver từ đây. Sau đó cài đặt bằng lệnh:

. tar xvzf hostap-version.tar.gz
. cd hostap-version
. make pci

Nếu mọi chuyện êm xui thì gõ tiếp make install

2. Khởi động card với lệnh:

modprobe hermes

Lưu ý: nếu bản Linux của bạn đã khởi động card thì bạn không cần chạy lệnh này nữa.



3. Khởi động HostAP driver bằng lệnh:

modprobe hostap_pci

4. Chỉ định IP cho card bằng lệnh:

ifconfig wlan0 192.168.1.1

5. Tạo ID, channel, mode cho card bằng lệnh:

iwconfig wlan0 essid em_thèm_mạng_không_dây channel 1 mode master

essid: bạn muốn dùng từ gì cũng được. Đây là ID của mạng không dây.
channel: mình sử dụng giá trị từ 1 đến 11.
mode: nếu là Access Point thì mode phải là Master. Có 7 modes khác nhau: Master (Access Point), Managed, Ad-Hoc, Repeater, Secondary, Monitor, Auto.

6. Mở port forward và MASQUERADING với lệnh:

echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j MASQUERADE

Sáu bước trên đã kết thúc việc cài đặt cho máy AP. Nếu khi chạy lệnh iwconfig mà bị báo lỗi nghĩa là máy bạn chưa có wireless-tools cài đặt. Bạn có thể tải wireless-tools từ đây

Những bước chuẩn bị cho máy xách tay Mandrake:

1. Chỉ định IP, essid, mode cho card:

Mandrake sẽ tự động tìm thấy và khởi động card NetGear MA401 bạn chỉ cần chỉ định IP 192.168.1.[2..254], essid giống như của máy AP, trong ví dụ này là 'em_mê_mạng_không_dây', mode sẽ là 'Managed', default gateway là 192.168.1.1 bằnh cách sử dụng MandrakeControlCenter (lệnh mcc), chọn phần Network.

1.Non-Mandrake users có thể chạy những lệnh sau:

ifconfig eth0 192.168.1.2
iwconfig eth0 mode managed essid em_mê_mạng_không_dây channel

2. Đặt giá trị cho gateway bằng lệnh:

route add -net default gw 192.168.1.1

3. Xem lại giá trị của dns: bạn nên xài dns servers giống như máy AP bằng cách điền vào /etc/resolv.conf

Bây giờ thử ping 192.168.1.1 xem nó có reply không? Nếu có thì...xin chúc mừng! Mạng không dây của bạn đã hoạt động.

Vấn đề an toàn của mạng không dây:

Mạng không dây nổi tiếng với chuyện bị crackers vào system. Đó là lý do users hay dùng WEP (Wired Equivalent Privacy) encryption. Bạn có thể sử dụng WEP bằng lệnh $iwconfig wlan0 key your_encryption_key_or_alphanumerical_letters_here. Bạn cũng có thể có nhiều hơn một key, chỉ việc thay thế key bằng key1, key2 ..v..v..

Tuy nhiên sử dụng WEP vẫn không phải là biện pháp tối ưu. Gần đây các nhà nghiên cứu đang chuẩn bị giới thiệu một kiểu encryption mới cho mạng không dây (Wi-Fi Protected Access - WPA) nằm trong 802.11i. Bạn đừng lo 802.11i sẽ vẫn hoạt động tốt với 802.11a và b. Hiện tại trên thị trường cũng đã có 802.11g, khác với a và b là tốc độ có thể lên đến 54Mbps thay vì 11Mbps.

Cám ơn bạn Hoàng (dr bsd), bác Chương (dr foobar) đã nhiệt tình trao đổi kinh nghiệm về wireless với mình. Xin gởi feedback cho bài viết đến mạng_không_dây@vnlinux.org. Hy vọng bạn có thể dùng chút ít trong bài viết này cho việc thiết kế mạng trong tương lai.

HostAP http://hostap.epitest.fi/

Wireless tools for Linux http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html

[1] Mạng không dây: wireless network. Wi-Fi (wireless fidelity) là từ hay dùng cho wireless network. Bạn cũng sẽ nghe WLAN: wireless local area network.

[2] Danh sách card sử dụng Prism2 chipset http://www.personaltelco.net/index.cgi/Prism2Card

Tác giả: Larry - vnLinux.org
Bản dịch tiếng Việt của Giấy phép Công cộng GNU Hạn chế (LGPL)


Người dịch Đặng Minh Tuấn <dangtuan@vietkey.net> Đây là bản dịch tiếng Việt không chính thức của Giấy phép Công cộng GNU Hạn chế. Bản dịch này không phải do Tổ chức Phần mềm Tự do ấn hành, và nó không quy định về mặt pháp lý các điều khoản cho các phần mềm sử dụng giấy phép GNU LGPL -- chỉ có bản tiếng Anh gốc của GNU LGPL mới có thể làm được như vậy. Tuy nhiên, chúng tôi hy vọng rằng bản dịch này sẽ giúp cho những người nói tiếng Việt hiểu rõ hơn về GNU LGPL.

This is an unofficial translation of the GNU Lesser General Public License into Vietnamese. It was not published by the Free Software Foundation, and does not legally state the distribution terms for software that uses the GNU LGPL--only the original English text of the GNU LGPL does that. However, we hope that this translation will help Vietnamese speakers understand the GNU LGPL better.

Giấy phép công cộng GNU hạn chế (LGPL)

Phiên bản 2.1 , tháng 2 năm 1999

Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
Ai cũng được phép sao chép và lưu hành bản sao nguyên bản nhưng không được phép thay đổi nội dung của giấy phép này.

[Đây là phiên bản đầu tiên của Giấy phép GNU Hạn chế. Giấy phép này cũng được coi là phiên bản kế tiếp của Giấy phép công cộng GNU, phiên bản 2.0, do đó nó có phiên bản là 2.1.]


Lời nói đầu

Giấy phép sử dụng của hầu hết các phần mềm đều được đưa ra nhằm hạn chế bạn tự do chia sẻ và thay đổi nó. Ngược lại, Giấy phép Công cộng của GNU có mục đích đảm bảo cho bạn có thể tự do chia sẻ và thay đổi phần mềm tự do - tức là đảm bảo rằng phần mềm đó là tự do đối với mọi người sử dụng.

Giấy phép Công cộng GNU hạn chế này được áp dụng cho các gói phần mềm – đặc biệt là các thư viện -- của Tổ chức Phần mềm Tự do hoặc của các tác giả quyết định sử dụng giấy phép này. Bạn cũng có thể sử dung nó, nhưng theo chúng tôi bạn nên suy nghĩ kỹ lưỡng liệu nên sử dụng giấy phép này hoặc Giấy phép công cộng GNU bình thường cho từng trường hợp cụ thể, căn cứ theo những điều khoản dưới đây.

Khi nói đến phần mềm tự do, chúng ta nói đến sự tự do sử dụng chứ không quan tâm đến giá cả. Giấy phép Công cộng của chúng tôi được thiết kế để đảm bảo rằng bạn hoàn toàn tự do cung cấp các bản sao của phần mềm tự do (cũng như kinh doanh dịch vụ này nếu bạn muốn); rằng bạn có thể nhận được mã nguồn nếu bạn muốn; rằng bạn có thể sửa đổi phần mềm hoặc sử dụng các thành phần của phần mềm đó cho những chương trình tự do mới; và rằng bạn được thông báo là bạn có thể làm được những điều này.

Để bảo vệ quyền của bạn, chúng tôi cần đưa ra những hạn chế để ngăn chặn những ai chối bỏ quyền của bạn, hoặc yêu cầu bạn chối bỏ quyền của mình. Những hạn chế này cũng có nghĩa là những trách nhiệm nhất định đối với bạn khi bạn cung cấp các bản sao của thư viện hoặc khi chỉnh sửa thư viện đó.

Ví dụ, nếu bạn cung cấp các bản sao của một thư viện, dù miễn phí hay không, bạn phải cho người nhận tất cả các quyền mà bạn có. Bạn cũng phải đảm bảo rằng họ cũng nhận được hoặc có thể nhận được mã nguồn. Nếu bạn liên kết mã nguồn khác với thư viện, bạn phải cung cấp các tập tin đã dich cho người nhận sao cho họ có thể liên kết lại được sau khi sửa đổi và dịch lại thư viện. Và bạn phải giới thiệu những điều khoản này cho họ để họ biết rõ về quyền của mình.

Chúng tôi bảo vệ quyền của bạn với hai bước: (1) bảo vệ bản quyền thư viện phần mềm, và (2) cung cấp giấy phép này để bạn có thể sao chép, lưu hành và/hoặc chỉnh sửa thư viện một cách hợp pháp.

Để bảo vệ người phân phối, chúng tôi cần phải làm rõ rằng không có bảo hành cho những thư viện tự do. Nếu một người nào đó chỉnh sửa và sau đó phân phối nó, thì chúng tôi muốn những người sử dụng biết rằng cái họ đang có không phải là bản gốc, do đó tất cả những vấn đề, lỗi do những người khác gây ra hoàn toàn không ảnh hưởng tới uy tín của tác giả ban đầu.

Cuối cùng, bất kỳ một chương trình tự do nào cũng đều thường xuyên có nguy cơ bị đe doạ bởi giấy phép bản quyền. Chúng tôi muốn chắc chắn rằng các công ty không thể hạn chế người sử dụng đối với phần mềm tự do khi các công ty này có giấy phép từ những người nắm giữ bản quyền. Bởi vậy, chúng tôi yêu cầu mỗi giấy phép bản quyền cho thư viện cần phải được đảm bảo hoàn toàn tự do sử dụng theo giấy phép này.

Phần lớn các phần mềm GNU, kể cả một số thư viện, được bảo vệ theo Giấy phép Công cộng thông thường. Giấy phép này, Giấy phép Công cộng Hạn chế, được áp dụng cho những thư viện có mục đích xác định, khác hẳn so với Giấy phép Công cộng thông thường. Chúng ta sử dụng Giấy phép này cho mục đích liên kết những thư viện đó vào những phần mềm không tự do.

Khi chương trình được liên kết với một thư viện, dù liên kết tĩnh hay liên kết động, thì kết hợp của hai thành phần đó về mặt pháp lý là một sản phẩm kết hợp, có nguồn gốc từ thư viện gốc ban đầu. Giấy phép Công cộng thông thường chỉ cho phép những liên kết đó nếu toàn bộ sự kết hợp phải thoả mãn điều kiện tự do. Giấy phép Công cộng hạn chế đưa ra những điều kiện ràng buộc ít hơn khi liên kết mã nguồn khác với thư viện.

Chúng tôi gọi giấy phép này là Giấy phép Công cộng “Hạn chế” bởi vì nó bảo vệ quyền tự do của người sử dụng ở mức độ hạn chế hơn so với Giấy phép Công cộng thông thường. Nó cũng hạn chế tính ưu việt trong việc cạnh tranh với những phần mềm không tự do đối với những nhà phát triển phần mềm tự do khác. Những hạn chế này cũng là lý do tại sao chúng ta dùng Giấy phép Công cộng thông thường cho đa số các thư viện. Tuy nhiên Giấy phép Công cộng Hạn chế cũng có những ưu điểm trong một số trường hợp xác định.

Ví dụ, trong một số hãn hữu trường hợp, cần phải quảng bá, phân phối rộng nhất có thể được đối với một số thư viện để sao cho nó sẽ thành chuẩn “thực tế” (de facto). Để làm được điều này, cần phải cho phép những phần mềm không tự do cũng có thể sử dụng được thư viện này. Trường hợp phổ biến hơn là, khi thư viện tự do có cùng chức năng giống thư viện không tư do đang được dùng phổ biến, trong trường hợp này thì thư viện tự do sẽ hạn chế sử dụng chỉ trong các phần mềm tự do, vì vậy chúng ta cần sử dụng Giấy phép Công cộng hạn chế (để có thể nâng cao miền ảnh hưởng).

Trong các trường hợp khác, việc cho phép sử dụng một số bộ thư viện nào đó được sử dụng trong các phần mềm không tự do sẽ tạo ra một số lượng lớn hơn người sử phần mềm tự do. Ví dụ, việc cho phép sử dụng bộ thư viện GNU C trong phần mềm không tự do sẽ khuyến khích nhiều người sử dụng hệ điều hành GNU cũng như các biến thể của nó, hệ điều hành GNU/LINUX.

Mặc dù Giấy phép Công cộng Hạn chế sẽ bảo vệ quyền tự do của người sử dụng ít hơn, nhưng nó vấn đảm bảo rằng người sử dụng phần mềm được liên kết với một thư viện xác định có sự tự do và đủ quyền để thực thi chương trình sử dụng phiên bản sửa đổi của thư viện đó.

Dưới đây là những điều khoản và điều kiện rõ ràng đối với việc sao chép, lưu hành và chỉnh sửa. Bạn hãy đặc biệt lưu ý sự khác nhau giữa hai khái niệm “Sản phẩm dựa trên bộ thư viện” và “Sản phẩm sử dụng bộ thư viện”, sản phẩm thứ nhất chứa mã nguồn được có nguồn gốc từ thư viện, còn sản phẩm thứ hai cần phải liên kết với thư viện mỗi khi thực thi.

NHỮNG ĐIỀU KHOẢN VÀ ĐIỀU KIỆN ĐỐI VỚI VIỆC SAO CHÉP, LƯU HÀNH VÀ CHỈNH SỬA

0. Giấy phép này áp dụng cho bất kỳ một thư viện hay một chương trình mà người giữ bản quyền công bố rằng nó có thể được cung cấp trong khuôn khổ những điều khoản của Giấy phép Công cộng Hạn chế này. Mỗi người được cấp phép được gọi là “bạn”.

Từ “thư viện” có nghĩa là tập hợp các hàm và/hoặc dữ liệu được chuẩn bị sao cho có thể dễ dàng liên kết với các chương trình (có sử dụng các hàm và dữ liệu này) để tạo thành chương trình hoàn chỉnh có thể thực thi được.

Từ “Thư viện” dưới đây có nghĩa là tất cả các thư viện chương trình hay sản phẩm được phân phối theo các điều khoản của giấy phép này. Sản phẩm dựa trên bộ Thư viện là Thư viện hoặc sản phẩm bắt nguồn từ Thư viện đó theo luật bản quyền, nghĩa là một sản phẩm chứa đựng Thư viện hoặc một phần của nó, hoặc đúng nguyên bản hoặc có một số chỉnh sửa và/hoặc được dịch ra một ngôn ngữ khác. (Sau đây, việc dịch được bao gồm nhưng không hạn chế trong khái niệm “chỉnh sửa”).

“Mã nguồn” của sản phẩm là một dạng của sản phẩm thường được dùng để chỉnh sửa sản phẩm đó. Toàn bộ mã nguồn của một thư viện là tất cả mã nguồn của tất cả các mô-đun của thư viện đó, cộng với các tập tin định nghĩa giao diện tương ứng, cộng với các tập tin lệnh (scripts) được sử dụng để điều khiển quá trình biên dịch và cài đặt bộ thư viện.

Trong Giấy phép này không đề cập tới các hoạt động khác ngoài việc sao chép, lưu hành và chỉnh sửa; chúng nằm ngoài phạm vi của giấy phép này. Hành động chạy chương trình sử dụng Thư viện không bị hạn chế, và những kết quả từ việc chạy chương trình chỉ được đề cập tới nếu nội dung của nó tạo thành một sản phẩm dựa trên Thư viện (độc lập với việc sử dụng Thư viện tromg công cụ để viết ra nó). Điều này đúng hay không là phụ thuộc vào Thư viện thực hiện những gì và chương trình sử dụng Thư viện này thực hiện những gì.
.
1. Bạn có thể sao chép và lưu hành những bản sao nguyên bản của toàn bộ mã nguồn Thư viện đúng như khi bạn nhận được, qua bất kỳ phương tiện nào, với điều kiện trên mỗi bản sao bạn đều kèm theo một ghi chú bản quyền rõ ràng và từ chối bảo hành; giữ nguyên tất cả các ghi chú theo Giấy phép này và về việc không có bất kỳ một sự bảo hành nào; và cùng với Thư viện bạn cung cấp cho người sử dụng một bản sao của Giấy phép này.

Bạn có thể tính phí việc chuyển giao vật lý cho mỗi bản sao, và tuỳ theo quyết định của mình bạn có thể cung cấp bảo hành để đổi lại với chi phí mà bạn đã tính.

2. Bạn có thể chỉnh sửa bản sao của bạn hoặc các bản sao của Thư viện hoặc của bất kỳ phần nào của nó, từ đó hình thành một sản phẩm dựa trên Thư viện, và sao chép cũng như phân phối sản phẩm đó hoặc những chỉnh sửa đó theo điều khoản trong Mục 1 trên đây, khi bạn đáp ứng được những điều kiện dưới đây:
• a) Sản phẩm đã chỉnh sửa cũng là một thư viện phần mềm.
• b) Bạn phải có ghi chú rõ ràng trong những tệp tin đã chỉnh sửa là bạn đã chỉnh sửa nó, và ngày tháng của bất kỳ một thay đổi nào.
• c) Bạn phải cấp giấy phép miễn phí cho tất cả các bên thứ ba toàn bộ sản phẩm theo những điều khoản của Giấy phép này.
• d) Nếu một chức năng nào đó trong Thư viện đã sửa đổi liên quan đến một hàm nào đó hoặc một bảng dữ liệu nào đó được cung cấp đi kèm với một phần mềm, mà phần mềm này sử dụng chức năng đó khác với việc truyền tham số khi chức năng đó được thực hiện, thì bạn phải cố gắng đảm bảo rằng trong trường hợp chương trình không cung cấp kèm hàm và bảng dữ liệu thì chức năng đó vẫn phải hoạt động và thực hiện sao cho bất kỳ mục đích nào của nó vẫn phải có ý nghĩa.

(ví dụ: một hàm trong thư viện dùng để tính căn bậc 2 được thiết kế để tính với những giá trị được định nghĩa từ trước trong ứng dụng, vì vậy mục 2d yêu cầu rằng bất kỳ hàm hay bảng dữ liệu bất kỳ nào được sử dụng bởi hàm của thư viện sẽ không bị phụ thuộc, nếu chương trình không cung cấp kèm theo chúng thì hàm tính căn bậc 2 vẫn phải tính được căn bậc 2) .

Yêu cầu này được áp dụng cho sản phẩm chỉnh sửa một cách tổng thể. Nếu một phần xác định nào đó của sản phẩm không có nguồn gốc từ Thư viện và nó có thể được coi và tách riêng thành sản phẩm độc lập thì Giấy phép này với các điều khoản của nó sẽ không áp dụng khi bạn phân phối chúng như là sản phẩm riêng biệt. Nhưng khi bạn phân phối nó như là một thành phần của một phần mềm hoàn chỉnh có sử dụng Thư viện đó thì việc phân phối phải tuân thủ các điều khoản của Giấy phép này mà việc cấp phép của nó cho người được cấp phép phải được mở rộng cho toàn bộ sản phẩm, tức là tới bất kỳ phần nào của sản phẩm không quan tâm người nào viết ra thành phần đó.

Như vậy, điều khoản này không nhằm mục đích xác nhận quyền hoặc tranh giành quyền của bạn đối với những sản phẩm hoàn toàn do bạn viết; mà mục đích của nó là nhằm thi hành quyền kiểm soát đối với việc cung cấp những sản phẩm bắt nguồn hoặc tổng hợp dựa trên Thư viện.
Ngoài ra, việc kết hợp thuần tuý Thư viện (hoặc một sản phẩm dựa trên Thư viện) với một sản phẩm không dựa trên Thư viện với mục đích lưu trữ hoặc quảng bá trong đĩa cứng, hoặc phuong tiện phân phối sẽ không đưa sản phẩm đó vào trong phạm vi áp dụng của Giấy phép này.

3. Bạn có thể quyết định áp dụng các điều khoản của Giấy phép công cộng thông thường thay vì Giấy phép này cho một bản sao xác định của Thư viện. Để làm điều này, bạn cần phải thay đổi tất cả các ghi chú tham chiếu đến Giấy phép này để sao cho chúng sẽ tham chiếu đến Giấy phép Công cộng thông thường phiên bản 2, thay vì Giấy phép này (nếu xuất hiện phiên bản mới hơn phiên bản 2.0 của Giấy phép Công cộng thì Bạn có thể xác định phiên bản mới đó nếu Bạn muốn.) Bạn không được làm bất kỳ thay đổi nào khác trong các ghi chú này.

Một khi các thay đổi này đã được áp dụng cho một bản sao xác định, thì điều đó không thể đảo ngược lại cho bản sao này. Vì vậy Giấy phép Công cộng thông thường sẽ được áp dụng cho các bản sao sau đó hoặc cho sản phẩm có nguồn gốc từ bản sao này.

Lựa chọn này sẽ có ích khi Bạn muốn sao một phần mã nguồn của Thư viện vào một chương trình không phải là Thư viện.

4. Bạn có thể sao chép và phân phối Thư viện (hoặc một phần của sản phẩm dựa trên Thư viện, nêu trong Mục 2) dưới hình thức mã đã biên dịch hoặc dưới dạng có thể thực thi được theo các điều khoản nêu trong Mục 1 và 2 ở trên, với điều kiện bạn phải kèm theo đó một bản mã nguồn đầy đủ có thể biên dịch theo các điều khoản trong Mục 1 và 2 nêu trên trong một môi trường trao đổi phần mềm thông thường.

Nếu việc phân phối mã đã biên dịch được thực hiện thông qua việc truy nhập tới một vị trí xác định thì việc cung cấp truy cập tương đương đến mã nguồn từ cùng vị trí đó hoàn toàn đáp ứng yêu cầu phân phối mã nguồn, mặc dù các đối tượng thứ 3 không bắt buộc phải sao cả mã nguồn cùng với mã đã biên dịch.

5. Một phần mềm không chứa bất kỳ thành phần nào có nguồn gốc từ Thư viện nhưng được thiết kế để làm việc với Thư viện thông qua việc biên dịch và liên kết với Thư viện được gọi là “Sản phẩm sử dụng Thư viện”. Sản phẩm như vậy trong sự cô lập không phải là sản phẩm có nguồn gốc từ Thư viện do đó nó nằm ngoài phạm vi của Giấy phép này.

Tuy nhiên, việc liên kết (link) một “sản phẩm sử dụng Thư viện” với Thư viện tạo ra sản phẩm thực thi có nguồn gốc từ Thư viện (bởi vì nó chứa một phần của Thư viện) chứ không phải là “Sản phẩm sử dụng Thư viện” vì vậy sản phẩm thực thi này sẽ nằm trong phạm vi của Giấy phép này. Mục 6 sẽ quy định những điều khoản cho việc phân phối các sản phẩm thực thi.

Khi một “Sản phẩm sử dụng thư viện” sử dụng dữ liệu từ các tập tin tiền tố (header) là thành phần của Thư viện, mã đã biên dịch của sản phẩm này có thể là một sản phẩm có nguồn gốc từ Thư viện mặc dù mã nguồn của nó thì không có nguồn gốc từ Thư viện, Điều này có là sự thực hay không, tuỳ thuộc vào việc sản phẩm có được liên kết mà không cần tới Thư viện hoặc Sản phẩm bản thân có là Thư viện hay không, ngưỡng để phân biệt khi nào là sự thật, không được định nghĩa một cách chính xác trong luật.

Nếu một tập tin đã biên dịch chỉ sử dụng các tham số là các giá trị số, cấu trúc dữ liệu về bố cục, các Macro nhỏ và các hàm nhúng nhỏ (10 dòng lệnh hoặc ít hơn) thì việc sử dụng các tập tin đã biên dịch như vậy là không hạn chế cho dù liệu nó có phải là sản phẩm dẫn xuất hợp pháp hay không. (Các sản phẩm thực thi có chứa những mã đã biên dịch này cộng với các thành phần của Thư viện vẫn phải tuân thủ Mục 6 của Giấy phép này).

Nói một cách khác, nếu sản phẩm có nguồn gốc từ Thư viện thì bạn có thể phân phối mã đã biên dịch theo các điều khoản ở Mục 6. Một chương trình thực thi được có chứa những sản phẩm như vậy cũng phải tuân theo Mục 6 cho dù nó có được liên kết một cách trực tiếp với Thư viện hay không.

6. Như là một ngoại lệ của Mục trên, bạn có thể kết hợp hoặc liên kết một “sản phẩm sử dụng Thư viện” với Thư Viện để tạo ra một sản phẩm chứa các thành phần của Thư viện và phân phối sản phẩm đó theo các điều khoản mà bạn chọn, với điều kiện các điều khoản này phải cho phép chỉnh sửa sản phẩm phục vụ nhu cầu của người sử dụng và cho phép kỹ thuật khôi phục ngược nhằm gỡ rối cho những chỉnh sửa đó.

Bạn cần phải đưa ra ghi chú rõ ràng với mỗi bản sao của sản phẩm rằng Thư viện được sử dụng trong đó và rằng Thư viện và việc sử dụng nó phải tuân thủ theo Giấy phép này. Bạn cũng phải kèm theo một bản sao của Giấy phép này. Nếu sản phẩm trong quá trình thực thi có hiển thị các ghi chú, bạn cũng phải thêm vào ghi chú bản quyền cho Thư viện cùng với các ghi chú đó cũng như tham chiếu hướng dẫn người sử dụng tới bản sao của Giấy phép này. Bạn cũng phải thực hiện một trong những điều sau:

• a) Phân phối cùng với sản phẩm toàn bộ mã nguồn tương ứng có thể biên dịch được của Thư viện cùng với tất cả những chỉnh sửa được sử dụng trong sản phẩm (được phân phối theo các Mục 1 và 2 ở trên); và nếu sản phẩm là thực thi được liên kết với Thư viện, thì cũng phải phân phối toàn bộ “sản phẩm sử dụng Thư viện”, như mã đã biên dịch và/hoặc mã nguồn sao cho người sử dụng có thể chỉnh sửa Thư viện và liên kết lại để tạo ra sản phẩm mới có chứa Thư viện được chỉnh sửa. (Được hiểu là người sử dụng thay đổi nội dung các tập tin định nghĩa trong Thư viện sẽ không cần thiết để có thể dịch lại ứng dụng để sử dụng các định nghĩa được sửa đổi.)
• b) Sử dụng một cơ chế thư viện chia sẻ phù hợp cho viện liên kết với Thư viện. Cơ chế phù hợp là cơ chế (1) sử dụng tại thời điểm thực thi bản sao của thư viện đã có ở trong hệ thống máy tính của người sử dụng mà không phải là sao chép các hàm của thư viện vào trong chương trình, và (2) hoạt động bình thường với phiên bản sửa đổi của thư viện, nếu người sử dụng cài đặt phiên bản sửa đổi có giao diện tương thích với phiên bản mà sản phẩm đã được dùng trước đó.
• C) Kèm theo đó một đề nghị có hạn trong ít nhất 3 năm, theo đó cung cấp cho cùng một người sử dụng các nội dung được quy định trong Mục 6a ở trên, với giá chi phí không cao hơn giá chi phí vật lý của việc cung cấp đó.
• d) Nếu phân phối sản phẩm được thực hiện thông qua việc truy cập để sao chép từ một vị trí xác định thì cũng phải cung cấp quyền truy nhập tương đương để sao các nội dung được quy định ở trên từ cùng vị trí.
• e) Xác định rõ rằng người sử dụng đã nhận được bản sao của các nội dung trên và rằng bạn đã gửi cho người sử dụng đó một bản sao.

Cho chương trình thực thi được, dạng yêu cầu của ”sản phẩm sử dụng thư viện” cần phải kèm theo dữ liệu và các chương trình công cụ cần thiết cho việc tạo ra chương trình thực thi. Tuy nhiên, như một trường hợp ngoại lệ đặc biệt, khi các nội dung cần cung cấp không kèm theo bất cứ những gì được phân phối (kể cả ở dạng mã nguồn hay dạng nhị phân) với các thành phần lớn (bộ biên dịch, nhân, vân vân) của hệ điều hành mà chương trình sẽ chạy trên đó, trừ khi thành phần đó được kèm vào trong chương trình thực thi.

Cũng có thể xẩy ra trường hợp các yêu cầu mâu thuẫn với các quy định trong giấy phép của các bộ thư viện độc quyền khác không kèm theo hệ điều hành. Mâu thuẫn này có nghĩa là bạn không thể sử dụng cả 2 bộ thư viện cùng nhau trong chương trình mà bạn phân phối.

7. Bạn cũng có thể đặt bộ Thư viện là sản phẩm dựa trên Thư viện ngay cạnh với các bộ thư viện khác không thuộc phạm vi Giấy phép này trong cùng một thư viện và phân phối bộ thư viện kết hợp với điều kiện rằng việc phân phối tách biệt của sản phẩm dựa trên Thư viện và bộ thư viện khác cũng được cho phép bằng một cách khác, và với điều kiện bạn phải thực hiện được 2 điều sau:
a) Kèm theo thư viện kết hợp một bản sao của sản phẩm dựa trên Thư viện, chưa được kết hợp với bộ thư viện khác. Việc phân phối đó phải thực hiện theo các điều khoản của Mục trên.
b) Đưa ra một ghi chú rõ ràng với thư viện kết hợp rằng một phần của nó là sản phẩm dựa trên thư viện, và giải thích rõ có thể tìm được ở đâu dạng chưa kết hợp được kèm theo của cùng một sản phẩm.

8. Bạn không được phép sao chép, chỉnh sửa, cấp phép, liên kết hoặc cung cấp Thư viện trừ phi được nêu trong Giấy phép. Bất kỳ ý định bằng cách khác sao chép, chỉnh sửa, cấp phép hoặc liên kết, hoặc cung cấp Thư viện đều làm mất hiệu lực và tự động huỷ bỏ quyền của bạn trong khuôn khổ Giấy phép này. Tuy nhiên, các bên đã nhận được bản sao hoặc quyền từ bạn với Giấy phép này sẽ không bị huỷ bỏ giấy phép nếu các bên đó vẫn tuân thủ đầy đủ các điều khoản của giấy phép.

9. Bạn không bắt buộc phải chấp nhận Giấy phép này khi bạn chưa ký vào đó. Tuy nhiên, không có gì khác đảm bảo cho bạn được phép chỉnh sửa hoặc cung cấp Thư viện hoặc các sản phẩm bắt nguồn từ Thư viện. Những hành động này bị luật pháp nghiêm cấm nếu bạn không chấp nhận Giấy phép này. Do vậy, bằng việc chỉnh sửa hoặc cung cấp Thư viện (hoặc bất kỳ một sản phẩm nào dựa trên Thư viẹn), bạn đã thể hiện sự chấp thuận đối với Giấy phép này, cùng với tất cả các điều khoản và điều kiện đối với việc sao chép, cung cấp hoặc chỉnh sửa Thư viện hoặc các sản phẩm dựa trên nó.

10. Mỗi khi bạn cung cấp lại Thư viện (hoặc bất kỳ một sản phẩm nào dựa trên Thư viện), người nhận sẽ tự động nhận được giấy phép từ người cấp phép đầu tiên cho phép sao chép, cung cấp, liên kết và chỉnh sửa Thư viện theo các điều khoản và điều kiện này. Bạn không thể áp đặt bất cứ hạn chế nào khác đối với việc thực hiện quyền của người nhận đã được cấp phép từ thời điểm đó. Bạn cũng không phải chịu trách nhiệm bắt buộc các bên thứ ba tuân thủ theo Giấy phép này.

11. Nếu như, theo quyết định của toà án hoặc với những dẫn chứng về việc vi phạm bản quyền hoặc vì bất kỳ lý do nào khác (không giới hạn trong các vấn đề về bản quyền), mà bạn phải tuân theo các điều kiện (nêu ra trong lệnh của toà án, biên bản thoả thuận hoặc ở nơi khác) trái với các điều kiện của Giấy phép này, thì chúng cũng không thể miễn cho bạn khỏi những điều kiện của Giấy phép này. Nếu bạn không thể đồng thời thực hiện các nghĩa vụ của mình trong khuôn khổ Giấy phép này và các nghĩa vụ thích đáng khác, thì hậu quả là bạn hoàn toàn không được cung cấp Thư viện. Ví dụ, nếu trong giấy phép bản quyền không cho phép những người nhận được bản sao trực tiếp hoặc gián tiếp qua bạn có thể cung cấp lại Thư viện thì trong trường hợp này cách duy nhất bạn có thể thoả mãn cả hai điều kiện là hoàn toàn không cung cấp Thư viện.

Nếu bất kỳ một phần nào trong điều khoản này không có hiệu lực hoặc không thể thi hành trong một hoàn cảnh cụ thể, thì sẽ cân đối các điều khoản để áp dụng, và toàn bộ điều khoản sẽ được áp dụng trong những hoàn cảnh khác.

Mục đích của điều khoản này không nhằm buộc bạn phải vi phạm bất kỳ một bản quyền nào hoặc các quyền sở hữu khác hoặc tranh luận về giá trị hiệu lực của bất kỳ quyền hạn nào như vậy; mục đích duy nhất của điều khoản này là nhằm bảo vệ sự toàn vẹn của hệ thống cung cấp phần mềm tự do đang được thực hiện với giấy phép công cộng. Nhiều người đã đóng góp rất nhiều vào sự đa dạng của các phần mềm tự do được cung cấp thông qua hệ thống này với sự tin tưởng rằng hệ thống được sử dụng một cách thống nhất; tác giả/người cung cấp có quyền quyết định rằng họ có mong muốn cung cấp phần mềm thông qua hệ thống nào khác hay không, và người được cấp phép không thể có ảnh hưởng tới sự lựa chọn này.

Điều khoản này nhằm làm rõ hậu quả của Giấy phép này.

12. Nếu việc cung cấp và/hoặc sử dụng Thư viện bị cấm ở một số nước nhất định bởi các quy định về bản quyền, thì người giữ bản quyền gốc đã đưa Thư viện vào phạm vi áp dụng của Giấy phép này có thể bổ sung một điều khoản hạn chế việc cung cấp ở những nước đó, nghĩa là việc cung cấp chỉ được phép ở các nước không bị liệt kê trong danh sách hạn chế. Trong trường hợp này, Giấy phép đưa vào những hạn chế được ghi trong nội dung của nó.

13. Tổ chức Phần mềm Tự do có thể theo thời gian công bố những phiên bản chỉnh sửa và/hoặc phiên bản mới của Giấy phép Công cộng Hạn chế. Những phiên bản đó sẽ đồng nhất với tinh thần của phiên bản hiện này, nhưng có thể khác ở một số chi tiết nhằm giải quyết những vấn đề hay lo ngại mới.

Mỗi phiên bản sẽ có một mã số phiên bản riêng. Nếu Thư viện áp dụng một phiên bản Giấy phép cụ thể, bạn có quyền lựa chọn tuân theo những điều khoản và điều kiện của phiên bản giấy phép đó hoặc của bất kỳ một phiên bản nào sau đó do Tổ chức Phần mềm Tự do công bố. Nếu Chương trình không nêu cụ thể mã số phiên bản giấy phép, bạn có thể lựa chọn bất kỳ một phiên bản nào đã từng được công bố bởi Tổ chức Phần mềm Tự do.

14. Nếu bạn muốn kết hợp các phần của Thư viện vào các chương trình tự do khác mà có các điều kiện cung cấp khác, hãy viết cho tác giả để xin phép. Đối với các phần mềm được cấp bản quyền bởi Tổ chức Phầm mềm Tự do, hãy đề xuất với tổ chức này; đôi khi chúng tôi cũng có những ngoại lệ. Quyết định của chúng tôi sẽ dựa trên hai mục tiêu là bảo hộ tình trạng tự do của tất cả các sản phẩm bắt nguồn từ phần mềm tự do của chúng tôi, và thúc đẩy việc chia sẻ và tái sử dụng phần mềm nói chung.

KHÔNG BẢO HÀNH

15. DO THƯ VIỆN ĐƯỢC CẤP PHÉP MIỄN PHÍ NÊN KHÔNG CÓ MỘT CHẾ ĐỘ BẢO HÀNH NÀO TRONG MỨC ĐỘ CHO PHÉP CỦA LUẬT PHÁP. TRỪ KHI ĐƯỢC CÔNG BỐ KHÁC ĐI BẰNG VĂN BẢN, NHỮNG NGƯỜI GIỮ BẢN QUYỀN VÀ/HOẶC CÁC BÊN CUNG CẤP THƯ VIỆN NGUYÊN BẢN SẼ KHÔNG BẢO HÀNH DƯỚI BẤT KỲ HÌNH THỨC NÀO, BAO GỒM NHƯNG KHÔNG GIỚI HẠN TRONG CÁC HÌNH THỨC BẢO HÀNH ĐỐI VỚI TÍNH THƯƠNG MẠI CŨNG NHƯ TÍNH THÍCH HỢP CHO MỘT MỤC ĐÍCH CỤ THỂ. BẠN LÀ NGƯỜI CHỊU TOÀN BỘ RỦI RO VỀ CHẤT LƯỢNG CŨNG NHƯ VIỆC VẬN HÀNH THƯ VIỆN. TRONG TRƯỜNG HỢP THƯ VIỆN CHO THẤY CÓ KHIẾM KHUYẾT, BẠN PHẢI CHỊU TOÀN BỘ CHI PHÍ CHO NHỮNG DỊCH VỤ SỬA CHỮA CẦN THIẾT.

16. TRONG TẤT CẢ CÁC TRƯỜNG HỢP TRỪ KHI CÓ YÊU CẦU CỦA LUẬT PHÁP HOẶC CÓ THOẢ THUẬN BẰNG VĂN BẢN, NHỮNG NGƯỜI CÓ BẢN QUYỀN HOẶC BẤT KỲ MỘT BÊN NÀO CHỈNH SỬA VÀ/HOẶC CUNG CẤP LẠI CHƯƠNG TRÌNH TRONG CÁC ĐIỀU KIỆN NHƯ ĐÃ NÊU TRÊN KHÔNG CÓ TRÁCH NHIỆM VỚI BẠN VỀ CÁC LỖI HỎNG HÓC, BAO GỒM CÁC LỖI CHUNG HAY ĐẶC BIỆT, NGẪU NHIÊN HAY TẤT YẾU NẢY SINH DO VIỆC SỬ DỤNG HOẶC KHÔNG SỬ DỤNG ĐƯỢC THƯ VIỆN (BAO GỒM NHƯNG KHÔNG GIỚI HẠN TRONG VIỆC MẤT DỮ LIỆU, DỮ LIỆU THIẾU CHÍNH XÁC HOẶC CHƯƠNG TRÌNH KHÔNG VẬN HÀNH ĐƯỢC VỚI CÁC CHƯƠNG TRÌNH KHÁC), THẬM CHÍ CẢ KHI NGƯỜI CÓ BẢN QUYỀN VÀ CÁC BÊN KHÁC ĐÃ ĐƯỢC KHUYẾN CÁO VỀ KHẢ NĂNG XẢY RA NHỮNG THIỆT HẠI ĐÓ.
KẾT THÚC CÁC ĐIỀU KHOẢN VÀ ĐIỀU KIỆN

Áp dụng những điều khoản trên như thế nào đối với thư viện mới của bạn

Nếu bạn xây dựng một thư viện mới, và bạn muốn cung cấp tối đa cho công chúng sử dụng, thì biện pháp tốt nhất để đạt được điều này là biến thư viện đó thành phần mềm tự do để ai cũng có thể cung cấp lại và sửa đổi. Bạn có thể thực hiện được điều này bằng việc cho phép các hạn chế theo các điều khoản của Giấy phép này (hoặc theo các điều khoản của Giấy phép GPL).

Để áp dụng các điều khoản này, hãy đính kèm những ghi chú như sau cùng với thư viện của mình. An toàn nhất là đính kèm chúng vào phần đầu mỗi tệp tin mã nguồn để thông báo một cách hiệu quả nhất về việc không có bảo hành; và mỗi tệp tin đều phải có ít nhất một dòng về “bản quyền” và dòng trỏ đến nới có toàn bộ ghi chú.

Một dòng đề tên chương trình và nội dung của nó.
Copyright (C) năm tên tác giả


Thư viện này là phần mềm tự do, bạn có thể cung cấp lại và/hoặc chỉnh sửa nó theo những điều khoản của Giấy phép Công cộng Hạn chế của GNU do Tổ chức Phần mềm Tự do công bố; phiên bản 2.1 của Giấy phép, hoặc bất kỳ một phiên bản sau đó (tuỳ sự lựa chọn của bạn).

Thư viện này được cung cấp với hy vọng nó sẽ hữu ích, tuy nhiên KHÔNG CÓ BẤT KỲ MỘT BẢO HÀNH NÀO; thậm chí kể cả bảo hành về KHẢ NĂNG THƯƠNG MẠI hoặc TÍNH THÍCH HỢP CHO MỘT MỤC ĐÍCH CỤ THỂ. Xin xem Giấy phép Công cộng Hạn chế của GNU để biết thêm chi tiết.


Bạn phải nhận được một bản sao của Giấy phép Công cộng Hạn chế của GNU kèm theo chương trình này; nếu bạn chưa nhận được, xin gửi thư về Tổ chức Phần mềm Tự do, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

Xin hãy bổ sung thông tin về địa chỉ liên lạc của bạn (thư điện tử và bưu điện).

Bạn cũng cần phải lấy chữ ký của người phụ trách (nếu bạn là người lập trình) hoặc của trường học (nếu có) xác nhận từ chối bản quyền đối với thư viện. Sau đây là ví dụ:

Yoyodyne, Inc., tại đây từ chối tất cả các quyền lợi bản quyền đối với thư viện ‘Frob’
Viết bởi James Random Hacker.

chữ ký của Ty Coon, 1 April 1990
Ty Coon, Phó Tổng Giám đốc
-----------------------------------

Bản gốc tiếng Anh:

GNU Lesser General Public License

Version 2.1, February 1999

Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users.

This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below.

When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things.

To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it.

For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights.

We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library.

To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others.

Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license.

Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs.

When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library.

We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances.

For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License.

In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system.

Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library.

The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run.

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you".

A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables.

The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".)

"Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library.

Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does.

1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library.

You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

a) The modified work must itself be a software library.

b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change.

c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License.

d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful.

(For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.)

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library.

In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices.

Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy.

This option is useful when you wish to copy part of the code of the Library into a program that is not a library.

4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange.

If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code.

5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License.

However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables.

When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law.

If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.)

Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself.

6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications.

You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things:

a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.)

b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with.

c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution.

d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place.

e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy.

For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute.

7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things:

a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above.

b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work.

8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it.

10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License.

11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library.

If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.

13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation.

14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Libraries

If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.

one line to give the library's name and an idea of what it does.
Copyright (C) year name of author

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Also add information on how to contact you by electronic and paper mail.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in
the library `Frob' (a library for tweaking knobs) written
by James Random Hacker.

signature of Ty Coon, 1 April 1990
Ty Coon, President of Vice

That's all there is to it!
Bản dịch tiếng Việt của Giấy phép Công cộng GNU (GPL)

Người dịch Đặng Minh Tuấn <dangtuan@vietkey.net> Đây là bản dịch tiếng Việt không chính thức của Giấy phép Công cộng GNU. Bản dịch này không phải do Tổ chức Phần mềm Tự do ấn hành, và nó không quy định về mặt pháp lý các điều khoản cho các phần mềm sử dụng giấy phép GNU GPL -- chỉ có bản tiếng Anh gốc của GNU GPL mới có tính pháp lý. Tuy nhiên, chúng tôi hy vọng rằng bản dịch này sẽ giúp cho những người Việt hiểu rõ hơn về GNU GPL.

This is an unofficial translation of the GNU General Public License into Vietnamese. It was not published by the Free Software Foundation, and does not legally state the distribution terms for software that uses the GNU GPL--only the original English text of the GNU GPL does that. However, we hope that this translation will help Vietnamese speakers understand the GNU GPL better.

GIẤY PHÉP CÔNG CỘNG GNU (GPL)



Giấy phép công cộng GNU
Phiên bản 2, tháng 6/1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA


Mọi người đều được phép sao chép và lưu hành bản sao nguyên bản nhưng không được phép thay đổi nội dung của giấy phép này.

Lời nói đầu

Giấy phép sử dụng của hầu hết các phần mềm đều được đưa ra nhằm hạn chế bạn tự do chia sẻ và thay đổi nó. Ngược lại, Giấy phép Công cộng của GNU có mục đích đảm bảo cho bạn có thể tự do chia sẻ và thay đổi phần mềm (tự do) - tức là đảm bảo rằng phần mềm đó là tự do đối với mọi người sử dụng. Giấy phép Công cộng này áp dụng cho hầu hết các phần mềm của Tổ chức Phần mềm Tự do và cho tất cả các chương trình khác mà tác giả của chúng cho phép áp dụng. (Đối với một số phần mềm khác của Tổ chức Phần Mềm Tự do, có thể nên áp dụng Giấy phép Công cộng Hạn chế của GNU thay cho giấy phép này ). Bạn cũng có thể áp dụng nó cho các chương trình của mình.

Khi nói đến phần mềm tự do, chúng ta nói đến sự tự do sử dụng chứ không quan tâm về giá cả. Giấy phép Công cộng của chúng tôi được thiết kế để đảm bảo rằng bạn hoàn toàn tự do cung cấp các bản sao của phần mềm tự do (và thu tiền đối với dịch vụ này nếu bạn muốn), rằng bạn có thể nhận được mã nguồn nếu bạn có yêu cầu, rằng bạn có thể thay đổi phần mềm hoặc sử dụng các thành phần của phần mềm đó cho những chương trình tự do mới; và rằng bạn biết chắc là bạn có thể làm được những điều này.

Để bảo vệ các quyền của bạn, chúng tôi cần đưa ra những hạn chế để ngăn chặn những ai chối bỏ quyền của bạn, hoặc yêu cầu bạn chối bỏ quyền của mình. Những hạn chế này đồng thời cũng là những trách nhiệm nhất định của bạn khi bạn cung cấp các bản sao phần mềm hoặc khi bạn chỉnh sửa các phần mềm đó.

Ví dụ, nếu bạn cung cấp các bản sao của một chương trình, dù miễn phí hay không, bạn phải cho người nhận tất cả các quyền mà bạn có. Bạn cũng phải đảm bảo rằng họ cũng nhận được hoặc tiếp cận được mã nguồn. Và bạn phải thông báo những điều khoản này để họ biết rõ về quyền của mình.

Chúng tôi bảo vệ quyền của bạn với hai bước: (1) xác lập bản quyền đối với phần mềm, và (2) cấp giấy phép này để bạn có thể sao chép, lưu hành và/hoặc chỉnh sửa phần mềm một cách hợp pháp.

Ngoài ra, để bảo vệ các tác giả cũng như để bảo vệ chính mình, chúng tôi muốn chắc chắn rằng tất cả mọi người đều hiểu rõ rằng phần mềm tự do không hề có bảo hành. Nếu phần mềm được chỉnh sửa thay đổi bởi một người khác và sau đó chuyển tiếp sang người khác nữa, thì chúng tôi muốn người tiếp nhận nó biết rằng phiên bản họ đang có không phải là bản gốc, do đó tất cả những trục trặc do những người khác gây ra hoàn toàn không ảnh hưởng tới uy tín của tác giả ban đầu.

Cuối cùng, bất kỳ một chương trình tự do nào cũng đều thường xuyên có nguy cơ bị đe doạ về bản quyền phần mềm. Chúng tôi muốn tránh nguy cơ khi những người cung cấp lại một chương trình tự do có thể có được giấy phép bản quyền cho bản thân họ, từ đó trở thành độc quyền đối với chương trình. Để ngăn ngừa trường hợp này, chúng tôi đã nêu rõ rằng mỗi giấy phép bản quyền hoặc phải được cấp cho tất cả mọi người sử dụng một cách tự do hoặc hoàn toàn không được cấp phép.

Dưới đây là những điều khoản và điều kiện cho việc sao chép, lưu hành và chỉnh sửa.

Những điều khoản và điều kiện đối với việc sao chép, lưu hành và chỉnh sửa

0. Giấy phép này áp dụng cho bất kỳ một chương trình hay sản phẩm nào mà người giữ bản quyền công bố rằng nó có thể được cung cấp trong khuôn khổ những điều khoản của Giấy phép Công cộng này. Từ “Chương trình” dưới đây có nghĩa là bất cứ chương trình hay sản phẩm nào như vậy, và “sản phẩm dựa trên Chương trình” có nghĩa là Chương trình hoặc bất kỳ một sản phẩm nào bắt nguồn từ Chương trình đó tuân theo luật bản quyền, tức là một sản phẩm dựa trên Chương trình hoặc một phần của nó, dù là đúng nguyên bản hoặc có một số chỉnh sửa và/hoặc được dịch ra một ngôn ngữ khác. (Dưới đây, việc dịch cũng được hiểu trong khái niệm “chỉnh sửa”). Mỗi người được cấp phép được gọi là “bạn”.

Các hoạt động không phải là sao chép, lưu hành và chỉnh sửa thì không được đề cập ở đây; chúng nằm ngoài phạm vi của Giấy phép này. Hành động chạy chương trình không bị ngăn cấm, và những kết quả thu được từ việc chạy Chương trình chỉ thuộc phạm vi áp dụng của Giấy phép này nếu nội dung của nó tạo thành một sản phẩm dựa trên Chương trình (cho dù nhờ có việc chạy Chương trình mà mới có được nó). Khả năng này có xảy ra hay không là phụ thuộc vào công việc mà Chương trình thực hiện.

1. Bạn có thể sao chép và lưu hành những bản sao nguyên bản của mã nguồn Chương trình đúng như khi bạn nhận được nó, qua bất kỳ phương tiện phân phối nào, với điều kiện rằng trên mỗi bản sao bạn đều kèm theo một ghi chú bản quyền rõ ràng và từ chối bảo hành; giữ nguyên tất cả những nội dung thông báo đề cập đến Giấy phép này và về việc không có bất kỳ một sự bảo hành nào; và cùng với Chương trình, bạn cung cấp cho người sử dụng một bản sao của Giấy phép này.

Bạn có thể tính phí cho việc cung cấp vật lý một bản sao nào đó, và tuỳ theo quyết định của mình bạn có thể đưa ra một cam kết bảo hành để lấy một khoản phí tương ứng.

2. Bạn có thể chỉnh sửa bản sao của bạn hoặc các bản sao của Chương trình hoặc của bất kỳ phần nào của nó, từ đó hình thành một sản phẩm dựa trên Chương trình, và sao chép cũng như lưu hành sản phẩm hoặc những chỉnh sửa đó theo các điều khoản tại Mục 1 ở trên, với điều kiện bạn cũng đáp ứng tất cả những điều kiện dưới đây:
• a) Bạn phải có ghi chú rõ ràng trong những tập tin đã chỉnh sửa là bạn đã chỉnh sửa nó, và ngày tháng của bất kỳ một thay đổi nào.
• b) Đối với các sản phẩm nào bạn cung cấp hoặc phát hành mà bao gồm hoặc bắt nguồn hoàn toàn hay một phần từ Chương trình hoặc bất cứ phần nào của nó thì Bạn phải cấp phép miễn phí cho tất cả các bên thứ ba theo những điều khoản của Giấy phép này.
• c) Nếu chương trình đã chỉnh sửa thường đọc lệnh tương tác trong khi chạy, bạn phải thực hiện sao cho khi bắt đầu chạy để sử dụng tương tác theo cách thông thường nhất, chương trình phải in ra hoặc hiện ra một thông báo về bản quyền và thông báo về việc không có bảo hành (hoặc thông báo bạn là người cung cấp bảo hành), và rằng người sử dụng có thể cung cấp lại Chương trình theo những điều kiện đã nêu, và thông báo để người sử dụng biết làm thế nào để có thể xem bản sao của Giấy phép này. (Ngoại lệ: nếu bản thân Chương trình là tương tác nhưng bình thường nó không đưa ra một thông báo nào như trên, thì sản phẩm của bạn dựa trên Chương trình đó cũng không bắt buộc phải có thông báo như vậy).

Những yêu cầu trên áp dụng cho toàn bộ sản phẩm chỉnh sửa. Nếu có những phần xác định được của sản phẩm rõ ràng là không bắt nguồn từ Chương trình, và có căn cứ hợp lý để có thể được xem là những sản phẩm độc lập và riêng biệt, thì Giấy phép này và các điều khoản của nó sẽ không áp dụng cho những phần đó khi bạn cung cấp chúng như những sản phẩm riêng biệt. Nhưng khi bạn cung cấp những phần đó như những phần nhỏ trong cả một sản phẩm dựa trên Chương trình thì việc cung cấp toàn bộ sản phẩm này phải tuân theo những điều khoản của Giấy phép này, mà giá trị cấp phép của nó đối với người được cấp phép sẽ áp dụng đối với toàn bộ sản phẩm và do đó, đối với từng và tất cả các phần trong đó, bất kể ai đã viết ra nó.

Như vậy, phần quy định này không nhằm mục đích xác nhận quyền hoặc tranh giành quyền của bạn đối với những sản phẩm hoàn toàn do bạn viết; mà mục đích của nó là nhằm thực hiện quyền kiểm soát đối với việc cung cấp những sản phẩm bắt nguồn từ hoặc tập hợp thành nhóm dựa trên Chương trình.

Ngoài ra, việc kết hợp thuần tuý Chương trình (hoặc một sản phẩm dựa trên Chương trình) với một sản phẩm khác không dựa trên Chương trình trên một tập hợp nào đó của một phương tiện lưu trữ hoặc quảng bá sẽ không làm cho sản phẩm khác đó rơi vào phạm vi áp dụng của Giấy phép này.

3. Bạn có thể sao chép và cung cấp Chương trình (hoặc một sản phẩm dựa trên Chương trình, theo Mục 2) dưới hình thức mã đã biên dịch hoặc dạng có thể thực thi được trong khuôn khổ các điều khoản nêu trong Mục 1 và 2 ở trên, nếu như bạn:
• a) Kèm theo đó một bản mã nguồn tương ứng dạng đầy đủ có thể biên dịch được, và mã nguồn này phải được cung cấp theo các điều khoản trong Mục 1 và 2 nêu trên thông qua một phương tiện mang tin thông thường vẫn được sử dụng cho mục đích trao đổi phần mềm; hoặc
• b) Kèm theo đó một đề nghị bằng văn bản có giá trị ít nhất 3 năm về việc cung cấp cho bất kỳ một bên thứ ba một bản sao đầy đủ của mã nguồn tương ứng, và việc cung cấp này phải được thực hiện thông qua một phương tiện thông thường vẫn được sử dụng để trao đổi phần mềm, với chi phí không cao hơn giá chi phí vật lý của hành vi cung cấp và căn cứ theo các điều khoản tại các Mục 1 và 2 nêu trên; hoặc
• c) Kèm theo đó những thông tin bạn đã nhận được về đề nghị cung cấp mã nguồn tương ứng. (Phương án này chỉ được phép đối với việc phân phối phi thương mại và chỉ với điều kiện nếu bạn nhận được Chương trình dưới hình thức mã đã biên dịch hoặc dạng có thể thực thi được cùng với lời đề nghị như vậy, theo phần b trong điều khoản nêu trên).

Mã nguồn của một sản phẩm là một dạng của sản phẩm thường được dùng cho việc chỉnh sửa nó. Với một sản phẩm có thể thi hành, mã nguồn hoàn chỉnh có nghĩa là toàn bộ các mã nguồn cho tất cả các môđun trong sản phẩm đó, cùng với tất cả các tệp tin định nghĩa giao diện đi kèm , cùng với tập lệnh dùng để kiểm soát việc biên dịch và cài đặt các tập tin thi hành. Tuy nhiên, có một ngoại lệ đặc biệt là mã nguồn được cung cấp không cần chứa những thành phần mà bình thường vẫn được cung cấp (dưới hình thức mã nguồn hoặc dạng nhị phân) cùng với những thành phần chính (chương trình biên dịch, nhân, và những phần tương tự) của hệ điều hành mà các chương trình sẽ chạy trong đó, trừ khi bản thân thành phần đó lại đi kèm với một tập tin thi hành.

Nếu việc cung cấp mã đã biên dịch hoặc tập tin thi hành được thực hiện qua việc cho phép tiếp cận để sao chép từ một địa điểm được chỉ định, thì việc cho phép tiếp cận theo một phương thức tương đương để sao chép mã nguồn từ cùng địa điểm cũng được tính như việc cung cấp mã nguồn, kể cả khi các bên thứ ba không bị buộc phải sao chép mã nguồn cùng với mã đã biên dịch.

4. Bạn không được phép sao chép, chỉnh sửa, cấp phép hoặc cung cấp Chương trình trừ phi phải tuân thủ một cách chính xác các điều khoản trong Giấy phép này. Bất kỳ ý định sao chép, chỉnh sửa, cấp phép hoặc cung cấp Chương trình theo cách khác đều làm mất hiệu lực và tự động huỷ bỏ quyền của bạn trong khuôn khổ Giấy phép này. Tuy nhiên, những bên nào đã nhận được bản sao hoặc quyền từ bạn căn cứ theo Giấy phép này sẽ không bị mất bản quyền, chừng nào các bên đó vẫn tuân thủ đầy đủ các điều khoản của giấy phép này.

5. Bạn không bắt buộc phải chấp nhận Giấy phép này khi bạn chưa ký vào đó. Tuy nhiên, thiếu nó bạn sẽ không được phép chỉnh sửa hoặc cung cấp Chương trình hoặc các sản phẩm bắt nguồn từ Chương trình. Những hành động này bị luật pháp nghiêm cấm nếu bạn không chấp nhận Giấy phép này. Do vậy, bằng việc chỉnh sửa hoặc cung cấp Chương trình (hoặc bất kỳ một sản phẩm nào dựa trên Chương trình), bạn đã thể hiện sự chấp thuận Giấy phép này, cùng với tất cả các điều khoản và điều kiện đối với việc sao chép, cung cấp hoặc chỉnh sửa Chương trình hoặc các sản phẩm dựa trên nó.

6. Mỗi khi bạn cung cấp lại Chương trình (hoặc bất kỳ một sản phẩm nào dựa trên Chương trình), người nhận sẽ tự động nhận được giấy phép từ người cấp phép đầu tiên cho phép sao chép, cung cấp và chỉnh sửa Chương trình theo các điều khoản và điều kiện này. Bạn không thể áp đặt bất cứ hạn chế nào khác đối với quyền của những người tiếp nhận ở đây. Bạn cũng không phải chịu trách nhiệm bắt buộc các bên thứ ba tuân thủ theo Giấy phép này.

7. Nếu như, theo quyết định của toà án hoặc với những khiếu nại về việc vi phạm bản quyền hoặc vì bất kỳ lý do nào khác (không chỉ giới hạn trong các vấn đề về bản quyền), mà bạn phải tuân theo các điều kiện (nêu ra trong lệnh của toà án, biên bản thoả thuận hoặc theo cách khác) trái với các điều kiện của Giấy phép GPL, thì chúng cũng không thể miễn cho bạn khỏi những điều kiện của Giấy phép này. Nếu bạn không thể đồng thời thực hiện các nghĩa vụ của mình trong khuôn khổ Giấy phép này và các nghĩa vụ thích đáng khác, thì hậu quả là bạn hoàn toàn không được cung cấp Chương trình. Ví dụ, nếu giấy phép bản quyền không cho phép những người nhận có được bản sao của Chương trình trực tiếp hoặc gián tiếp qua bạn một cách miễn phí thì trong trường hợp này cách duy nhất bạn có thể thoả mãn cả hai điều kiện là hoàn toàn không cung cấp Chương trình.

Nếu bất kỳ một phần nào trong điều khoản này không có hiệu lực hoặc không thể thi hành trong một hoàn cảnh cụ thể, thì phần nội dung còn lại của điều khoản vẫn được áp dụng, và toàn bộ điều khoản sẽ được áp dụng trong những hoàn cảnh khác.

Mục đích của điều khoản này không nhằm buộc bạn phải vi phạm bất kỳ bản quyền nào hoặc các quyền sở hữu khác hoặc tranh luận về giá trị hiệu lực của bất kỳ quyền hạn nào như vậy; mục đích duy nhất của điều khoản này là nhằm bảo vệ sự toàn vẹn của hệ thống cung cấp phần mềm tự do đang được thực hiện theo những thực tiễn chung về giấy phép công cộng. Nhiều người đã đóng góp một cách tích cực vào hàng loạt các phần mềm tự do được cung cấp thông qua hệ thống này với sự tin tưởng rằng hệ thống được sử dụng một cách thống nhất; tác giả/người cung cấp có quyền quyết định về việc họ có cung cấp phần mềm thông qua hệ thống nào khác hay không, và người được cấp phép không thể tác động tới sự lựa chọn này.

Điều khoản này nhằm làm rõ những vấn đề được cho là hậu quả tiếp theo của các phần còn lại của Giấy phép này.

8. Nếu việc cung cấp và/hoặc sử dụng Chương trình bị cấm ở một số nước nhất định bởi quy định về sáng chế hoặc bản quyền, và người giữ bản quyền gốc đã quyết định áp dụng Giấy phép này cho Chương trình thì có thể bổ sung một điều khoản cụ thể hạn chế việc cung cấp theo phạm vi lãnh thổ để loại trừ các nước đó ra, tức là việc cung cấp chỉ được phép ở các nước không nằm trong danh sách hạn chế. Trong trường hợp đó, điều khoản loại trừ sẽ được coi như một thành phần của Giấy phép này.

9. Tổ chức Phần mềm Tự do có thể tuỳ từng thời điểm mà công bố những phiên bản chỉnh sửa và/hoặc phiên bản mới của Giấy phép Công cộng. Những phiên bản đó sẽ đồng nhất với tinh thần của phiên bản hiện này, nhưng có thể khác ở một số chi tiết nhằm giải quyết những vấn đề hay những quan ngại mới.

Mỗi phiên bản sẽ có một mã số phiên bản riêng. Nếu Chương trình và "bất kỳ một phiên bản nào sau đó" có áp dụng một phiên bản Giấy phép cụ thể, thì bạn có quyền lựa chọn tuân theo những điều khoản và điều kiện của phiên bản giấy phép đó hoặc của bất kỳ một phiên bản nào sau đó do Tổ chức Phần mềm Tự do công bố. Nếu Chương trình không nêu cụ thể mã số phiên bản giấy phép, bạn có thể lựa chọn bất kỳ một phiên bản nào đã từng được công bố bởi Tổ chức Phần mềm Tự do.

10. Nếu bạn muốn kết hợp các phần của Chương trình vào các chương trình tự do khác mà điều kiện cung cấp khác với chương trình này, hãy viết cho tác giả để được phép. Đối với các phần mềm được cấp bản quyền bởi Tổ chức Phầm mềm Tự do, hãy đề xuất; đôi khi chúng tôi cũng có những ngoại lệ. Quyết định của chúng tôi sẽ dựa trên hai mục tiêu là bảo hộ tình trạng tự do của tất cả các sản phẩm bắt nguồn từ phần mềm tự do của chúng tôi, và thúc đẩy việc chia sẻ và tái sử dụng phần mềm nói chung.

KHÔNG BẢO HÀNH
DO CHƯƠNG TRÌNH ĐƯỢC CẤP PHÉP MIỄN PHÍ NÊN KHÔNG CÓ MỘT CHẾ ĐỘ BẢO HÀNH NÀO TRONG MỨC ĐỘ CHO PHÉP CỦA LUẬT PHÁP. TRỪ KHI ĐƯỢC CÔNG BỐ KHÁC ĐI BẰNG VĂN BẢN, NHỮNG NGƯỜI GIỮ BẢN QUYỀN VÀ/HOẶC CÁC BÊN CUNG CẤP CHƯƠNG TRÌNH "NGUYÊN TRẠNG" SẼ KHÔNG BẢO HÀNH DƯỚI BẤT KỲ HÌNH THỨC NÀO DÙ CÓ QUY ĐỊNH RÕ HAY NGỤ Ý, BAO GỒM NHƯNG KHÔNG GIỚI HẠN TRONG CÁC HÌNH THỨC BẢO HÀNH ĐỐI VỚI TÍNH THƯƠNG MẠI CŨNG NHƯ TÍNH THÍCH HỢP CHO MỘT MỤC ĐÍCH CỤ THỂ. BẠN LÀ NGƯỜI CHỊU TOÀN BỘ RỦI RO VỀ CHẤT LƯỢNG CŨNG NHƯ VIỆC VẬN HÀNH CHƯƠNG TRÌNH. TRONG TRƯỜNG HỢP CHƯƠNG TRÌNH CÓ KHIẾM KHUYẾT, BẠN PHẢI CHỊU TOÀN BỘ CHI PHÍ CHO NHỮNG DỊCH VỤ SỬA CHỮA CẦN THIẾT.

TRONG TẤT CẢ CÁC TRƯỜNG HỢP TRỪ KHI CÓ YÊU CẦU CỦA LUẬT PHÁP HOẶC CÓ THOẢ THUẬN BẰNG VĂN BẢN, NHỮNG NGƯỜI NẮM BẢN QUYỀN HOẶC BẤT KỲ MỘT BÊN NÀO CHỈNH SỬA VÀ/HOẶC CUNG CẤP LẠI CHƯƠNG TRÌNH THEO SỰ CẤP PHÉP NHƯ TRÊN ĐỀU KHÔNG CÓ TRÁCH NHIỆM VỚI BẠN VỀ CÁC LỖI HỎNG HÓC, BAO GỒM CÁC LỖI THÔNG THƯỜNG HAY ĐẶC BIỆT, NGẪU NHIÊN HAY TẤT YẾU NẢY SINH DO VIỆC SỬ DỤNG HOẶC KHÔNG SỬ DỤNG ĐƯỢC CHƯƠNG TRÌNH (BAO GỒM NHƯNG KHÔNG GIỚI HẠN TRONG VIỆC MẤT DỮ LIỆU, DỮ LIỆU THIẾU CHÍNH XÁC HOẶC CHƯƠNG TRÌNH KHÔNG VẬN HÀNH ĐƯỢC VỚI CÁC CHƯƠNG TRÌNH KHÁC), THẬM CHÍ CẢ KHI NGƯỜI NẮM BẢN QUYỀN VÀ CÁC BÊN KHÁC ĐÃ ĐƯỢC THÔNG BÁO VỀ KHẢ NĂNG XẢY RA NHỮNG THIỆT HẠI ĐÓ.

KẾT THÚC CÁC ĐIỀU KIỆN VÀ ĐIỀU KHOẢN.

Áp dụng những điều khoản trên như thế nào đối với chương trình của bạn

Nếu bạn xây dựng một chương trình mới, và bạn muốn cung cấp một cách tối đa cho công chúng sử dụng, thì biện pháp tốt nhất để đạt được điều này là phát triển chương trình đó thành phần mềm tự do để ai cũng có thể cung cấp lại và thay đổi theo những điều khoản như trên.

Để làm được việc này, hãy đính kèm những ghi chú như sau vào chương trình của mình. An toàn nhất là đính kèm chúng trong phần đầu của tập tin mã nguồn để thông báo một cách hiệu quả nhất về việc không có bảo hành; và mỗi tệp tin đều phải có ít nhất một dòng về “bản quyền” và trỏ đến toàn văn nội dung thông báo.

Một dòng đề tên chương trình và nội dung của nó.
Bản quyền (C) năm, tên tác giả.

Chương trình này là phần mềm tự do, bạn có thể cung cấp lại và/hoặc chỉnh sửa nó theo những điều khoản của Giấy phép Công cộng của GNU do Tổ chức Phần mềm Tự do công bố; phiên bản 2 của Giấy phép, hoặc bất kỳ một phiên bản sau đó (tuỳ sự lựa chọn của bạn).

Chương trình này được cung cấp với hy vọng rằng nó sẽ hữu ích, tuy nhiên KHÔNG CÓ BẤT KỲ MỘT BẢO HÀNH NÀO; thậm chí kể cả bảo hành về KHẢ NĂNG THƯƠNG MẠI hoặc TÍNH THÍCH HỢP CHO MỘT MỤC ĐÍCH CỤ THỂ. Xin xem Giấy phép Công cộng của GNU để biết thêm chi tiết.

Bạn phải nhận được một bản sao của Giấy phép Công cộng của GNU kèm theo chương trình; nếu bạn chưa nhận được, xin gửi thư về Tổ chức Phần mềm Tự do, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

Bạn cũng phải bổ sung thông tin về địa chỉ liên lạc của bạn (thư điện tử và bưu điện).

Nếu chương trình chạy tương tác, hãy cho nó đưa ra một thông báo ngắn khi bắt đầu chạy chương trình như sau:

Gnomovision phiên bản 69, Copyright (C) năm, tên tác giả.

Gnomovision HOÀN TOÀN KHÔNG CÓ BẢO HÀNH; để xem chi tiết hãy gõ `show w'. Đây là một phần mềm tự do, bạn có thể phân phối tiếp với những điều kiện nhất định, gõ ‘show c’ để xem chi tiết.
Các lệnh có tính giả thiết `show w' và `show c' sẽ cho xem những phần tương ứng trong Giấy phép Công cộng. Tất nhiên những lệnh mà bạn dùng có thể khác với ‘show w' và `show c'; những lệnh này có thể là nhấn chuột hoặc lệnh trong thanh công cụ - tuỳ theo chương trình của bạn.

Khi cần thiết, bạn cũng cần phải lấy chữ ký của người phụ trách (nếu bạn là người lập trình) hoặc của trường học (nếu có) xác nhận từ chối bản quyền đối với chương trình. Sau đây là ví dụ:

Yoyodyne, Inc., bằng văn bản này từ chối tất cả các quyền lợi bản quyền đối với chương trình `Gnomovision' viết bởi James Hacker.

chữ ký của Ty Coon, 1 tháng 4 năm 1989
Ty Coon, Phó Tổng Giám đốc.

Giấy phép Công cộng này không cho phép đưa chương trình của bạn vào trong các chương trình độc quyền. Nếu chương trình của bạn là một thư viện thủ tục phụ, bạn có thể thấy nó hữu ích hơn nếu cho thư viện liên kết với các ứng dụng độc quyền. Nếu đây là việc bạn mong muốn, hãy sử dụng Giấy phép Công cộng Hạn chế của GNU thay cho Giấy phép này.

----------------------------------------------------

[/b]Bản gốc tiếng Anh:[b]

The GNU General Public License (GPL)

Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.

b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.

c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.

In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.

3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.

If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.

7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.

This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.

9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.

10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS

How to Apply These Terms to Your New Programs

If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.

To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found.

One line to give the program's name and a brief idea of what it does.
Copyright (C) <year> <name of author>

This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this when it starts in an interactive mode:

Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names:

Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.

signature of Ty Coon, 1 April 1989
Ty Coon, President of Vice

This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License.
Biên dịch Linux kernel - phần 4

9. Cài kernel
Phần này giới thiệu hai cách cài kernel vừa biên dịch và chỉnh định boot loader.

9.1 Cài qua "make install"
Ít người dùng đến chức năng "make install" này vì một số bản phân phối không có các tiện ích cần thiết để thực hiện trọn vẹn bước này. "make install" tiện lợi và an toàn hơn cài bằng tay vì nó thao tác các bước cần thiết để thiết lập kernel mới trên hệ thống. Các bước này bao gồm quy trình lưu trữ kernel cũ (trong thư mục /boot), copy kernel image mới, copy System.map mới, điều chỉnh boot loader configuration (lilo.conf hoặc grub.conf) và cập nhật boot loader.

Bước "make install" dựa trên hồ sơ Makefile và install.sh, một shell script thuộc thư mục ./arch/$ARCH/boot. Shell script install.sh "gọi" một số shell script khác như /sbin/installkernel và /sbin/new-kernel-pkg, ngoài ra các shell scripts này còn dựa vào một binary có tên là "grubby" để tạo thông tin trong grub.conf nếu bạn dùng GRUB. Các shell scripts "installkernel" và "new-kernel-install" thuộc gói mkinitrd của RedHat, các bản phân phối khác có những ứng dụng tương tự. Nếu bản phân phối bạn dùng không có gói tương tự, bạn phải cài kernel bằng tay (phần 9.2) hoặc tạo các script tương tự để thực hiện bước này. Trong khuôn khổ giới hạn của bài viết, tôi không đi sâu vào vấn đề tạo các script tiện ích.

Để cài Linux kernel mới, bạn chỉ đơn giản chạy lệnh # make install ở chế độ super user từ trong thư mục chứa mã nguồn của Linux kernel. Sau khi hoàn tất bước "make install" bạn nên kiểm tra lại cấu hình của boot loader trên máy và chạy các lệnh tương ứng (nếu cần) để chỉnh định boot loader cho chính xác.

9.1.1 Đối với GRUB
Ví dụ bạn có hai phiên bản kernel trên máy 2.4.20 (phiên bản đang chạy) và 2.4.26 (phiên bản vừa được biên dịch), sau khi chạy "make install", grub.conf có chi tiết tương tự như sau:

default=1
timeout=20
splashimage=(hd0,0)/boot/grub/splash.xpm.gz

title Linux (2.4.26)
root (hd0,0)
kernel /boot/vmlinuz-2.4.26 ro root=/dev/hda1
initrd=/boot/initrd-2.4.26.img

title Linux (2.4.20)
root (hd0,0)
kernel /boot/vmlinuz-2.4.20 ro root=/dev/hda1
initrd=/boot/initrd-2.4.20.img


- chi tiết cần chú ý là biến default. Trong ví dụ trên, bạn có hai kernel trong cấu hình GRUB cho các phiên bản 2.4.26 và 2.4.20. Nếu bạn muốn boot kernel 2.4.26 theo mặc định thì giá trị của default phải là 0 (grub đếm thứ tự các kernel từ giá trị 0, không phải từ giá trị 1). Khi chạy "make install", các tiện ích của "install" tự động đưa vào các chi tiết thuộc kernel mới vào cấu hình GRUB. Tuy nhiên, giá trị default vẫn giữ ở giá trị chỉ định cho kernel hiện đang hoạt động trên máy. Bạn cần chỉnh giá trị này để buộc boot loader tải lên phiên bản kernel mới. Một chi tiết hết sức quan trọng bạn cần chú ý là giá trị root (hdX,Y). Nếu GRUB đã được cài trong lúc cài đặt hệ thống từ CD và đã hoạt động hoàn chỉnh, bạn không nên thay đổi giá trị này. Giá trị này chỉ cần thay đổi nếu bạn thêm đĩa cứng và thay đổi các partitions trên máy.

- sau khi chỉnh định và lưu trữ grub.conf thích hợp, bạn chỉ cần tái khởi động máy. Nếu bạn dùng GRUB làm boot loader thì công tác tái biên dịch nhân Linux hoàn thành ở đây.

- giải pháp phòng bị trường hợp không thể boot vào kernel mới rất đơn giản nếu dùng GRUB làm boot loader. Bạn chỉ cần thêm một dòng fallback 1 vào cấu hình grub.conf là đủ. Chỉnh định này cho GRUB boot loader biết nếu dùng "default=0" để boot kernel mới nhất (2.4.26 trong ví dụ này) nhưng không thành công vì lý do nào đó thì thử boot lại với kernel cũ hơn (2.4.20). Xem thêm ở phần 10 nếu không thể boot được vào Linux vì boot loader bị hỏng.

9.1.2 Đối với LILO
Ví dụ bạn có hai phiên bản kernel trên máy 2.4.20 (phiên bản đang chạy) và 2.4.26 (phiên bản vừa được biên dịch), sau khi chạy "make install", lilo.conf có chi tiết tương tự như sau:

prompt
timeout=50
{b}default=linux{/b}
boot=/dev/hda
map=/boot/map
install=/boot/boot.b
message=/boot/message

image=/boot/vmlinuz-2.4.20
initrd=/boot/initrd-2.4.20.img
root=/dev/hda1
label=linux-2.4.20
read-only

image=/boot/vmlinuz
initrd=/boot/initrd-2.4.26.img
root=/dev/hda1
{b}label=linux{/b}
read-only


- chi tiết cần chú ý là biến default. Trong ví dụ trên, bạn có hai kernel trong cấu hình LILO cho các phiên bản 2.4.26 và 2.4.20. Nếu bạn muốn boot kernel 2.4.26 thì giá trị của default phải là giá trị label thuộc kernel nào bạn muốn dùng. Trong trường hợp này, label có giá trị là linux chỉ định cho kernel 2.4.26. Khi chạy "make install", các tiện ích của "install" đưa vào các chi tiết của kernel mới vào cấu hình LILO. Ở đây vmlinuz là symbolic link của hồ sơ vmlinuz-2.4.26. Bạn nên kiểm tra lại giá trị default để bảo đảm boot loader sẽ tải kernel vừa biên dịch khi boot.

- sau khi chỉnh định và lưu trữ lilo.conf theo ý muốn, bạn phải chạy lệnh:
# /sbin/lilo và chú ý trường hợp hệ thống báo lỗi trong bước cài lilo làm boot loader. Nếu có, điều chỉnh cho chính xác và thực hiện lại lệnh trên. Với ví dụ trên, bạn sẽ được báo kết quả trên console tương tự như:
Added linux*
Added linux-2.4.20
Giá trị nào đi kèm với dấu hoa thị smilie chỉ định cho kernel được boot theo mặc định.

- với LILO, giải pháp đơn giản nhất phòng bị trường hợp không thể boot vào kernel mới mang tính tạm thời. Trước khi tái khởi động máy dùng lệnh như sau:
# /sbin/lilo -R linux
rồi chạy
# reboot

Nên nhớ lệnh trên được đưa ra như một ví dụ cho kernel 2.4.20 và 2.4.26 với cấu hình boot loader như trên, bạn phải điều chỉnh đúng phiên bản kernel bạn đang biên dịch.

Lệnh thứ nhất cho LILO biết lần kế tiếp máy tái khởi động thì thử dùng kernel 2.4.26. Nếu không thành công cũng không chỉnh định cho kernel 2.4.26 làm kernel boot theo mặc định và lần boot kế tiếp sẽ dùng kernel 2.4.20 (kernel này chắc chắn phải làm việc được vì nó đã dùng để biên dịch kernel 2.4.26).

Lệnh thứ nhì chỉ đơn giản ra lệnh cho máy tái khởi động.

Nếu dùng lệnh "/sbin/lilo -R linux-x.xx.xx" và boot vào kernel mới thành công thì sau khi boot vào, bạn cần chỉnh định cho kernel x.xx.xx làm mặc định rồi mới chạy "/sbin/lilo -v" như đã nói ở trên (trong phần biến "default" của lilo.conf).


9.2 Cài qua các bước bằng tay
Các bước cài "bằng tay" tương tự như các bước "make install" ở trên nhưng được thao tác "bằng tay". Thật ra quy trình này rất đơn giản, điều bạn cần lưu ý là phải thực hiện chính xác để tránh những trở ngại trong bước này và trong giai đoạn boot vào kernel mới.

9.2.1 Tạo initrd
Trường hợp bạn biên dịch các drivers quan trọng ở dạng modules có liên hệ đến quy trình boot của Linux (như SCSI driver, RAID driver, các loại filesystem mà root filesystem dùng như ext3, jbd...) thì chắc chắn bạn phải cần đến initrd (INITial Ram Disk). Mục đích chính của initrd là phương tiện tải sẵn các driver cần thiết cho kernel trong quá trình boot. Nếu không muốn dùng initrd, bạn phải biên dịch các driver trực tiếp vào kernel (hay còn gọi là static compile). Nên chú ý một số bản phân phối Linux không dùng initrd, họ khuyến khích biên dịch các driver liên hệ đến quy trình boot trực tiếp vào kernel. Muốn tham khảo thêm chi tiết về RAM disk cho trường hợp này, xem <KERNEL_SRC>/Documentation/ramdisk.txt.

Quy trình tạo initrd rất đơn giản, chỉ cần chạy lệnh:
# /sbin/mkinitrd /boot/initrd-<KERNEL_VERSION>.img <KERNEL_VERSION>, trong đó:

- Tham số thứ nhất /boot/initrd-<KERNEL_VERSION>.img chỉ định cho hồ sơ và thư mục chứa hồ sơ initrd. Thông thường initrd của kernel được chứa trong thư mục /boot cùng với các thông tin và hồ sơ khác cần thiết cho quy trình boot.

- Tham số <KERNEL_VERSION> thứ nhì chính là kernel nào bạn muốn tạo initrd cho nó. Tất nhiên thư mục chứa các modules cho kernel version này phải hiện hữu ở /lib/modules/, nếu không bạn sẽ được system báo lỗi.

Tùy bản phân phối, mkinitrd đòi hỏi thêm các thông số cụ thể để chỉ đường dẫn đến kernel. Nếu gặp trở ngại trong bước tạo mkinitrd bạn nên tham khảo tài liệu cụ thể cho bản phân phối mình đang dùng hoặc tối thiểu là xem man mkinitrd và tài liệu <KERNEL_SRC>/Documentation/initrd.txt để xem thêm các thông tin cần thiết.

Một điểm đáng chú ý là từ kernel 2.5.x (development kernel) trở đi, initramfs được phát triển với mục đích hỗ trợ và sẽ đi đến chỗ thay thế initrd (init ram disk). Ưu điểm nổi bật của initramfs là nó có thể chứa các bộ lưu trữ ở dạng cpio "newc" hoặc "crc" (được nén hoặc không được nén). initramfs cho đến nay chưa phổ biến và ứng dụng rộng rãi trên các bản phân phối Linux. Tuy nhiên, hướng phát triển và ứng dụng initramfs có vẻ đầy hứa hẹn.

9.2.2 Copy kernel và System.map
Sau khi hoàn thành bước "make modules_install" (phần 8.2), lúc này bạn đã có trọn bộ các bộ phận cần thiết cho kernel mới bao gồm kernel image và các modules thuộc kernel này.

- copy bzImage từ <KERNEL_SRC>/arch/i386/boot/ đến thư mục /boot, ví dụ:
# cp /usr/src/linux-2.4.26/arch/i386/boot/bzImage /boot/bzImage-2.4.26

install script của RedHat và một số phân phối khác bao gồm bước copy bzImage thành vmlinuz, bạn có thể thực hiện (hay không tùy ý, bước này tương tự như bước ở trên) như sau:
# cp /usr/src/linux-2.4.26/arch/i386/boot/bzImage /boot/vmlinuz-2.4.26

kế tiếp là xoá symbolic link cũ (nếu có) của vmlinuz trong thư mục /boot:
# rm -f /boot/vmlinuz

và sau đó tạo symbolic link mới cho vmlinuz-2.4.26 thành:
# ln -s /boot/vmlinuz-2.4.26 /boot/vmlinuz

Tất nhiên bạn phải điều chỉnh lại cấu hình boot loader để thích ứng với cách gọi "bzImage" hoặc "vmlinuz" này cho giá trị image (trong lilo.conf) hoặc giá trị kernel (trong grub.conf). Cách dùng và cách gọi bzImage và vmlinuz tạo khá nhiều bối rối cho người dùng Linux khi tiếp cận quy trình biên dịch kernel. Một số bản phân phối Linux dùng bzImage, một số khác lại dùng vmlinuz. Dù gì đi chăng nữa, đây cũng chỉ là cách dùng và cách gọi; bạn nên dùng theo cách bản phân phối Linux nào có trên máy.

- phần còn lại là bước copy hồ sơ System.map:
# cp /usr/src/linux-2.4.26/System.map-2.4.26 /boot/System.map-2.4.26

kế tiếp là xoá symbolic link cũ của System.map trong thư mục /boot:
# rm -f /boot/System.map

và sau đó, tạo symbolic link mới cho System.map:
# ln -s /boot/System.map-2.4.26 /boot/System.map


9.2.3. Chỉnh bootloader config

9.2.3.1 Nếu bootloader là GRUB
Ví dụ bạn có hai phiên bản kernel trên máy 2.4.20 (phiên bản đang chạy) và 2.4.26 (phiên bản vừa được biên dịch) thì grub.conf tương tự như sau:

default=0
timeout=20
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
title Linux (2.4.20)
root (hd0,0)
kernel /boot/vmlinuz-2.4.20 ro root=/dev/hda1
initrd=/boot/initrd-2.4.20.img


Chỉnh thành:

default=0
timeout=20
splashimage=(hd0,0)/boot/grub/splash.xpm.gz

title Linux (2.4.26)
root (hd0,0)
kernel /boot/vmlinuz ro root=/dev/hda1
initrd=/boot/initrd-2.4.26.img

title Linux (2.4.20)
root (hd0,0)
kernel /boot/vmlinuz-2.4.20 ro root=/dev/hda1
initrd=/boot/initrd-2.4.20.img


Sau khi đã lưu trữ (save) cấu hình của /etc/grub.conf ở trên (/etc/grub.conf là symbolic link đến /boot/grub/menu.1st) và tái khởi động máy để bắt đầu dùng kernel vừa được biên dịch. Nếu bạn dùng GRUB làm boot loader thì công tác tái biên dịch nhân Linux hoàn thành ở đây. Nên lưu ý trong ví dụ này, tôi dùng vmlinuz thay vì dùng bzImage, bạn nên chọn lựa theo ý và điều chỉnh cho phù hợp trong grub.conf.

Đối với giải pháp phòng bị trường hợp không thể dùng GRUB để boot vào kernel mới, xem chi tiết ở phần 9.1.1 ở trên.

9.2.3.2 Nếu bootloader là LILO
Ví dụ bạn có hai phiên bản kernel trên máy 2.4.20 (phiên bản đang chạy) và 2.4.26 (phiên bản vừa được biên dịch) thì lilo.conf tương tự như sau:

prompt
timeout=50
default=linux
boot=/dev/hda
map=/boot/map
install=/boot/boot.b
message=/boot/message

image=/boot/vmlinuz
initrd=/boot/initrd-2.4.20.img
root=/dev/hda1
label=linux
read-only


Chỉnh /etc/lilo.conf để cài kernel mới (2.4.26 cho ví dụ ở đây), bạn có /etc/lilo.conf như sau:

prompt
timeout=50
{b}default=linux{/b}
boot=/dev/hda
map=/boot/map
install=/boot/boot.b
message=/boot/message

image=/boot/vmlinuz-2.4.20
initrd=/boot/initrd-2.4.20.img
root=/dev/hda1
{b}label=linux-2.4.20{/b}
read-only

image=/boot/vmlinuz
initrd=/boot/initrd-2.4.26.img
root=/dev/hda1
{b}label=linux{/b}
read-only


Sau khi đã lưu trữ (save) cấu hình của /etc/lilo.conf ở trên, chạy lệnh:
# /sbin/lilo để đăng ký kernel mới cho LILO boot loader.

Đối với giải pháp phòng bị trường hợp không thể dùng LILO để boot vào kernel mới, xem chi tiết ở phần 9.1.2 ở trên.


10. Tái khởi động máy và chỉnh lý nếu gặp trục trặc
Tới đây, bạn cần tái khởi động máy để boot vào kernel mới. Nếu không có gì trở ngại, máy sẽ boot vào Linux bình thường. Bạn có thể kiểm lại xem kernel mình đang chạy có đúng phiên bản vừa được biên dịch hay không bằng cách chạy:
$ uname -r

hoặc,
$ cat /proc/version

Nếu kết quả báo phiên bản kernel cũ thì có nghĩa boot loader (LILO hoặc GRUB) đã không boot kernel vừa được biên dịch. Bạn nên kiểm tra lại boot configuration (lilo.conf hoặc grub.conf) cho đúng theo chi tiết đã nêu ở trên.

10.1 Bị treo khi bootloader đang boot vào linux
Trở ngại trong giai đoạn boot loader chuẩn bị boot vào Linux thông thường do cấu hình boot loader ấn định không đúng và boot loader được cài lên không đúng boot partition hoặc MBR bị hỏng (hiếm thấy trong quá trình tái biên dịch và cài kernel mới nếu thực hiện đúng quy cách). Trong trường hợp này, bạn phải:
- dùng đến đĩa mềm "cấp cứu" được tạo ở phần 6.1 để boot vào Linux

- Đến giai đoạn này bạn hẳn phải biết vị trí của root partition (/) trên đĩa cứng để mount partition của đĩa cứng:
# mount /dev/hdXy /mount/point/somewhere, trong đó X là ví trí đĩa cứng trên máy, y là vị trị root partition trên đĩa cứng này.

- đổi root (chroot) trở thành root partition của đĩa cứng:
# chroot /mount/point/somewhere, trong đó /mount/point/somewhere là nơi đĩa cứng của bạn được mount.

- kiểm tra lại cấu hình của boot loader và cài lại boot loader cho máy (xem phần 9.1.1 hoặc 9.1.2 tùy theo boot loader bạn dùng là GRUB hay LILO). Điểm cần chú ý ở đây cho GRUB boot loader là bạn phải chạy lệnh:
# /sbin/grub-install /dev/hdX, trong đó /dev/hdX là disk nào chứa MBR cho hệ thống (thường là đĩa đầu tiên trên máy - Primary Master). Lệnh trên sẽ tái thiết lập boot record và loại bỏ các trường hợp MBR bị hỏng. Tương tự cho LILO, bạn phải chạy lệnh:
# /sbin/lilo.

10.2 Bị treo trong quá trình kernel được load
Nếu bạn vướng vào các trở ngại trong giai đoạn kernel đang được tải lên thông thường là do các drivers tối cần thiết để mount filesystems trên máy bị thiếu. Giả sử bạn dùng ext3 cho root partition (/) chứa kernel. Để có thể mount root partition này, ext3 module phải được biên dịch và initrd phải tải module này lên. Tương tự ứng dụng cho các trường hợp dùng filesystem khác và cũng thiếu module.

Trong trường hợp này, bạn cần ghi xuống phần lỗi được báo trong khi boot vào kernel mới để xác định lỗi này thuộc phần nào của cấu hình biên dịch nhân Linux và từ đó điều chỉnh lại và tái biên dịch lại cho thích ứng. Nói một cách tổng quát, bạn phải:
- tái khởi động lại máy và boot vào phiên bản cũ của kernel (hoặc boot loader sẽ boot vào phiên bản cũ của kernel nếu bạn dùng biện pháp trù bị đã được đề cập ở phần 9.1.1 và 9.1.2 ở trên)
- chọn lựa và chỉnh định cấu hình biên dịch nhân Linux lại (xem phần 7.2.2 để tránh lặp lại bước lựa chọn cấu hình một cách không cần thiết).
- thực hiện lại các bước đã nêu ra trong phần 8 và 9 ở trên


11. Vá và biên dịch kernel
Mã nguồn của Linux kernel thường được "vá" rồi tái biên dịch nhiều hơn là được biên dịch từ trọn bộ mã nguồn tải về từ kernel.org nếu bạn đã quen thuộc với quy trình tái biên dịch hoặc bạn có nhu cầu phải cập nhập kernel của máy thường xuyên. Tại sao lại cần "vá"? Mã nguồn của Linux kernel cần được vá vì các lý do thường gặp như sau:
- mã nguồn của Linux kernel được cập nhật. Bạn đã có sẵn mã nguồn của Linux kernel (cũ hơn) trên máy. Muốn nâng cấp phiên bản của Linux kernel, bạn chỉ cần tải các "miếng vá" về để vá (thay vì phải tải trọn bộ mã nguồn của Linux kernel cho phiên bản mới).
- một số "drivers" được cập nhật. Để xử dụng các driver mới này (và các drivers này cần được biên dịch để nối với các thư viện hiện hành trên máy), bạn chỉ cần tải các "miếng vá" của những drivers này để vá Linux kernel và tái biên dịch chúng.

11.1 Các điểm quan trọng trước khi vá
Tương tự như phần 6.2, 6.3 và 6.4 ở trên, quy trình tải các miếng vá (patch) cho Linux kernel y hệt như tải trọn bộ gói mã nguồn của Linux kernel. Điểm khác biệt là bạn phải tải các hồ sơ khởi đầu bằng patch và chọn cho đúng các patch cần thiết cho kernel cần được patch.

Điểm tối yếu cần ghi nhớ là khi vá mã nguồn của Linux kernel, bạn phải vá đúng thứ tự và đầy đủ các miếng vá cho đến đúng phiên bản cần có. Ví dụ, bạn đang có phiên bản kernel là 2.4.20 trên máy và bạn muốn tái biên dịch phiên bản kernel của máy trở thành 2.4.26. Thay vì tải trọn bộ mã nguồn của kernel 2.4.26 và biên dịch lại (như đã trình bày trong suốt bài viết này), bạn có thể tải các bản vá 2.4.21, 2.4.22, 2.4.23, 2.4.24, 2.4.25 và 2.4.26 về máy. Tổng cộng dung lượng các bản vá này chỉ là một phần rất nhỏ so với trọn bộ gói mã nguồn 2.4.26. Tất nhiên bạn đã có mã nguồn của kernel 2.4.20 trên máy không thì không thể vá được.


11.2 Tải, xả và vá
Các miếng vá thường được nén ở hai dạng: .gz hoặc .bz2 như gói mã nguồn. Bạn có thể tùy chọn và có thể tải các miếng vá này về bất cứ nơi nào trên máy. Sau khi tải chúng về, bạn có thể thực hiện quy trình tương tự như sau:

giả định các bản vá được nén ở dạng .bz2, nơi chứa mã nguồn của Linux kernel ở /usr/src và thực tính của các patch này đã được kiểm tra. Trong ví dụ này, giả định phiên bản đang dùng trên máy là 2.4.20 và phiên bản cần được vá sẽ là 2.4.26

a)
# chuyển vào thư mục /usr/src
$ cd /usr/src

b)
# xả nén các patch ở dạng .bz2 vào thư mục /usr/src. Lặp lại cho đến khi xả hết các patch cần được vá
$ tar xfvj /path/to/patch/patch-x.xx.xx ./

c)
# dọn dẹp sạch sẽ mã nguồn kernel hiện có trên máy, giả định phiên bản mã nguồn hiện có là 2.4.20
cd ./kernel-2.4.20
make mrproper


d)
# lưu một bản mã nguồn kernel 2.4.20 trong thư mục /usr/src phòng bị cho sự cố trong quá trình vá (nếu bạn không lưu một bản mã nguồn nguyên thủy của kernel 2.4.20 trên máy, hoặc bản mã nguồn 2.4.20 này cũng đã được vá trước đây)
tar cvf ../linux-2.4.20.tar ./

e)
# vá các miếng vá theo đúng thứ tự và theo dõi bất cứ lỗi nào được báo
$ patch -p1 < ../patch-2.4.21
$ patch -p1 < ../patch-2.4.22
$ patch -p1 < ../patch-2.4.23
$ patch -p1 < ../patch-2.4.24
$ patch -p1 < ../patch-2.4.25
$ patch -p1 < ../patch-2.4.26


hoặc thực hiện kiểu "lười" như sau:

# tạo một biến PATCH tạm thời chứa tên các patch cần patch theo đúng thứ tự, tách rời bằng phím trống (space)
$ export PATCH="patch-2.4.21 patch-2.4.22 patch-2.4.23 patch-2.4.24 patch-2.4.25 patch-2.4.26"

# chạy vòng lặp
$ for item in $PATCH; do patch -p1 < ../$item; done

Nếu trong khi vá không có gì trở ngại, bạn sẽ thấy các thông tin tương tự:

patching file xxx
patching file yyy
....

cho đến khi kết thúc.

Nếu trong khi vá bị báo lỗi, bạn phải ngưng bước vá (ctrl-C) và kiểm tra xem bạn có dùng đúng bản vá và thực hiện các bản vá đúng thứ tự phiên bản hay không. Không nên tiếp tục với bước vá khi gặp lỗi vì chắc chắn bạn sẽ gặp trở ngại trong giai đoạn biên dịch sau này. Để tránh các trở ngại về sau, nếu bị báo lỗi trong khi vá, cách tốt nhất bạn nên xoá trọn bộ thư mục chứa mã nguồn của Linux kernel (đang được vá và bị lỗi) và xả gói mã nguồn nguyên thủy hoặc gói bạn vừa lưu trữ ở trên rồi thử lại.

f)
# xoá thư mục chứa mã nguồn vừa vá và bị trục trặc, thư mục linux-2.4.20 được dùng như một ví dụ ở đây
$ cd /usr/src
$ rm -rf ./linux-2.4.20


g)
# xả gói mã nguồn được lưu trữ ở trên
$ tar xvf linux-2.4.20
$ cd ./linux-2.4.20


và sau đó lặp lại bước vá (bước e) theo đúng thứ tự các miếng và.

Sau khi vá thành công, bạn nên thực hiện hai bước kế tiếp như sau trước khi bắt tay vào việc chuẩn bị cấu hình biên dịch nhân Linux và biên dịch mã nguồn:

h)
# đổi tên thư mục chứa mã nguồn cho đúng phiên bản đã được vá (giúp bạn nhận diện phiên bản của mã nguồn đang có trên máy đã được vá tới phiên bản nào)
$ cd /usr/src
$ mv ./linux-2.4.20 ./linux-2.4.26


i)
# chỉnh giá trị "VERSION" trong Makefile chính của mã nguồn Linux. Thư mục chứa mã nguồn lúc này đã được đổi tên thành linux-2.4.26
$ vi ./linux-2.4.26/Makefile

Vài dòng đầu của hồ sơ Makefile này chứa các thông tin tương tự như sau (nếu mã nguồn của phiên bản 2.4.20 được xả từ gói mã nguồn nguyên thủy):

VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 20
EXTRAVERSION =


Bạn cần đổi giá trị SUBLEVEL thành 26 và lưu hồ sơ Makefile này (cho ví dụ này, hoặc bất cứ phiên bản nào bạn đã vá tới - xem thêm chi tiết về quy định phiên bản Linux kernel ở phần 3). Giá trị phiên bản 2.6.26 lấy từ hồ sơ Makefile sẽ được dùng trong quá trình biên dịch và cài đặt kernel về sau. Nếu bạn không điều chỉnh giá trị "VERSION" ở bước này, bước cài kernel về sau sẽ viết chồng lên kernel 2.4.20 đang có trên máy. Nói về mặt kỹ thuật việc viết chồng lên không có gì trở ngại. Tuy nhiên, nếu bạn gặp trục trặc sau khi đã biên dịch kernel nhưng không boot vào được thì sự thể sẽ rất phức tạp vì bạn không còn bản kernel chạy được trên máy.

Tới đây bạn đã thực hiện thành công bước vá mã nguồn Linux kernel và các bước phòng bị cần thiết. Bạn có thể tiếp tục với công việc tái biên dịch Linux kernel như đã nói trên.

<Hết>
<hnd, vninformatics.com / diendantinhoc.net - 10/06/2004>

Tác giả : Conmale (hnd)
Nguồn : www.diendantinhoc.net
Biên dịch Linux kernel - phần 3

Hướng dẫn chi tiết các bước trong quá trình tái biên dịch Linux kernel cho kernel 2.4.x và 2.6.x.
Các yếu tố cần thiết trong việc chuẩn bị cấu hình biên dịch Linux kernel và các bước tạo.
<hnd viết cho vninformatics.com>

7.2 Điều chỉnh cấu hình biên dịch nhân Linux
Vậy, để điều chỉnh các chọn lựa cho một cấu hình biên dịch nhân Linux, có một số cách thực hiện chuyện này.

7.2.1 Các "config" tools
Như đã đề cập ở phần 6.5, mặc định cấu hình biên dịch nhân nằm ở ./arch/i386/defconfig. Khi khởi động một "config" tool nó sẽ tự động đọc và dùng nội dung của config mặc định này trước khi bạn chỉnh sửa theo ý.

Để chỉnh cấu hình biên dịch nhân Linux, chuyển vào thư mục chứa mã nguồn của kernel (đã xả nén):
$ cd /usr/src/linux-2.4.26 (ví dụ này dùng kernel 2.4.26 - xem lại phần xả nén ở phần 6.4)
và việc đầu tiên rất nên làm đó là chạy lệnh:
$ make mrproper
Không kể bạn dùng bản phân phối Linux nào và phiên bản Linux kernel nào, bạn nên chạy lệnh này trước khi thực hiện quy trình tái biên dịch kernel. Target "mrproper" này dùng để xoá hết tất cả những gì còn "vất vưởng" trong các cây chứa mã nguồn của Linux kernel để nắm chắc mã nguồn trước khi được biên dịch phải ở tình trạng "sạch sẽ".

Có ba phương tiện "config" phổ biến có thể dùng để chỉnh cấu hình biên dịch nhân Linux. Sau khi chuyển vào thư mục /usr/src/linux-2.4.26, bạn có thể chọn một trong ba cách:
- make config
- make menuconfig
- make xconfig


Trong đó,
- make config là phương tiện đơn giản nhất và không đòi hỏi thêm bất cứ thư viện nào khác để chạy công cụ này. make config sẽ tạo ra một loạt câu hỏi (ở dạng prompt) và sau khi nhận được câu trả lời của bạn (Y, N, M như đã nói ở trên sau khi bạn nhấn phím Enter, xác nhận câu trả lời của mình), nó sẽ hình thành một cấu hình biên dịch nhân Linux. Nhược điểm của loại config này ở chỗ, nếu bạn lỡ trả lời sai (chọn Y, N hoặc M và gõ phím Enter), bạn không thể quay ngược lại để điều chỉnh mà phải bắt đầu lại từ đầu. Phương tiện "make config" này chỉ tiện lợi cho những ai rất kinh nghiệm và nắm rõ mình cần gì trong cấu hình biên dịch nhân, nó cũng tiện lợi cho quy trình chỉnh cấu hình biên dịch nhân từ xa (xuyên qua console và không dùng được X11 forward vì lý do gì đó). Sau khi hoàn tất các câu hỏi, công cụ này sẽ lưu trữ một cấu hình biên dịch nhân (được lưu ở dạng .config trong thư mục chứa mã nguồn của Linux) và sẵn sàng cho bước tạo dependency cho kernel build. Nếu hồ sơ .config đã tồn tại từ lần biên dịch trước, nó sẽ bị viết chồng lên ở giai đoạn này.
<insert hình>

- make menuconfig nâng cấp lên một mức cao hơn so với make config. Công cụ này cần thư viện và binaries "ncurses" để tạo GUI đơn giản. Với công cụ này, bạn có thể tái điều chỉnh các chi tiết tuỳ thích mà không phải bắt đầu lại từ đầu (nếu lỡ chọn sai) như dùng make config. Trên GUI đơn giản này, bạn có thể di chuyển, thay đổi các chọn lựa bằng cách dời chuyển phím mũi tên (lên xuống), chọn Y bằng phím Y, chọn N bằng phím N và chọn M bằng phím M. Với công cụ này, bạn cũng có thể tải một cấu hình biên dịch nhân có sẵn (đã làm từ trước và đã biên dịch thành công chẳng hạn) mà chẳng phải đi xuyên qua mọi chọn lựa để hình thành một cấu hình biên dịch nhân mới. Một đặc tính của công cụ này là nó chứa "help context sensitive" (phần giúp đỡ hoặc thông tin cho từng mục trong quá trình điều chỉnh configuration). Nếu bạn không nắm rõ giá trị hoặc tác dụng của module nào đó, bộ phận "help" này chắc chắn sẽ hữu ích. Sau khi đã hoàn thành các chọn lựa, bạn có thể lưu trữ một bản configuration trên máy để lần sau dùng lại và "exit" đồ nghề này. Ở giai đoạn này, một bản configuration được lưu lại (ở dạng .config trong thư mục chứa mã nguồn của Linux) và sẵn sàng cho bước tạo dependency cho kernel build. Tương tự như "make config", nếu hồ sơ .config đã tồn tại từ lần biên dịch trước, nó sẽ bị viết chồng lên.
<insert hình>

- make xconfig có lẽ là phương tiện được dùng rộng rãi nhất, nhất là cho những hệ thống chạy X Window. make xconfig cần trọn bộ thư viện Qt và X Window để tạo GUI. Các chọn lựa và cách di chuyển trong GUI này để điều chỉnh hoàn toàn giống như trường hợp dùng menuconfig và thêm một khả năng nữa là có thể dùng mouse để chọn. Nếu bạn cần tái biên dịch kernel và có thể dùng X Window thì nên dùng công cụ xconfig này vì nó dễ dùng nhất.

Trên Linux kernel 2.6.x series có thêm make gconfig. Tương tự như make xconfig, "gconfig" cũng tạo GUI config tool nhưng GUI này dựa trên thư viện Gtk.


7.2.2 Một số điểm cần chú ý trong giai đoạn hình thành cấu hình biên dịch nhân
- Dùng cấu hình biên dịch nhân có sẵn và điều chỉnh cho thích hợp với nhu cầu của mình. Nếu bạn dùng bản phân phối của RedHat, cấu hình biên dịch nhân có trong thư mục /boot ở dạng config-<KERNEL_VERSION> (hồ sơ cấu hình này từ các kernel do RedHat cung cấp). Để dùng cấu hình biên dịch nhân này, bạn có thể dùng make menuconfig hoặc make xconfig để tải configuration này lên và điều chỉnh theo ý muốn. Thật ra không có bất cứ tài liệu nào có thể giải thích cặn kẽ từng chọn lựa cho mỗi cấu hình máy cả. Ở mức độ tái biên dịch một kernel, bạn cần hiểu cấu hình máy và những chọn lựa trong một configuration đến mức độ có thể quyết định chọn lựa những gì cho thích hợp. Bản phân phối Debian cũng lưu trữ các cấu hình biên dịch nhân trong thư mục /boot tương tự như bản phân phối RedHat. Các bản phân phối khác có một số tương đồng và dị biệt, bạn nên tham khảo thêm các hướng dẫn cụ thể cho bản phân phối mình đang dùng.

- Lưu trữ cấu hình biên dịch nhân cho lần biên dịch kế tiếp. Nếu vì lý do gì đó khiến giai đoạn biên dịch kernel bị hỏng, bạn cần xem xét đoạn báo lỗi sau cùng khi công cụ biên dịch (compiler) thoát ra với "tình trạng không thành công" (exit status is not 0). Thông thường compiler thoát ra nửa chừng vì cách chọn lựa cấu hình biên dịch nhân có những điểm không thích hợp và thoả mãn (liên hệ nhau). Những lỗi được báo trên console giúp bạn xác định trục trặc nằm trong khu vực nào của cấu hình biên dịch nhân. Bạn chỉ cần tải hồ sơ biên dịch đã được lưu trữ lần cuối cùng lên và vào thẳng khu vực bị sự cố để xem xét và điều chỉnh, thay vì phải thiết lập từ dầu để tránh va vào những lỗi khác. Mỗi khi điều chỉnh và thay đổi cấu hình biên dịch nhân, bạn lại tiếp tục lưu lại một bản và đặt tên cho nó một cách hợp lý (ví dụ kernel-2.4.26-1 cho configuration thứ nhất, kernel-2.4.26-2 cho configuration thứ nhì.....).

- Nếu bạn dùng một "vanilla" kernel, mã nguồn kernel được tải về từ kernel.org hoặc mirror site của nó (bài viết này tập trung chủ yếu vào "vanilla" kernel), sau khi hoàn thành bước make config hoặc make menuconfig hoặc make xconfig, cấu hình biên dịch nhân đã được bạn điều chỉnh và chọn lựa sẽ đưọc lưu trữ ở dạng dấu (hidden) ở ./.config (các hồ sơ và thư mục bắt đầu bằng dấu chấm . được xếp loại là hidden files, chỉ có ls -la mới thấy chúng). Lần kế tiếp, sau khi chạy một trong số lệnh trên và tiếp nhận các thay đổi thì cấu hình biên dịch nhân lại tự động viết chồng lên ./.config. Cho nên, bạn có thể lưu trữ hồ sơ ./.config thành một hồ sơ có tên khác trước khi điều chỉnh và chọn lựa lần kế tiếp.

- Ngoài make config, make menuconfig, make xconfig hoặc make gconfig (cho kernel 2.6.x series), bạn còn có thể dùng một lệnh khác cho cả kernel series 2.4.x và 2.6.x là: make oldconfig. make oldconfig là một trường hợp đặc biệt dùng để đọc và dùng các chọn lựa đã có sẵn trong ./.config mà không cho bạn cơ hội đi xuyên qua để điều chỉnh và chọn lựa. Trường hợp này rất tiện lợi nếu bạn đã điều chỉnh và chọn lựa thành công một cấu hình biên dịch nhân cho mình.

Kernel 2.6.x series còn có bốn target cho bước này:
make defconfig: tạo một cấu hình biên dịch nhân mới với chế độ mặc định cho mọi chọn lựa
make allmodconfig: tạo một cấu hình biên dịch nhân mới với chế độ chọn lựa các modules khi có thể được
make allyesconfig: tạo một cấu hình biên dịch nhân mới với chế độ tiếp nhận yes (Y) cho mọi chọn lựa
make allnoconfig: tạo một cấu hình biên dịch nhân mới với chế độ tiêp nhận no (N) cho mọi chọn lựa. Chế độ này sẽ tạo ra một kernel rất nhỏ và đơn giản.

Hiếm khi bạn điều chỉnh một cấu hình biên dịch nhân Linux lần đầu mà không hề bị lỗi trong khi biên dịch. Cách lưu trữ từng configuration cho mỗi lần hiệu chỉnh là cách tốt nhất để bảo đảm "lỗi" lần trước sẽ không tái diễn. Nếu bạn chỉ đơn giản dùng cấu hình biên dịch nhân có sẵn (như RedHat Linux chứa trong /boot) và không điều chỉnh gì cả thì ngoài mục đích vá lỗi, lối dùng này chẳng có tác dụng gì về mặt nâng cao hiệu năng của máy.


8. Các bước xây dựng
8.1 Bước tạo dependency, dọn dẹp và tạo kernel image
Bước này có thể chạy ba lệnh:
make dep
make clean
make bzImage


hoặc gom chung lại thành một nhóm:
make dep clean bzImage

Nếu bạn chạy dep, clean và bzImage riêng biệt thì phải trông chừng khi nào lệnh thứ nhất hoàn tất để tiếp tục chạy lệnh thứ nhì và tiếp theo. Nếu bạn chạy ba lệnh một lượt thì lệnh thứ nhì tự dộng nối tiếp lệnh thứ nhất và lệnh thứ ba nối tiếp lệnh thứ nhì. Bạn không cần phải chờ đợi.

- bước "dep" là bước tạo dependencies và các includes cần thiết cho kernel. Bước này có thể mất nhiều phút, tùy vào CPU của từng máy. Đối với kernel series 2.6.x, bước này không cần thiết nữa.

- sau khi xong bước "dep", bước "clean" dùng để dọn dẹp tất cả những "objects" vụn vặt, không còn cần thiết vì dependencies đã hoàn tất ở trên.

- bước kế tiếp "bzImage" là bước tạo kernel image. Đây là bước hết sức quan trọng trong ba bước này. Nếu có sự cố gì xảy ra thì phải quay lại điều chỉnh cấu hình biên dịch nhân và đi xuyên qua các bước "make dep", "make clean" trở lại (cần phải chạy một số lệnh dọn dẹp trước khi make dep clean bzImage trở lại, vấn đề này sẽ được đề cập trong phần 10). Trên máy chạy Athlon Thunderbird 1.4Ghz, tôi mất chừng 10 phút để hoàn thành bước này. Trên một máy Pentium 233MMX cũ, tôi mất hơn 40 phút mới hoàn thành bước tạo kernel image.

Nếu ba bước trên hoàn toàn thành công, bạn có thể tìm thấy "kernel image" nằm trong thư mục ./arch/$ARCH/boot, trong đó $ARCH là dòng phần cứng của kernel bạn muốn biên dịch. Nếu máy bạn thuộc dạng i386, bạn sẽ tìm thấy kernel image trong ./arch/i386/boot. Kernel image này đã được tạo ra nhưng chưa được cài và ở bước này, nó chỉ lưu trong thư mục trên cho các bước về sau.

Thật ra có thể tạo nhiều dạng "kernel image". Dạng kernel image được tạo từ "make bzImage" là dạng phổ biến nhất hiện nay vì nó nén kernel image tốt nhất và thích hợp với hầu hết các loại computer. Bạn cũng có thể dùng:
make zImage, make zDisk hoặc make zLilo để tạo kernel image nếu kernel dự kiến rất nhỏ và không cần kỹ thuật nén cao độ như "bz". Dùng các dạng này cũng thích hợp trong trường hợp máy của bạn quá cũ và có thể có sự cố với "bzImage". Chỉ cần nắm một cách khái quát như sau:
- Phần bz hoặc z đi trước các image ở trên chỉ định cho loại nén nào được dùng với kernel image.
- Phần Image hoặc Disk hoặc Lilo chỉ định cho "loại" kernel image.
- Kernel image này được xả nén "on-the-fly" trong quá trình boot vào Linux sau này.

Xuyên qua ba bước ở trên, bạn sẽ thấy vô số thông điệp chạy trên console (ở kernel 2.6.x thông điệp chạy trên console ít hơn rất nhiều). Bất cứ lỗi nào (error) được báo trong bước này đều phải điều chỉnh cấu hình biên dịch nhân và trở lại bước "make dep". Cho đến giai đoạn này, lý do gây ra lỗi thường là:
- đồ nghề dùng để biên dịch không đúng phiên bản (xem phần 4.1 và 4.2 cho kernel series này bạn đang biên dịch)
- điều chỉnh sai hoặc thiếu một số chọn lựa nào đó trong cấu hình biên dịch nhân. Xem lỗi báo trước khi compiler thoát ra để xác định lỗi này thuộc phần nào trong cấu hình biên dịch nhân mà chỉnh lại cho thích hợp, nên dùng phương pháp tải và lưu trữ cấu hình biên dịch nhân đã đề cập trong phần 7.2.2 ở trên
- cấu hình máy quá thấp (memory / diskspace) không đủ để thực hiện ba bước ở trên. Nếu gặp sự cố này, nên nâng cấp máy hoặc dùng một máy khác để build kernel cho máy này.

Linux kernel 2.6.x series đơn giản hoá chỉ với một target "make all". Target này bao gồm luôn phần "make modules" trong bước 8.2 kế tiếp.

8.2 Bước tạo modules và cài modules
Bước này có thể chạy hai lệnh:
make modules
make modules_install


hoặc gom chung lại thành một dòng:
make modules modules_install

Điểm khác biệt giữa cách chạy hai lệnh riêng biệt hoặc chạy chung một dòng lệnh ở đây nằm ở chỗ:
- bạn có thể chỉ muốn biên dịch modules cho kernel mà không muốn cài (install) trên máy ngay sau khi các modules được biên dịch xong,
- hoặc bạn chỉ muốn biên dịch modules trên máy này rồi sẽ mang qua máy khác để cài.

Thông thường "make modules modules_install" đi chung vì ít người build modules trên một máy rồi mang đi cài trên một máy khác. Nếu chạy hai lệnh này một lượt, bạn phải chạy ở chế độ "super user" không thì modules không install được vì chỉ có root (super user) mới có thể "install" các modules vừa được biên dịch. Nếu bạn tách rời hai lệnh trên thì các lệnh tách rời như sau:
make modules # chạy bằng user account bình thường
su # chuyển sang chế độ "super user"
[enter password]
make modules_install # cài modules vừa biên dịch xong.

Bước "make modules" là bước biên dịch và tạo ra các modules (mà bạn đã chọn ở dạng M trong quá trình chỉnh lý cấu hình biên dịch nhân). Các modules đã được biên dịch sẽ được lưu trữ trong các thư mục thích ứng với từng nhóm "drivers" trong cây mã nguồn (kernel source tree). Giai đoạn này là giai đoạn biên dịch lâu nhất trong trọn bộ quá trình compiler thực sự biên dịch mã nguồn của kernel. Trên một máy chạy Athlon Thunderbird 1.4Ghz, bước này mất chừng 25 phút. Trong khi đó cùng số lượng modules cần biên dịch chạy trên máy Pentium 233MMX mất chừng trên 4 giờ đồng hồ.

Bước "make modules_install" sẽ "cài" các modules vừa được biên dịch vào thư mục /lib/modules/<kernel_version>. Nếu liệt kê thư mục này (ls), bạn sẽ thấy ít nhất một thư mục chứa modules cho kernel đang chạy trên máy hoặc nhiều thư mục cho nhiều phiên bản kernel trước đây (có từ quy trình cập nhật kernel bằng rpm hoặc quy trình nào đó tuỳ theo bản phân phối, hoặc từ quy trình biên dịch kernel tương tự như bài viết này). Khi boot Linux bằng một phiên bản kernel nào đó có trên máy, các modules thuộc kernel này (trong thư mục thích ứng với kernel version) sẽ được ứng tải.

Đối với kernel 2.4.x series, bạn có thể tham khảo chi tiết thông tin về modules, cách biên dịch modules tổng quát và cách xử dụng modules (thuộc user space) trong hồ sơ ./Documentation/modules.txt thuộc mã nguồn kernel bạn dự định biên dịch.

Đối với kernel 2.6.x series, bạn có thể tham khảo chi tiết thông tin về modules, cách biên dịch modules tổng quát và cách xử dụng modules (thuộc user space) trong ba hồ sơ ./Documentation/kbuild/modules.txt, ./Documentation/networking/net-modules.txt và ./Documentation/sound/oss/README.modules thuộc mã nguồn kernel bạn dự định biên dịch. Riêng với kernel 2.6.x series, bước "make modules" có thể thực hiện từ "make all" và bước "make modules_install" chỉ thực hiện riêng (ở chế độ super user) để cài các modules đã được biên dịch.


8.3 Tách rời mã nguồn và hồ sơ output trên kernel 2.6.x series
Nếu bạn đang dùng kernel 2.4.x series thì không cần tham khảo thông tin của mục 8.3. Những thông tin trong mục này chỉ giới thiệu thêm một số tiện ích hữu dụng cho quy trình chuẩn bị và biên dịch kernel 2.6.x.

8.3.1 "make help", một tiện ích mới trên kernel 2.6.x series
Ngoài những điểm khác biệt trong các make target đã được đề cập ở phần 8.1 và 8.2, trên kernel 2.6.x series, bạn có thể xử dụng một tiện ích khá hay mà kernel 2.4.x không có đó là phần "help" trước khi "make" mã nguồn của Linux kernel. Tất nhiên bạn phải chạy lệnh này sau khi vào trong thư mục chứa mã nguồn Linux kernel:
$ cd /usr/src/linux-2.6.6 (dùng kernel 2.6.6 trong trường hợp này)
$ make help sẽ cho thông tin trợ giúp như sau:
bash-2.05b$ make help
Cleaning targets:
clean - remove most generated files but keep the config
mrproper - remove all generated files + config + various backup files

Configuration targets:
oldconfig - Update current config utilising a line-oriented program
menuconfig - Update current config utilising a menu based program
xconfig - Update current config utilising a QT based front-end
gconfig - Update current config utilising a GTK based front-end
defconfig - New config with default answer to all options
allmodconfig - New config selecting modules when possible
allyesconfig - New config where all options are accepted with yes
allnoconfig - New minimal config

Other generic targets:
all - Build all targets marked with [*]
* vmlinux - Build the bare kernel
* modules - Build all modules
modules_install - Install all modules
dir/ - Build all files in dir and below
dir/file.[ois] - Build specified target only
rpm - Build a kernel as an RPM package
tags/TAGS - Generate tags file for editors
cscope - Generate cscope index

Documentation targets:
Linux kernel internal documentation in different formats:
sgmldocs (SGML), psdocs (Postscript), pdfdocs (PDF)
htmldocs (HTML), mandocs (man pages, use installmandocs to install)

Architecture specific targets (i386):
* bzImage - Compressed kernel image (arch/i386/boot/bzImage)
install - Install kernel using
(your) ~/bin/installkernel or
(distribution) /sbin/installkernel or
install to $(INSTALL_PATH) and run lilo
bzdisk - Create a boot floppy in /dev/fd0
fdimage - Create a boot floppy image

make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build
make O=dir [targets] Locate all output files in "dir", including .config
make C=1 [targets] Check all c source with checker tool

Execute "make" or "make all" to build all targets marked with [*]
For further info see the ./README file
bash-2.05b$


Thông tin trên cho thấy "Makefile" chính của kernel 2.6.x series bao gồm các mục tiêu (target) biên dịch khi chạy make help. Với thông tin này, bạn có thể chọn các target make theo ý muốn mà không phải kiểm tra trong "Makefile" như với kernel 2.4.x series (kernel 2.4.x series không có "make help" như kernel 2.6.x series và kernel 2.4.x series không có nhiều make targets như kernel 2.6.x series). Điểm đặt biệt cần quan tâm là ba chọn lựa cuối trong thông tin "make help" cung cấp:
make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build
make O=dir [targets] Locate all output files in "dir", including .config
make C=1 [targets] Check all c source with checker tool

Một trong những chọn lựa quan trọng ở đây là nó cho phép bạn lưu trữ trọn bộ các hồ sơ output trong quá trình biên dịch vào một thư mục riêng biệt thay vì chứa chung với mã nguồn của kernel.

8.3.2 Tách rời mã nguồn và output files
Kernel 2.6.x series cho phép bạn tách rời mã nguồn của kernel và các hồ sơ output được tạo trong quá trình compile, các hồ sơ dấu (hidden) như .config, .depend.... trong các bước đề cập ở phần 7 và 8 cũng sẽ được lưu trữ ở thư mục nào bạn muốn dùng cho output files. Với phương tiện này, mã nguồn và các hồ sơ output sẽ không xen kẽ chung. Điểm quan trọng cần nhớ là khi đã dùng chọn lựa này thì phải dùng cho các bước "make" khác trong suốt quá trình biên dịch. Ví dụ, bạn có thể khởi đầu bằng:
make O=/path/to/output xconfig

thì các bước kế tiếp sẽ là:
make O=/path/to/output all (target "all" bao gồm "dep, clean, bzImage, modules"smilie, và
make O=/path/to/output modules_install (chạy lệnh này bằng super user để cài modules của kernel).

<kết thúc phần 3>. Mời các bạn đọc tiếp /hvaonline/posts/list/88.html.

<hnd, vninformatics.com / diendantinhoc.net - 06/06/2004>

Tác giả : Conmale (hnd)
Nguồn : www.diendantinhoc.net
 
Go to Page:  First Page Page 13 14 15 16

Powered by JForum - Extended by HVAOnline
 hvaonline.net  |  hvaforum.net  |  hvazone.net  |  hvanews.net  |  vnhacker.org
1999 - 2013 © v2012|0504|218|