> For the complete documentation index, see [llms.txt](https://book.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://book.bsdcn.org/man/man4/ng_nat.4.md).

# ng\_nat.4

`ng_nat` — NAT netgraph 节点类型

## 名称

`ng_nat`

## 概要

`#include <netgraph/ng_nat.h>`

## 描述

`ng_nat` 节点对通过它的 IPv4 数据包执行网络地址转换（NAT）。`nat` 节点使用 libalias(3) 引擎进行数据包别名处理。

## 钩子

本节点类型有两个钩子：

**`out`** 在此钩子上接收的数据包被视为传出数据包，将被伪装为配置的地址。

**`in`** 在此钩子上接收的数据包被视为传入数据包，将被解除别名。

## 控制消息

本节点类型支持通用控制消息，以及以下消息：

```sh
struct ng_nat_mode {
	uint32_t	flags;
	uint32_t	mask;
};
/* 支持的标志： */
#define NG_NAT_LOG			0x01
#define NG_NAT_DENY_INCOMING		0x02
#define NG_NAT_SAME_PORTS		0x04
#define NG_NAT_UNREGISTERED_ONLY	0x10
#define NG_NAT_RESET_ON_ADDR_CHANGE	0x20
#define NG_NAT_PROXY_ONLY		0x40
#define NG_NAT_REVERSE			0x80
#define NG_NAT_UNREGISTERED_CGN		0x100
#define NG_NAT_UDP_EIM			0x200
```

```sh
#define NG_NAT_DESC_LENGTH	64
struct ng_nat_redirect_port {
	struct in_addr	local_addr;
	struct in_addr	alias_addr;
	struct in_addr	remote_addr;
	uint16_t	local_port;
	uint16_t	alias_port;
	uint16_t	remote_port;
	uint8_t		proto;
	char		description[NG_NAT_DESC_LENGTH];
};
```

```sh
struct ng_nat_redirect_addr {
	struct in_addr	local_addr;
	struct in_addr	alias_addr;
	char		description[NG_NAT_DESC_LENGTH];
};
```

```sh
struct ng_nat_redirect_proto {
	struct in_addr	local_addr;
	struct in_addr	alias_addr;
	struct in_addr	remote_addr;
	uint8_t		proto;
	char		description[NG_NAT_DESC_LENGTH];
};
```

```sh
struct ng_nat_add_server {
	uint32_t	id;
	struct in_addr	addr;
	uint16_t	port;
};
```

```sh
struct ng_nat_listrdrs_entry {
	uint32_t	id;		/* 除零外的任何值 */
	struct in_addr	local_addr;
	struct in_addr	alias_addr;
	struct in_addr	remote_addr;
	uint16_t	local_port;
	uint16_t	alias_port;
	uint16_t	remote_port;
	uint16_t	proto;		/* 有效 proto 或 NG_NAT_REDIRPROTO_ADDR */
	uint16_t	lsnat;		/* LSNAT 服务器计数 */
	char		description[NG_NAT_DESC_LENGTH];
};
struct ng_nat_list_redirects {
	uint32_t		total_count;
	struct ng_nat_listrdrs_entry redirects[];
};
#define NG_NAT_REDIRPROTO_ADDR	(IPPROTO_MAX + 3)
```

```sh
struct ng_nat_libalias_info {
	uint32_t	icmpLinkCount;
	uint32_t	udpLinkCount;
	uint32_t	tcpLinkCount;
	uint32_t	sctpLinkCount;
	uint32_t	pptpLinkCount;
	uint32_t	protoLinkCount;
	uint32_t	fragmentIdLinkCount;
	uint32_t	fragmentPtrLinkCount;
	uint32_t	sockCount;
};
```

`#include <net/bpf.h>`

**`NGM_NAT_SET_IPADDR`** (`setaliasaddr`) 为节点配置别名地址。在两个钩子都已连接且别名地址已配置后，节点即可进行别名操作。

**`NGM_NAT_SET_MODE`** (`setmode`) 使用提供的 `struct ng_nat_mode` 设置节点的操作模式。相应的 libalias 标志可通过将 `NG_NAT` 前缀替换为 `PKT_ALIAS` 找到。

**`NGM_NAT_SET_TARGET`** (`settarget`) 为节点配置目标地址。当与任何先前存在的别名链无关的传入数据包到达主机时，它将被发送到指定地址。

**`NGM_NAT_REDIRECT_PORT`** (`redirectport`) 将到达给定端口的传入连接重定向到另一主机和端口。必须提供以下 `struct ng_nat_redirect_port` 作为参数。重定向会分配一个唯一 ID，作为对此消息的响应返回，重定向信息会添加到静态重定向列表中，稍后可通过 `NGM_NAT_LIST_REDIRECTS` 消息检索。

**`NGM_NAT_REDIRECT_ADDR`** (`redirectaddr`) 将公共 IP 地址的流量重定向到本地网络上的机器。此功能称为*静态 NAT*。必须提供以下 `struct ng_nat_redirect_addr` 作为参数。此重定向的唯一 ID 作为对此消息的响应返回。

**`NGM_NAT_REDIRECT_PROTO`** (`redirectproto`) 将协议 `proto`（参见 [protocols(5)](/man/man5/protocols.5.md)）的传入 IP 数据包重定向到本地网络上的机器。必须提供以下 `struct ng_nat_redirect_proto` 作为参数。此重定向的唯一 ID 作为对此消息的响应返回。

**`NGM_NAT_REDIRECT_DYNAMIC`** (`redirectdynamic`) 将指定 ID 的重定向标记为动态，即它将仅服务于下一个连接，然后会自动从内部链路表中删除。只有完全指定的链路才能设为动态。具有此 ID 的重定向也会立即从用户可见的静态重定向列表中删除（可通过 `NGM_NAT_LIST_REDIRECTS` 消息访问）。

**`NGM_NAT_REDIRECT_DELETE`** (`redirectdelete`) 删除指定 ID 的重定向（当前活动连接不受影响）。

**`NGM_NAT_ADD_SERVER`** (`addserver`) 向池中添加另一台服务器。用于透明地卸载单个服务器上的网络负载并跨服务器池分发负载，也称为 *LSNAT*（RFC 2391）。必须提供以下 `struct ng_nat_add_server` 作为参数。首先，通过 `NGM_NAT_REDIRECT_PORT` 或 `NGM_NAT_REDIRECT_ADDR` 设置重定向。然后，使用该重定向的 ID 在多个 `NGM_NAT_ADD_SERVER` 消息中添加所需数量的服务器。对于由 `NGM_NAT_REDIRECT_ADDR` 创建的重定向，`port` 被忽略，可以是任何值。使用 `NGM_NAT_ADD_SERVER` 后，原始重定向参数 `local_addr` 和 `local_port` 也会被忽略（它们实际上被服务器池替换）。

**`NGM_NAT_LIST_REDIRECTS`** (`listredirects`) 以 `struct ng_nat_list_redirects` 形式返回已配置的静态重定向列表。返回的 `redirects` 数组条目以统一格式呈现所有重定向类型。仅当协议为 TCP 或 UDP 时端口才有意义，而*静态 NAT* 重定向（由 `NGM_NAT_REDIRECT_ADDR` 创建）通过 `proto` 设置为 `NG_NAT_REDIRPROTO_ADDR` 指示。如果 `lsnat` 服务器计数器大于零，则 `local_addr` 和 `local_port` 也无意义。

**`NGM_NAT_PROXY_RULE`** (`proxyrule`) 指定透明代理规则（必须以字符串作为参数提供）。详见 libalias(3)。

**`NGM_NAT_LIBALIAS_INFO`** (`libaliasinfo`) 以 `struct ng_nat_libalias_info` 形式返回 libalias(3) 实例的内部统计信息。如果 `nat` 无法从其 libalias(3) 实例检索某个计数器，相应字段返回 `UINT32_MAX`。

**`NGM_NAT_SET_DLT`** (`setdlt`) 设置 `in` 和 `out` 钩子上的数据链路类型。目前支持的类型有 `DLT_RAW`（原始 IP 数据报，无偏移应用，默认）和 `DLT_EN10MB`（以太网）。DLT\_ 定义可在如果你想在 [ipfw(8)](/man/man8/ipfw.8.md) 级别工作，必须通过指定 `DLT_RAW` 使用无额外偏移。但如果将 `nat` 直接附加到网络接口并指定了 `EN10MB`，则会应用额外偏移以考虑链路层头部。在此模式下，`nat` 还会检查以太网头部中的相应类型字段，并传递任何非 IP 数据包的数据报。

**`NGM_NAT_GET_DLT`** (`getdlt`) 此控制消息返回 `in` 和 `out` 钩子的当前数据链路类型。

在所有重定向消息中，`local_addr` 和 `local_port` 分别表示内部网络中目标机器的地址和端口。如果 `alias_addr` 为零，则使用默认别名地址（由 `NGM_NAT_SET_IPADDR` 设置）。通过使用非零 `remote_addr` 和/或 `remote_port`，还可以限制连接仅从特定外部机器接受。每个重定向都分配一个 ID，稍后可用于单独操作重定向（例如移除）。此 ID 保证在节点关闭之前唯一（删除后不会重用），并在每次创建新重定向后返回给用户，或可在所有重定向的存储列表中找到。`description` 字段在传入和传出节点时保持不变，与 ID 一起提供了一种让多个实体以自动化方式并发操作重定向的方法。

## 关闭

本节点在收到 `NGM_SHUTDOWN` 控制消息时关闭，或在两个钩子都已断开时关闭。

## 实例

在以下示例中，数据包使用 [ng\_ipfw(4)](/man/man4/ng_ipfw.4.md) 节点注入 `nat` 节点。

```sh
# 创建 NAT 节点
ngctl mkpeer ipfw: nat 60 out
ngctl name ipfw:60 nat
ngctl connect ipfw: nat: 61 in
ngctl msg nat: setaliasaddr x.y.35.8
# 将流量分流到 NAT 节点
ipfw add 300 netgraph 61 all from any to any in via fxp0
ipfw add 400 netgraph 60 all from any to any out via fxp0
# 让数据包在（解除）别名后继续
sysctl net.inet.ip.fw.one_pass=0
```

`nat` 节点可以插入图中 [ng\_iface(4)](/man/man4/ng_iface.4.md) 节点之后。在以下示例中，我们对使用 HDLC 封装的串行线路执行伪装。

```sh
/usr/sbin/ngctl -f- <<-SEQ
	mkpeer cp0: cisco rawdata downstream
	name cp0:rawdata hdlc
	mkpeer hdlc: nat inet in
	name hdlc:inet nat
	mkpeer nat: iface out inet
	msg nat: setaliasaddr x.y.8.35
SEQ
ifconfig ng0 x.y.8.35 x.y.8.1
```

`nat` 节点也可以通过图中的 [ng\_ether(4)](/man/man4/ng_ether.4.md) 节点直接附加到物理接口。在以下示例中，我们对连接到公共网络的以太网接口执行伪装。

```sh
ifconfig igb0 inet x.y.8.35 netmask 0xfffff000
route add default x.y.0.1
/usr/sbin/ngctl -f- <<-SEQ
        mkpeer igb0: nat lower in
        name igb0:lower igb0_NAT
        connect igb0: igb0_NAT: upper out
        msg igb0_NAT: setdlt 1
        msg igb0_NAT: setaliasaddr x.y.8.35
SEQ
```

## 参见

libalias(3), [ng\_ipfw(4)](/man/man4/ng_ipfw.4.md), [natd(8)](/man/man8/natd.8.md), ng\_ether(8), ngctl(8)

## 历史

`nat` 节点类型实现于 FreeBSD 6.0。

## 作者

Gleb Smirnoff <glebius@FreeBSD.org>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/man/man4/ng_nat.4.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
