2014年12月30日 星期二

[Linux 文章收集] iptables 做路由器

Source From Here 
Preface 
因為測試需要, Client 需要透過 Route 到達 Server: 
 

Build-up VM OS 
這邊使用 VMWare Workstation 建立 VM OS, 而 OS 選擇 CentOS 6.4 64bits 版本. 各個部份設定參考如下. 

Route VM 
Route 共需要三張網卡, UI 設定如下: 
 

因為 eth0 是 NAT, 故只剩下 eth1 與 eth2 需要設定. 請新增下面檔案: 
- /etc/sysconfig/network-scripts/ifcfg-eth1 
  1. DEVICE=eth1  
  2. HWADDR=00:0C:29:21:FC:4D  
  3. BOOTPROTO=static  
  4. NM_CONTROLLED=yes  
  5. ONBOOT=yes  
  6. IPADDR=10.5.0.6  
  7. NETMASK=255.255.255.0  
- /etc/sysconfig/network-scripts/ifcfg-eth2 
  1. DEVICE=eth2  
  2. HWADDR=00:0C:29:21:FC:57  
  3. BOOTPROTO=static  
  4. NM_CONTROLLED=yes  
  5. ONBOOT=yes  
  6. IPADDR=172.16.0.2  
  7. NETMASK=255.255.0.0  
上面設定的 HWADDR 請使用 ifconfig 命令觀察每個 eth? 的實際值後替換成對應的值. 接著使用下面命令使設定生效: 
# echo "1" > /proc/sys/net/ipv4/ip_forward // 啟動Linux的 ip 轉發功能
# ifup eth1
# ifup eth2
# ipconfig

接下來為了方便測試, 增加 Client 與 Server 的 ip 到 /etc/hosts 檔案中: 
# vi /etc/hosts
  1. ...  
  2. 10.5.0.7        client  
  3. 172.16.0.3      server  

Client VM 
Client 的 eth0 連接到 Vmnet2, 接著設定如下: 
# ifconfig // 確認 eth0 的 HWaddr
# vim /etc/sysconfig/network-scripts/ifcfg-eth0 // 設定網卡資訊
  1. DEVICE=eth0  
  2. HWADDR=00:0C:29:8A:88:F6  
  3. BOOTPROTO=static  
  4. NM_CONTROLLED=yes  
  5. ONBOOT=yes  
  6. IPADDR=10.5.0.7  
  7. NETMASK=255.255.255.0  
# ifup eth0
# ifconfig // 確認設定生效
# route add default gw 10.5.0.6 // 設定 default gateway 指向 Route eth1 ip
route -n // 確認設定生效
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.5.0.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
0.0.0.0 10.5.0.6 0.0.0.0 UG 0 0 0 eth0

# vi /etc/hosts
  1. ...  
  2. 10.5.0.7        route  
  3. 172.16.0.3      server  
# ping server // Now server is unreachable!
...Destination Host Unreachable

Server VM 
Server 的 eth0 連接到 Vmnet3, 接著設定如下: 
# ifconfig // 確認 eth0 的 HWaddr
# vim /etc/sysconfig/network-scripts/ifcfg-eth0 // 設定網卡資訊
  1. DEVICE=eth0  
  2. HWADDR=  
  3. BOOTPROTO=static  
  4. NM_CONTROLLED=yes  
  5. ONBOOT=yes  
  6. IPADDR=172.16.0.3  
  7. NETMASK=255.255.0.0  
# ifup eth0
# ifconfig // 確認設定生效
# route add default gw 172.16.0.2 // 設定 default gateway 指向 Route eth2 ip
route -n // 確認設定生效
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
172.16.0.0 0.0.0.0 255.255.0.0 U 1 0 0 eth0
0.0.0.0 172.16.0.2 0.0.0.0 UG 0 0 0 eth0

# vi /etc/hosts
  1. ...  
  2. 172.16.0.2      route  
  3. 10.5.0.7        client  
