Yesterday, my colleague asked me how to configure a policy route on Mac, but I don't know! Due to your actual needs, I have always wanted to play with the Mac network function, but my eyes are always stunned by its dazzling appearance! When my colleague asked me this question, I suddenly had a desire to study the problem. Fortunately, my home computer is a MAC system (I am not a fan, but my wife is ), I took my daughter to an early education class over the weekend and finally I could have a good time...
As a matter of fact, MacOS looks like a tank. Its kernel is a bsd unix with an academic and noble lineage. We know that the UNIX network is powerful, and the relationship between TCP/IP and UNIX is as follows, I can't help but think of Mac's greatness. I put UNIX on a pair of fashionable ol's knees, but what a great conquest!
My experiment topology is as follows:
IMac simulates a terminal, WiFi is disabled, MacBook analog router, WiFi is enabled, two computers are connected with a network cable.
First, I want to configure nat on the MacBook to convert the source address of the data packet sent from the iMac on the Intranet. In this case, I want dynamic Nat or similar to the Linux maquerade. The wifi interface on the MacBook connects to the router of my house. Therefore, we need to perform SNAT for the packets sent out of the WiFi port EN1, similar to the Linux-O EN1-J MasqueradeIn this way, I know that BSD can be configured in multiple ways. There is a tool similar to Linux iptables, that is, PF, by editing/etc/PF. it is better to implement the configuration through Conf. Because pfctl has a rule syntax detection mechanism that can help you check many errors, the above requirements can be completed through the following Configuration:
Nat on EN1 from 172.16.4.0/24 to any-> EN1
Among them, 172.16.4.0/24 is the address of the iMac segment, as the Intranet, and on EN1 is the so-called Internet address 192.168.1.108. In fact, EN1 and the CIDR block can be written as variables. For the sake of simplicity, you can write them as variables. I will use this to compare it with iptables and Cisco Systems later. Then run pfctl-e-f/etc/PF. conf! At this time, ping the 192.168.1.1 vro from iMac, but the vro cannot ping the Intranet. This is obviously a one-way conversion. To achieve two-way conversion, therefore, a one-to-one conversion is required. In BSD, this is implemented through binat. It is mainly used in the command and is separated from Bat by adding the Bi prefix, let's take a look at the binat Configuration:
Binat on EN1 from 172.16.4.10 to any-> 172.16.4.30
In this way, a one-to-one ing relationship is established. address translation can be implemented no matter whether the router initiates or the iMac initiates the ing, this is the function that I implemented in Linux with great effort in my previous article. Both BSD and Cisco can easily complete configuration, but Linux is very difficult, even if you use rawnat, you still have to configure two rules !!! Although match is also built in one-to-one Nat of PF, you can use any to overwrite it. The most important thing is that it is independent of binat, rather than a configuration option of Nat.
The NAT Function is already playing around. I want to try a minimal set first, and then expand it slowly. The same is true when I first met iptables. I have always wondered why iptables does not implement one-to-one address conversion? Note: netfilter is only a framework and can implement any function. Therefore, I did not blame netfilter but iptables. This is a basic requirement. Imagine a web server providing external services in the DMZ zone, and it also needs to actively access other external resources, which is very common in the cloud environment, if Nat is not mapped one by one, ip_conntrack alone consumes a lot of resources. It is not necessary to convert an address to maintain a stream. Any other operating system can easily implement the functions. Why does Linux not? Another question is why Mac OS does not open common functions, such as adding multiple IP addresses to a network card. I guess Windows is a moderate system. It provides powerful tools such as iptables and iproute2 without adding multiple addresses. Even if netsh is used, linux and Mac OS are more extreme, especially Mac OS. It is assumed that the people who use it are not people who love the network, an ol or Western-style sunglasses won't stick the chin to configure a policy route... however, in its command line, it provides almost a complete BSD command set. The designer once again assumes that if a person who buys a Mac is a technical enthusiast, such as me, then he always calls up the command line immediately. Once the command line is called up, everything is in front of him, is it necessary to add the function that is not used to add multiple IP addresses to the Gui? I can't help but respect Apple people! In this regard, Windows and Linux should learn ah, I do not say heavyweight Unix (such as Aix, HP-UX), because that things will not be exposed to ordinary people, on the contrary windows, there are still a lot of Linux contacts. Windows does not have to say that Linux is also a popular system, especially after the Android era. I have attached a supplement to this section: How can I add a secodary IP address to so many Mac OS instances?Ifconfig ENX $ IP/$ mask aliasThe keyword is alias!
The most important time of this article is now. Which of the following is better for PF configuration and iptables configuration? This is of course not a matter of opinion. You can not hesitate to say that iptables is defeated! People who have written iptables rule control scripts have a headache, that is, you have to write a rule for each of your ideas, and then the nightmare is coming, you should always pay attention to when to delete this rule, and make sure that the deletion is clean... complex business logic often makes this difficult to guarantee, so you can only simplify the business logic to accommodate iptables... why ??
The root cause is that iptables does not implement mechanism and policy separation at the level of each rule. if policies are not configurable, the Operation atom of the entire iptables rule is the rule itself, for example, you cannot parameterize a match or a target. For example:
Iptables-a forward-s 1.1.1.1-D 2.2.2.2-p tcp-J Drop
Once this rule is set, if one day your target is no longer 2.2.2.2, but changed to 3.3.3.3, you must delete this rule and then add a new rule, you cannot add, delete, modify, or delete a match. We know that a rule contains a judgment logic, and the specific action must be parameterized to make it flexible. For the above example rule, the logic is, TCP packets starting from somewhere to somewhere need to be discarded! That's all. It must be configurable to describe what the "somewhere" in the statement is.
BSD pf achieves this. It supports parameters such as variables and macros. For example, the initial NAT configuration, such as the IP address, can be defined like a bash script. The lack of the rule operation plane of iptables is indeed a serious injury, but it cannot be killed by a stick. We know that ipset is one of the efforts to make up for this deficiency, the definition of the matching IP Set is handed over to the ipset program. We expect to see a lot of sets, such as protoset, portset, stateset... in this regard, we can also see a similar idea in Cisco's NAT configuration. Cisco has stripped the ACL and Nat, And the ACL is only responsible for match.
But it doesn't mean that PF has no disadvantages, and the configuration is too complicated. For example, configuring a policy route: from which network port the access package comes in and from which network port. The implementation of PF is to introduce a series of hard configuration route-to/reply. According to this logic, a configuration parameter is required for each type of configuration. This method is inappropriate. On the contrary, linux does a good job. It uses the mark mechanism to implement policy routing. The flow-based NF-mark can mark a stream, and it is easy to configure policy routing through the fwmark of IP rule, policy Routing is not the responsibility of iptables. iptables only applies to mark. As for how to use this mark, it does not matter. Policy Routing is implemented independently in Linux, it has nothing to do with netfilter. PF is different. In fact, it also has a tag mechanism similar to mark. I think it is not good to introduce configuration parameters for routing. In addition to supporting the match parameterization, the vertical pf seems to be messy. Almost everything can be implemented using PF. Nat is just an action parallel to pass and block. In addition, all the proxies, for example, have corresponding configuration parameters. I think they can all be divided by tags.
Before PF is met, iptables is always regarded as a treasure. In fact, it is really! The attraction of PF lies in the maintainability of its configuration. If you have a Mac, then you really have a Unix, which can be used to make great strides. The powerful network functions of bsd unix are present.