-
Notifications
You must be signed in to change notification settings - Fork 20
NAT64/Teredo Embedding Strategies + Public/Private Blocks #105
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
zanbaldwin
wants to merge
6
commits into
6.x
Choose a base branch
from
z/nat64
base: 6.x
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
aabff9d
feature(strategy): ✨ add NAT64 (RFC6052) embedding strategy
zanbaldwin ce3b644
feature(strategy): ✨ add Composite embedding strategy
zanbaldwin 11b3b78
bugfix(ipv6): 🐛 classify IPv4-embedded IPv6 by embedded address
zanbaldwin 1627e36
feature(strategy): ✨ add Teredo (RFC4380) embedding strategy
zanbaldwin 456af9e
bugfix(ipv6): 🐛 classify NAT64 local-use block as not global
zanbaldwin 026a62a
docs: 📚 update CHANGELOG
zanbaldwin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Darsyn\IP\Strategy; | ||
|
|
||
| use Darsyn\IP\Exception\Strategy as StrategyException; | ||
|
|
||
| class Composite implements EmbeddingStrategyInterface | ||
| { | ||
| /** @var list<EmbeddingStrategyInterface> */ | ||
| private $strategies; | ||
|
|
||
| /** @var EmbeddingStrategyInterface */ | ||
| private $packer; | ||
|
|
||
| public function __construct( | ||
| EmbeddingStrategyInterface $packer, | ||
| EmbeddingStrategyInterface ...$additional | ||
| ) { | ||
| $this->packer = $packer; | ||
| $this->strategies = array_values(array_merge([$packer], $additional)); | ||
| } | ||
|
|
||
| /** | ||
| * Named helper constructor for matching all unambiguous, non-deprecated | ||
| * embedding strategies. | ||
| */ | ||
| public static function all(): self | ||
| { | ||
| // Explicitly NOT including the ambiguous, deprecated "Compatible" | ||
| // embedding strategy, and using Mapped as the canonical strategy for | ||
| // packing. | ||
| return new self(new Mapped(), new Derived(), new Nat64(), new Teredo()); | ||
| } | ||
|
|
||
| public function isEmbedded(string $binary): bool | ||
| { | ||
| foreach ($this->strategies as $strategy) { | ||
| if ($strategy->isEmbedded($binary)) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| public function extract(string $binary): string | ||
| { | ||
| foreach ($this->strategies as $strategy) { | ||
| if ($strategy->isEmbedded($binary)) { | ||
| return $strategy->extract($binary); | ||
| } | ||
| } | ||
| throw new StrategyException\ExtractionException($binary, $this); | ||
| } | ||
|
|
||
| public function pack(string $binary): string | ||
| { | ||
| return $this->packer->pack($binary); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Darsyn\IP\Strategy; | ||
|
|
||
| use Darsyn\IP\Exception\Strategy as StrategyException; | ||
| use Darsyn\IP\Util\Binary; | ||
| use Darsyn\IP\Util\MbString; | ||
|
|
||
| /** | ||
| * Embeds an IPv4 address within the "Well-Known Prefix" `64:ff9b::/96`, as | ||
| * defined by RFC 6052 ("IPv6 Addressing of IPv4/IPv6 Translators"), § 2.1 | ||
| * | ||
| * Globally reachable, but not reserved by protocol. RFC 6052 § 3.1 states that | ||
| * non-global IPv4 addresses must NOT be embedded as NAT64. | ||
| */ | ||
| class Nat64 implements EmbeddingStrategyInterface | ||
| { | ||
| public function isEmbedded(string $binary): bool | ||
| { | ||
| return 16 === MbString::getLength($binary) | ||
| && MbString::subString($binary, 0, 12) === Binary::fromHex('0064ff9b0000000000000000'); | ||
| } | ||
|
|
||
| public function extract(string $binary): string | ||
| { | ||
| if (16 === MbString::getLength($binary)) { | ||
| return MbString::subString($binary, 12, 4); | ||
| } | ||
| throw new StrategyException\ExtractionException($binary, $this); | ||
| } | ||
|
|
||
| public function pack(string $binary): string | ||
| { | ||
| // Note: non-global IPv4 addresses should not be packed into NAT64, but | ||
| // is not enforced here. It is down to the user of this library to know | ||
| // when to use which embedding strategy. | ||
| if (4 === MbString::getLength($binary)) { | ||
| return Binary::fromHex('0064ff9b0000000000000000') . $binary; | ||
| } | ||
| throw new StrategyException\PackingException($binary, $this); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| <?php | ||
|
|
||
| declare(strict_types=1); | ||
|
|
||
| namespace Darsyn\IP\Strategy; | ||
|
|
||
| use Darsyn\IP\Exception\Strategy as StrategyException; | ||
| use Darsyn\IP\Util\Binary; | ||
| use Darsyn\IP\Util\MbString; | ||
|
|
||
| /** | ||
| * Extracts an IPv4 address from the Teredo prefix `2001::/32`, as defined by | ||
| * RFC 4380 ("Teredo: Tunneling IPv6 over UDP through NATs"), § 4. | ||
| * | ||
| * A Teredo address encodes the tunnel server's IPv4 address (bits 32–63), flags | ||
| * (bits 64–79), the client's obfuscated UDP port (bits 80–95, XOR'd with | ||
| * `0xFFFF`), and the client's obfuscated public IPv4 address (bits 96–127, | ||
| * XOR'd with `0xFFFFFFFF`). This strategy extracts the client address (the | ||
| * address the Teredo address stands for). | ||
| */ | ||
| class Teredo implements EmbeddingStrategyInterface | ||
| { | ||
| public function isEmbedded(string $binary): bool | ||
| { | ||
| return 16 === MbString::getLength($binary) | ||
| && MbString::subString($binary, 0, 4) === Binary::fromHex('20010000'); | ||
| } | ||
|
|
||
| public function extract(string $binary): string | ||
| { | ||
| if (16 === MbString::getLength($binary)) { | ||
| // The client's public IPv4 sits in the last 4 bytes XOR'd with 0xFFFFFFFF. | ||
| return MbString::subString($binary, 12, 4) ^ "\xff\xff\xff\xff"; | ||
| } | ||
| throw new StrategyException\ExtractionException($binary, $this); | ||
| } | ||
|
|
||
| public function pack(string $binary): string | ||
| { | ||
| // Per RFC 4380 the embedded client address is the public, post-NAT | ||
| // mapped address, so a non-global value is malformed by specification. | ||
| // The same reasoning as RFC 6052 § 3.1 for NAT64. | ||
|
|
||
| // Extraction-only: a Teredo address cannot be constructed from an IPv4 | ||
| // address alone (server, flags, and port are not derivable), so `pack()` | ||
| // always throws. | ||
| throw new StrategyException\PackingException($binary, $this); | ||
| // It is down to the user of this library to know that you should not | ||
| // use this embedding strategy to pack. At all. | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since NAT64 supports prefixes other than
64:ff9b::/96, would it be possible to add the option to specify a different checksum-neutral prefix for NAT64?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have been reading RFC specifications for nearly 2 days, so my brain needs a rest right now, but I have seen this and I will reply some time in the next couple of days 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about adding named constructors to NAT64:
Nat64::wellKnown()(default, part ofComposite::all()), andNat64::networkSpecific(IPv6 $prefix, int $cidr)where$cidrmust be one of 32, 40, 48, 56, 64, or 96.Will probably cancel this pull request, and do just the NAT64 stuff on its own in a new pull request on Monday. Will tag you in it for review (unless you leave any comments here before then).
Thanks for the suggestion!