# ping client // Now client is unreachable!
...Destination Host Unreachable

Setup iptables as Router 
接著請在 Route machine 上進行如下設定: 
# iptables -t nat -A POSTROUTING -s 10.5.0.0/24 -o eth1 -j MASQUERADE // 設定只要 IP 是 10.5.0.0/24 就往 eth1 送
POSTROUTING:在通過Linux路由器之後做的策略,也就是路由器的外網接口
-s 192.168.1.0/24:源數據所來自這個網段,也可以是單個ip,不寫表示所有內網 ip
-o eth0 -j MASQUERADE:表示在eth0這個外網接口上使用IP偽裝
# iptables -t nat -A POSTROUTING -s 172.16.0.0/16 -o eth2 -j MASQUERADE // 設定只要 IP 是 172.16.0.0/16 就往 eth2 送
# iptables -L -t nat // 確定設定生效
Chain PREROUTING (policy ACCEPT)
target prot opt source destination

Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 10.5.0.0/24 anywhere
MASQUERADE all -- 172.16.0.0/16 anywhere

...

接著進行如下測試, 首先開啟一個 terminal 並登入 Client 後執行 tcpdump -i eth0. 接著再開啟另一個 terminal 登入 Server: 
# ping client // 這次可以通了
PING client (10.5.0.7) 56(84) bytes of data.
64 bytes from client (10.5.0.7): icmp_seq=1 ttl=63 time=0.668 ms
64 bytes from client (10.5.0.7): icmp_seq=2 ttl=63 time=1.35 ms
64 bytes from client (10.5.0.7): icmp_seq=3 ttl=63 time=1.48 ms
...

此時回到剛剛 Client 開啟的 terminal 應該可以看到: 
...
14:34:15.579748 IP server > route: ICMP echo request, id 3877, seq 66, length 64
14:34:15.579799 IP route > server: ICMP echo reply, id 3877, seq 66, length 64
14:34:16.583181 IP server > route: ICMP echo request, id 3877, seq 67, length 64
14:34:16.583240 IP route > server: ICMP echo reply, id 3877, seq 67, length 64
14:34:17.589643 IP server > route: ICMP echo request, id 3877, seq 68, length 64
14:34:17.589691 IP route > server: ICMP echo reply, id 3877, seq 68, length 64
...

你會發現雖然是由 Server 在 ping Client, 但是 Client 看到的卻是 Route 的 IP, 這是因為 NAT (Network Address Translation) 造成的結果. 

Supplement 
AskUbuntu - Forwarding traffic between 2 interfaces 
Introduction to Linux Traffic Control 
Changing IP Addresses and Routes 
Red Hat Enterprise Linux 4 - FORWARD 與 NAT 規則

2014年12月29日 星期一

[ 文章收集 ] Functional thinking: Functional features in Groovy, Part 1

Source From Here 
Preface 
Over time, languages and runtimes have handled more and more mundane details for us. Functional languages exemplify this trend, but modern dynamic languages have also incorporated many functional features to make developers' lives easier. This installment investigates some of the functional features already lurking in Groovy, showing how recursion hides state and how to build lazy lists. 

Confession: I never want to work in a non-garbage-collected language again. I paid my dues in languages like C++ for too many years, and I don't want to surrender the conveniences of modern languages. That's the story of how software development progresses. We build layers of abstraction to handle (and hide) mundane details. As the capabilities of computers have grown, we've offloaded more tasks to languages and runtimes. As recently as a decade ago, developers shunned interpreted languages for being too slow for production applications, but they are common now. Many of the features of functional languages were prohibitively slow a decade ago but make perfect sense now because they optimize developer time and effort

Many of the features I cover in this article series show how functional languages and frameworks handle mundane details. However, you don't have to go to a functional language to start reaping benefits from functional constructs. In this installment and the next, I'll show how some functional programming has already been applied into Groovy. 

