NATの種類
Mappingの種類
マッピングはNAT内部から外部にパケットを送信時にアドレス変換する行為です。
- Endpoint-Independent Mapping
NAT内部のネットワークの同じIPアドレスとポートで外部のそれぞれのUDPサーバ(IPアドレスとポートが違う)にパケットを送信すると、各個UDPサーバも同じIPアドレスとポートのパケットを受信する。
例えば:
送信元アドレス | 宛先アドレス | NATマッピングアドレス |
---|---|---|
192.168.1.1:3000 | 1.1.1.1:3000 | 43.124.222.234:4500 |
192.168.1.1:3000 | 1.1.1.1:3001 | 43.124.222.234:4500 |
192.168.1.1:3000 | 1.1.1.3:3002 | 43.124.222.234:4500 |
192.168.1.1:3000 | 1.1.1.4:3004 | 43.124.222.234:4500 |
- Address-Dependent Mapping
UDPサーバのアドレスが同じ(ポートが違う)なら受信したパケットのIPアドレスとポートを変換しない、そうしないと、IPアドレスやポートを変換する。
例えば:
送信元アドレス | 宛先アドレス | NATマッピングアドレス |
---|---|---|
192.168.1.1:3000 | 1.1.1.1:3000 | 43.124.222.234:4500 |
192.168.1.1:3000 | 1.1.1.1:3001 | 43.124.222.234:4500 |
192.168.1.1:3000 | 1.1.1.2:3000 | 43.124.222.234:4501 |
192.168.1.1:3000 | 1.1.1.3:3003 | 43.124.222.234:4502 |
- Address and Port-Dependent Mapping
UDPサーバのアドレスとポートが同じなら受信したパケットのIPアドレスとポートを変換しない、そうしないと、IPアドレスやポートを変換する。
例えば:
送信元アドレス | 宛先アドレス | NATマッピングアドレス |
---|---|---|
192.168.1.1:3000 | 1.1.1.1:3000 | 43.124.222.234:4500 |
192.168.1.1:3000 | 1.1.1.1:3000 | 43.124.222.234:4500 |
192.168.1.1:3000 | 1.1.1.1:3001 | 43.124.222.234:4501 |
192.168.1.1:3000 | 1.1.1.2:3000 | 43.124.222.234:4502 |
192.168.1.1:3000 | 1.1.1.3:3003 | 43.124.222.234:4503 |
Filteringの種類
フィルタリングはNAT外部から内部に送信するパケットをフィルタリングする行為です。
- Endpoint-Independent Filtering
一旦内部アドレスを外部にマッピングすると、全ての外部サーバから内部に送信することが可能です。
例えば:
内部アドレス | マッピング |
---|---|
192.168.1.1:3000 | 43.124.222.234:4500 |
送信元アドレス | 宛先アドレス | 受信する? |
---|---|---|
1.1.1.1:3000 | 43.124.222.234:4500 | はい 🟢 |
1.1.1.1:3001 | 43.124.222.234:4500 | はい 🟢 |
1.1.1.2:3000 | 43.124.222.234:4500 | はい 🟢 |
1.1.1.3:3002 | 43.124.222.234:4500 | はい 🟢 |
- Address-Dependent Filtering
内部から外部に送信したサーバ、且つアドレスも同じなら、サーバから内部に送信することが可能です。
例えば:
内部アドレス | マッピング | 送信歴史 宛先アドレス |
---|---|---|
192.168.1.1:3000 | 43.124.222.234:4500 | 1.1.1.1:3000 |
送信元アドレス | 宛先アドレス | 受信する? |
---|---|---|
1.1.1.1:3000 | 43.124.222.234:4500 | はい 🟢 |
1.1.1.1:3001 | 43.124.222.234:4500 | はい 🟢 |
1.1.1.2:3000 | 43.124.222.234:4500 | ダメ ❌ |
1.1.1.3:3002 | 43.124.222.234:4500 | ダメ ❌ |
- Address and Port-Dependent Filtering
内部から外部に送信したサーバ、且つアドレスとポートも同じなら、サーバから内部に送信することが可能です。
例えば:
内部アドレス | マッピング | 送信歴史 宛先アドレス |
---|---|---|
192.168.1.1:3000 | 43.124.222.234:4500 | 1.1.1.1:3000 |
送信元アドレス | 宛先アドレス | 受信する? |
---|---|---|
1.1.1.1:3000 | 43.124.222.234:4500 | はい 🟢 |
1.1.1.1:3001 | 43.124.222.234:4500 | ダメ ❌ |
1.1.1.2:3000 | 43.124.222.234:4500 | ダメ ❌ |
1.1.1.3:3002 | 43.124.222.234:4500 | ダメ ❌ |
Fullcone NAT
Fullcone NATはEndpoint-Independent FilteringとEndpoint-Independent Mappingです。
goで実現する
最も重要なのはNATテーブルの実現です。
// NATテーブル
// キーはプロキシクライアントの送信元アドレス
// 値はマッピングしたUDPサーバ
var natTable = map[string]net.PacketConn{}
var getTargetAddress = func([]byte) (*net.UDPAddr, []byte) {
// TODO implement proxy protocol
return nil, nil
}
var packetResponse = func(net.Addr, []byte) []byte {
// TODO implement proxy protocol
return nil
}
// mockのUDPプロキシサーバ
pc, err := net.ListenPacket("udp", "")
if err != nil {
panic(err)
}
defer pc.Close()
for {
// IPプロトコルによってパケット最大は65535です。
buf := make([]byte, 65535)
n, addr, err := pc.ReadFrom(buf)
if err != nil {
panic(err)
}
// クライアントのアドレスでマッピングサーバを保存して
conn, ok := natTable[addr.String()]
if !ok {
// マッピングサーバを作ります
conn, err = net.ListenPacket("udp", "")
if err != nil {
panic(err)
}
go func() {
defer conn.Close()
for {
buf := make([]byte, 65535)
// リモートサーバ(target)の返信を受信する
n, src, err := conn.ReadFrom(buf)
if err != nil {
panic(err)
}
// レスポンスデータをクライアントに返信して
_, err = pc.WriteTo(packetResponse(src, buf[:n]), addr)
if err != nil {
panic(err)
}
}
}()
// 初めてマッピングサーバをNATテーブルに保存して
natTable[addr.String()] = conn
}
target, remain := getTargetAddress(buf[:n])
// リモートサーバにデータを送信して
_, err = conn.WriteTo(remain, target)
if err != nil {
panic(err)
}
}