{"id":272,"date":"2021-02-18T14:52:52","date_gmt":"2021-02-18T06:52:52","guid":{"rendered":"https:\/\/blog.swineson.me\/en\/?p=272"},"modified":"2021-02-22T23:00:33","modified_gmt":"2021-02-22T15:00:33","slug":"juniper-srx-as-a-dhcpv6-pd-client-on-a-pppoe-interface","status":"publish","type":"post","link":"https:\/\/blog.swineson.me\/en\/juniper-srx-as-a-dhcpv6-pd-client-on-a-pppoe-interface\/","title":{"rendered":"Juniper SRX as a DHCPv6 PD Client on a PPPoE Interface"},"content":{"rendered":"<p>Recently my ISP fixed the compatibility issues between their Huawei BRAS and my Junos router. After some digging, I managed to get some IPv6 address allocation for all my client devices. Here&#8217;s how I achieved it.<\/p>\n<p>Disclaimer: This article assumes you have basic understanding on IPv6 as we are not going to dig into the very details of the IPv6 standards.<\/p>\n<p><!--more--><\/p>\n<h1>Planning<\/h1>\n<p>My router is a Juniper SRX300 (JUNOS Software Release [19.4R3-S1.3]). I have a PPPoE interface configured in a routing instance as the uplink, and multiple irb interfaces in another routing instance as the local networks. SLAAC requires at least a \/64 IPv6 section per layer 2, so I have to request a DHCPv6 PD for more than \/64 (my ISP currently allows up to \/56) and chop the address blocks into smaller chunks, one per VLAN.<\/p>\n<h1>DHCPv6 Client on PPPoE<\/h1>\n<p>Very basic config and doesn&#8217;t have much variations. Here you can also propagate your ISP&#8217;s DNS config to your clients, but I chose to opt out.<\/p>\n<pre class=\"lang:default decode:true\">set interfaces pp0 unit 0 ppp-options initiate-ncp ipv6\r\nset interfaces pp0 unit 0 family inet6 rpf-check\r\nset interfaces pp0 unit 0 family inet6 dhcpv6-client client-type stateful\r\nset interfaces pp0 unit 0 family inet6 dhcpv6-client client-ia-type ia-pd\r\nset interfaces pp0 unit 0 family inet6 dhcpv6-client rapid-commit\r\nset interfaces pp0 unit 0 family inet6 dhcpv6-client prefix-delegating preferred-prefix-length 56\r\nset interfaces pp0 unit 0 family inet6 dhcpv6-client prefix-delegating sub-prefix-length 64\r\nset interfaces pp0 unit 0 family inet6 dhcpv6-client client-identifier duid-type duid-ll\r\nset interfaces pp0 unit 0 family inet6 dhcpv6-client retransmission-attempt 5\r\nset interfaces pp0 unit 0 family inet6 dhcpv6-client update-server<\/pre>\n<h1>Prepare for Router Advertisement on LAN Interfaces<\/h1>\n<p>There are 2 methods to configure RA on a interface. One is to configure a static IPv6 range under <span class=\"lang:default highlight:0 decode:true crayon-inline \">protocols router-advertisement<\/span> (only available under the default routing instance, and works for all the routing instances in current logical system), another is to use <span class=\"lang:default highlight:0 decode:true crayon-inline \">dhcpv6-client update-router-advertisement<\/span> under a interface for dynamically-acquired address blocks. These two methods are exclusive. My ISP only offers dynamic addresses, so I&#8217;ll go with the latter one.<\/p>\n<p>Enable the &#8220;other&#8221; flag here since we&#8217;ll use stateless DHCPv6 to send DNS config to the clients.<\/p>\n<pre class=\"lang:default decode:true \">set interfaces irb unit 100 family inet6 rpf-check\r\nset interfaces pp0 unit 0 family inet6 dhcpv6-client update-router-advertisement interface irb.100 other-stateful-configuration<\/pre>\n<h1>Stateless DHCPv6<\/h1>\n<p>We can use stateless DHCPv6 server to set DNS, search domain, etc. for SLAAC clients. You may use RDNSS too, but it falls out of the scope of this article. Stateless DHCPv6 only works if the &#8220;other&#8221; flag is set in the RA, so make sure you set it.<\/p>\n<p>Notes:<\/p>\n<ul>\n<li>If your LAN interface is in a routing instance, set everything below inside the routing instance<\/li>\n<li><span class=\"lang:default highlight:0 decode:true crayon-inline \">access address-assignment pool &lt;*&gt; family<\/span> is exclusive; config one family and you&#8217;ll lose everything for the other family<\/li>\n<li><span class=\"lang:default highlight:0 decode:true crayon-inline \">access address-assignment pool &lt;*&gt; family inet6 prefix<\/span> is required even if the pool is only used for stateless DHCPv6; just config something so that the client address can match the pool<\/li>\n<li>You can config one pool for all DHCPv6 groups under <span class=\"lang:default highlight:0 decode:true crayon-inline \">system services dhcp-local-server dhcpv6 overrides process-inform pool<\/span> if their config is the same<\/li>\n<\/ul>\n<pre class=\"lang:default decode:true\">set system services dhcp-local-server dhcpv6 overrides interface-client-limit 255\r\nset system services dhcp-local-server dhcpv6 overrides rapid-commit\r\nset system services dhcp-local-server dhcpv6 overrides process-inform\r\nset system services dhcp-local-server dhcpv6 group LAN overrides process-inform pool LAN_V6\r\nset system services dhcp-local-server dhcpv6 group LAN interface irb.100\r\n\r\nset access address-assignment pool LAN_V6 family inet6 prefix 2000::\/3\r\nset access address-assignment pool LAN_V6 family inet6 dhcp-attributes dns-server 2001:4860:4860::8888\r\nset access address-assignment pool LAN_V6 family inet6 dhcp-attributes dns-server 2001:4860:4860::8844\r\nset access address-assignment pool LAN_V6 family inet6 dhcp-attributes valid-lifetime 3600\r\nset access address-assignment pool LAN_V6 family inet6 dhcp-attributes preferred-lifetime 1800<\/pre>\n<h1>DHCPv6 Client Stuck<\/h1>\n<p>If your PPPoE session is kicked by BRAS, the DHCPv6 client might get stuck. Use the following event script to solve the problem. (Don&#8217;t forget to adjust the interface name and routing instance name!)<\/p>\n<pre class=\"lang:default decode:true\">set event-options policy PPPOE_DHCPV6_REQ events SNMP_TRAP_LINK_UP\r\nset event-options policy PPPOE_DHCPV6_REQ attributes-match SNMP_TRAP_LINK_UP.interface-name matches pp0.0\r\nset event-options policy PPPOE_DHCPV6_REQ then execute-commands commands \"request dhcpv6 client renew routing-instance ISP interface pp0.0\"<\/pre>\n<hr \/>\n<h1>References<\/h1>\n<ul>\n<li><a href=\"https:\/\/blogs.infoblox.com\/ipv6-coe\/slaac-to-basics-part-2-of-2-configuring-slaac\/\" target=\"_blank\" rel=\"noopener\">SLAAC-to-Basics (Part 2 of 2: Configuring SLAAC)<\/a><\/li>\n<li><a href=\"https:\/\/blog.apnic.net\/2019\/06\/07\/how-to-slaac-dhcpv6-on-juniper-vsrx\/\" target=\"_blank\" rel=\"noopener\">How to: SLAAC\/DHCPv6 on Juniper vSRX<\/a><\/li>\n<li><a href=\"https:\/\/kb.juniper.net\/InfoCenter\/index?page=content&amp;id=KB30509\" target=\"_blank\" rel=\"noopener\">Configuring the SRX as a DHCPv6 client with auto-prefix delegation<\/a><\/li>\n<li><a href=\"https:\/\/www.juniper.net\/documentation\/en_US\/junos\/topics\/topic-map\/dhcpv6-server-security-devices.html\" target=\"_blank\" rel=\"noopener\">DHCPv6 Server<\/a><\/li>\n<li><a href=\"https:\/\/kb.juniper.net\/InfoCenter\/index?page=content&amp;id=KB30824&amp;cat=SRX_550&amp;actp=LIST\" target=\"_blank\" rel=\"noopener\">[SRX] Example &#8211; Configuring DHCPv6 PD over PPPoE<\/a><\/li>\n<li><a href=\"https:\/\/www.noroutetohost.net\/ipv6-over-fttc-on-the-juniper-srx110\/\" target=\"_blank\" rel=\"noopener\">IPv6 over FTTC on the Juniper SRX110<\/a><\/li>\n<li><a href=\"https:\/\/lkhill.com\/dhcpv6-client-srx\/\" target=\"_blank\" rel=\"noopener\"> DHCPv6 Client on Juniper SRX-110<\/a><\/li>\n<\/ul>\n<div class=\"ms-editor-squiggler\" style=\"color: initial; font: initial; font-feature-settings: initial; font-kerning: initial; font-optical-sizing: initial; font-variation-settings: initial; text-orientation: initial; text-rendering: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; animation: initial; appearance: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-inline: initial; inset: initial; box-shadow: initial; box-sizing: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-color: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; color-scheme: initial; columns: initial; column-fill: initial; gap: initial; column-rule: initial; column-span: initial; contain: initial; contain-intrinsic-size: initial; content: initial; content-visibility: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; display: block; dominant-baseline: initial; empty-cells: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-flow: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: 0px; hyphens: initial; image-orientation: initial; image-rendering: initial; inline-size: initial; inset-block: initial; inset-inline: initial; isolation: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; max-block-size: initial; max-height: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; offset: initial; opacity: initial; order: initial; origin-trial-test-property: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-wrap: initial; overflow: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; pointer-events: initial; position: initial; quotes: initial; r: initial; resize: initial; ruby-position: initial; rx: initial; ry: initial; scroll-behavior: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-indent: initial; text-overflow: initial; text-shadow: initial; text-size-adjust: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; user-select: initial; vector-effect: initial; vertical-align: initial; visibility: initial; -webkit-app-region: initial; border-spacing: initial; -webkit-border-image: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-highlight: initial; -webkit-hyphenate-character: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-mask: initial; -webkit-mask-composite: initial; -webkit-perspective-origin-x: initial; -webkit-perspective-origin-y: initial; -webkit-print-color-adjust: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-emphasis: initial; -webkit-text-emphasis-position: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-transform-origin-x: initial; -webkit-transform-origin-y: initial; -webkit-transform-origin-z: initial; -webkit-user-drag: initial; -webkit-user-modify: initial; white-space: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; z-index: initial;\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Recently my ISP fixed the compatibility issues between their Huawei BRAS and my Junos router. After some digging, I managed to get some IPv6 address allocation for all my client devices. Here&#8217;s how I achieved it. Disclaimer: This article assumes you have basic understanding on IPv6 as we are not going to dig into the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[13,14],"tags":[],"class_list":["post-272","post","type-post","status-publish","format-standard","hentry","category-juniper","category-junos-os"],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/posts\/272"}],"collection":[{"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/comments?post=272"}],"version-history":[{"count":3,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/posts\/272\/revisions"}],"predecessor-version":[{"id":275,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/posts\/272\/revisions\/275"}],"wp:attachment":[{"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/media?parent=272"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/categories?post=272"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.swineson.me\/en\/wp-json\/wp\/v2\/tags?post=272"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}