Groovy's functional-ish lists 
Groovy significantly augments the Java collection libraries, including adding functional constructs. The first favor Groovy does for you is provide a different perspective on lists, which seems trivial at first but offers some interesting benefits. 

Seeing lists differently 
If your background is primarily in C or C-like languages (including Java), you probably conceptualize lists as indexed collections. This perspective makes it easy to iterate over a collection, even when you don't explicitly use the index, as shown in the Groovy code in Listing 1: 
- Listing 1. List traversal using (hidden) indexes 
  1. def perfectNumbers = [6284968128]  
  2.   
  3. def iterateList(listOfNums) {  
  4.   listOfNums.each { n ->  
  5.     println "${n}"  
  6.   }  
  7. }  
  8.   
  9. iterateList(perfectNumbers)  
Groovy also includes an eachWithIndex() iterator, which provides the index as a parameter to the code block for cases in which explicit access is necessary. Even though I don't use an index in the iteraterList() method in Listing 1, I still think of it as an ordered collection of slots, as shown in Figure 1: 
Figure 1. Lists as indexed slots 
 

Many functional languages have a slightly different perspective on lists, and fortunately Groovy shares this perspective. Instead of thinking of a list as indexed slots, think of it as a combination of the first element in the list (the headplus the remainder of the list (the tail), as shown in Figure 2: 
Figure 2. A list as its head and tail 
 

Thinking about a list as head and tail allows me to iterate through it using recursion, as shown in Listing 2: 
- Listing 2. List traversal using recursion 
  1. def recurseList(listOfNums) {  
  2.     if (listOfNums.size == 0return;  
  3.     println "${listOfNums.head()}"  
  4.     recurseList(listOfNums.tail())  
  5. }  
  6.   
  7. recurseList(perfectNumbers)  
In the recurseList() method in Listing 2, I first check to see if the list that's passed as the parameter has no elements in it. If that's the case, then I'm done and can return. If not, I print out the first element in the list, available via Groovy's head() method, and then recursively call the recurseList() method on the remainder of the list. 

Recursion has technical limits built into the platform (see Resources), so this isn't a panacea. But it should be safe for lists that contain a small number of items. I'm more interested in investigating the impact on the structure of the code, in anticipation of the day when the limits ease or disappear. Given the shortcomings, the benefit of the recursive version may not be immediately obvious. To make it more so, consider the problem of filtering a list. In Listing 3, I show an example of a filtering method that accepts a list and a predicate (a boolean test) to determine if the item belongs in the list: 
- Listing 3. Imperative filtering with Groovy 
  1. def filter(list, p) {  
  2.     def new_list = []  
  3.     list.each { i ->  
  4.         if (p(i))  
  5.             new_list << i  
  6.     }  
  7.     new_list  
  8. }  
  9.   
  10. modBy2 = { n -> n % 2 == 0}  
  11. evenNums = filter(1..20, modBy2)  
  12. printf("Even number between 1~20: ${evenNums}\n")  
The code in Listing 3 is straightforward: I create a holder variable for the elements that I want to keep, iterate over the list, check each element with the inclusion predicate, and return the list of filtered items. When I call filter(), I supply a code block specifying the filtering criteria. 

Consider a recursive implementation of the filter method from Listing 3, shown in Listing 4: 
- Listing 4. Recursive filtering with Groovy 
  1. def recFilter(list, p) {  
  2.     if (list.size() == 0return list  
  3.     if (p(list.head()))  
  4.         []+ list.head() + filter(list.tail(), p)  
  5.     else  
  6.         filter(list.tail(), p)  
  7. }  
  8.   
  9. evenNums = recFilter(1..20, {n-> n % 2 == 0})  
  10. printf("Even number between 1~20: ${evenNums}\n")  
From Listing 4, I check the size of the passed list and return it if it has no elements. Otherwise, I check the head of the list against my filtering predicate; if it passes, I add it to the list (with an initial empty list to make sure that I always return the correct type); otherwise, I recursively filter the tail. 

The difference between Listing 3 and Listing 4 highlights an important question: Who's minding the state? In the imperative version, I am. I must create a new variable named new_list, I must add things to it, and I must return it when I'm done. In the recursive version, the language manages the return value, building it up on the stack as the recursive return for each method invocation. Notice that every exit route of the recFilter() method in Listing 4 is a return call, which builds up the intermediate value on the stack

Although not as dramatic a life improvement as garbage collection, this does illustrate an important trend in programming languages: offloading moving parts. If I'm never allowed to touch the intermediate results of the list, I cannot introduce bugs in the way that I interact with it. This perspective shift about lists allows you explore other aspects, such as a list's size and scope. 

Lazy lists in Groovy 
One of the common features of functional languages is the lazy list: a list whose contents are generated only as you need it. Lazy lists allow you to defer initialization of expensive resources until you absolutely need them. They also allow the creation of infinite sequences: lists that have no upper bound. If you aren't required to say up front how big the list could be, you can let it be as big as it needs to be. 

First, I'll show you an example of using a lazy list in Groovy in Listing 5, and then I'll show you the implementation: 
- Listing 5. Using lazy lists in Groovy 
  1. def prepend(val, closure) { new LazyList(val, closure) }  
  2.   
  3. def integers(n) { prepend(n, { integers(n + 1) }) }  
  4.   
  5. def naturalNumbers = integers(1)  
  6. printf("Top 10 number: %s\n", naturalNumbers.getHead(10).join(' '))  
  7. def evenNumbers = naturalNumbers.filter { it % 2 == 0 }  
  8. printf("Top 10 even number: %s\n", evenNumbers.getHead(10).join(' '))  
The first method in Listing 5, prepend(), creates a new LazyList, allowing you to prepend values. The next method, integers(), returns a list of integers using theprepend() method. The two parameters I send to the prepend() method are the initial value of the list and a code block that includes code to generate the next value. The integers() method acts like a factory that returns the lazy list of integers with a value at the front and a way to calculate additional values in the rear. 

To retrieve values from the list, I call the getHead() method, which returns the argument number of values from the top of the list. In Listing 5, naturalNumbers is a lazy sequence of all integers. To get some of them, I call the getHead() method, specifying how many integers I want. Call naturalNumbers.getHead(10) to receive a list of the first 10 natural numbers. Using the filter() method, I retrieve a lazy list of even numbers and call the getHead() method to fetch the first 10 even numbers. 

The implementation of LazyList appears in Listing 6: 
- Listing 6. LazyList implementation 
  1. class LazyList {  
  2.   private head, tail  
  3.   
  4.   LazyList(head, tail) {  
  5.     this.head = head;  
  6.     this.tail = tail  
  7.   }  
  8.   
  9.   def LazyList getTail() { tail ? tail() : null }  
  10.   
  11.   def List getHead(n) {  
  12.     def valuesFromHead = [];  
  13.     def current = this  
  14.     n.times {  
  15.       valuesFromHead << current.head  
  16.       current = current.tail  
  17.     }  
  18.     valuesFromHead  
  19.   }  
  20.   
  21.   def LazyList filter(Closure p) {  
  22.     if (p(head))  
  23.       p.owner.prepend(head, { getTail().filter(p) })  
  24.     else  
  25.       getTail().filter(p)  
  26.   }  
  27. }  
A lazy list holds a head and tail, specified in the constructor. The getTail() method ensures that tail isn't null and executes it. The getHead() method gathers the elements that I want to return, one at a time, pulling the existing element off the head of the list and asking the tail to generate a new value. The call to n.times {} performs this operation for the number of elements requested, and the method returns the harvested values. 

The filter() method in Listing 5 uses the same recursive approach as Listing 4 but implements it as part of the list rather than a stand-alone function. Lazy lists exist in Java (see Resources) but are much easier to implement in languages that have functional features. Lazy lists work great in situations in which generating resources are expensive, such as getting lists of perfect numbers

Lazy list of perfect numbers 
If you've been following this article series, you're well aware of my favorite guinea-pig code, finding perfect numbers (see "Thinking functionally, Part 1"). One of the shortcomings of all the implementations so far is the need to specify the number for classification. Instead, I want a version that returns a lazy list of perfect numbers. Toward that goal, I've written a highly functional, very compact perfect-number finder that supports lazy lists, shown in Listing 7: 
- Listing 7. Pared-down version of number classifier, including nextPerfectNumberFrom() method 
  1. class NumberClassifier {  
  2.   static def factorsOf(number) {  
  3.       (1..number).findAll { i -> number % i == 0 }  
  4.   }  
  5.   
  6.   static def isPerfect(number) {  
  7.       factorsOf(number).inject(0, {i, j -> i + j}) == 2 * number  
  8.   }  
  9.   
  10.   static def nextPerfectNumberFrom(n) {  
  11.     while (! isPerfect(++n)) ;  
  12.     n  
  13.   }  
  14. }  
The method nextPerfectNumber(), uses the isPerfect() method to find the next perfect number beyond the number passed as the parameter. This method call will take a long time to execute even for small values (especially given how unoptimized this code is); there just aren't that many perfect numbers. 

Using this new version of NumberClassifier, I can create a lazy list of perfect numbers, as shown in Listing 8: 
- Listing 8. Lazily initialized list of perfect numbers 
  1. def perfectNumbers(n) {   
  2.   prepend(n,  { perfectNumbers(nextPerfectNumberFrom(n)) })   
  3. };  
  4.   
  5. @Test  
  6. public void infinite_perfect_number_sequence() {  
  7.   def perfectNumbers = perfectNumbers(nextPerfectNumberFrom(1))  
  8.   assertEquals([628496], perfectNumbers.getHead(3))  
  9. }  
Using the prepend() method I defined in Listing 5, I construct a list of perfect numbers with the initial value as the head and a closure block that knows how to calculate the next perfect number as the tail. I initialize my list with the first perfect number after 1 (using a static import so that I can call myNumberClassifier.nextPerfectNumberFrom() method more easily), then I ask my list to return the first three perfect numbers. 

Calculating new perfect numbers is expensive, so I would rather do it as little as possible. By building it as a lazy list, I can defer calculations until the optimum time. It is more difficult to think about infinite sequences if your abstraction of "list" is "numbered slots." Thinking of a list as the "first element" and the "rest of the list" encourages you to think of the elements in the list rather than the structure, which in turn allows you to think about things like lazy lists

Conclusion 
One of the ways that developers make quantum leaps in productivity is by building effective abstractions to hide details. We would never get anywhere if we were still coding with ones and zeros. One of the appealing aspects of functional languages is the attempt to abstract more details away from developers.Modern dynamic languages on the JVM already give you many of these features. In this installment, I showed how just shifting your perspective a little bit on how lists are constructed allows the language to manage state during iteration. Also, when you think of lists as "head" and "tail," it allows you to build things like lazy lists and infinite sequences. 

Supplement 
The Productive Programmer (Neal Ford, O'Reilly Media, 2008): Neal Ford's most recent book discusses tools and practices that help you improve your coding efficiency. 
An Excursion in Java Recursion: Recursion in Java has well-known limits, including some pointed out in this blog. 
Find limit of recursion: Find the recursion depth on your platform with these tests from RosettaCode. 
Apache Commons LazyList: Apache Commons includes a lazy-list implementation. 
Browse the technology bookstore for books on these and other technical topics. 
developerWorks Java technology zone: Find hundreds of articles about every aspect of Java programming.

[Linux 常見問題] What's the best way to send a signal to all members of a process group?

Source From  Here   Question   I want to  kill a whole process tree.  What is the best way to do this using any common scripting languages? ...