IPv6 on FreeBSD

Hello,

I'm trying to get IPv6 going on my Linode running FreeBSD 12.1. I'm having two issues, one a firewall, I'm using SLAAC rc.conf below, and when the firewall is on system start does not bring up IPv6. I have to manually reload firewall rules. I'm wondering the ports/protocols SLAAC uses to pass them through. Currently I'm using ipfilter as firewall.

So I temporarily disabled ipfilter, restarted, and the IPv6 SLAAC address comes up on vtnet0. I'll eventually need to know why the firewall is acting like this.

The second problem I have is that I can do a host lookup on IPv6 addresses/hostnames for example ipv6.google.com returns that it's an alias and it's IPv6 address. If I do a ping6 -c 1 ipv6.google.com I get a UDP connect no route to host message. Now IPv6 I'm new at, I've got it working on a nanode, with just the SLAAC address, but the Linode has a pool assigned. I've tried statically assigning an IPv6 address and I could see the message with a static assignment if my IPv6 gateway was wrong, with SLAAC I can't see that happening.
Since I've got a IPv6 pool on this linode should I be using addresses from it and assigning them statically and not using rtsold?
I'd appreciate any suggestions.

Thanks.
Dave.

ping6 -c 1 ipv6.google.com

ping6: UDP connect: No route to host

netstat -rn -6

Routing tables

Internet6:
Destination Gateway Flags Netif Expire
::/96 ::1 UGRS lo0
::1 link#2 UH lo0
::ffff:0.0.0.0/96 ::1 UGRS lo0
2600:3c03::/64 link#1 U vtnet0
2600:3c03::f03c:91ff:fedf:6fc link#1 UHS lo0
fe80::/10 ::1 UGRS lo0
fe80::%vtnet0/64 link#1 U vtnet0
fe80::f03c:91ff:fedf:6fc%vtnet0 link#1 UHS lo0
fe80::%lo0/64 link#2 U lo0
fe80::1%lo0 link#2 UHS lo0
ff02::/16 ::1 UGRS lo0

10 Replies

Hey Dave -

Even though I don't know a whole lot about FreeBSD I wanted to get the ball rolling on your post.

I'm using SLAAC rc.conf below, and when the firewall is on system start does not bring up IPv6. I have to manually reload firewall rules. I'm wondering the ports/protocols SLAAC uses to pass them through. Currently I'm using ipfilter as firewall.

I found this page, which appears to give some information on how to make IPv6 addresses work with ipfilter through FreeBSD.

Have free IPv6 now, how to configure IPv6 & ipfilter firewall

I've tried statically assigning an IPv6 address and I could see the message with a static assignment if my IPv6 gateway was wrong, with SLAAC I can't see that happening.
Since I've got a IPv6 pool on this linode should I be using addresses from it and assigning them statically and not using rtsold?

For this, I want to give you some guides that might help you out. The first is ours on IPv6 basics with Linode:

A Guide for Understanding IPv6 on Linode

Here is a guide from FreeBSD that discusses IPv6 configuration:

Advanced Networking - IPv6

Another post here on the Community Questions site that discusses IPv6 addresses from your pool, and enabling them permanently:

Enable IPV6 addresses from pool permanently

Hopefully these links will give you a good place to start. I've also added some tags to this post to increase visibility and get it in front of some of our other FreeBSD users who may have more insight.

@tech43 --

When I set up my FreeBSD 12.1 Linode, I just followed the installation instructions given here:

https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/bsdinstall-network.html

bsdinstall will skip the stuff about wireless…you don't have a wireless interface (it doesn't make sense in a Linode environment).

In particular, the questions about acquiring your IPv4 address using DHCP and your IPv6 address via SLAAC is the important stuff.

In my (pf) firewall, I just allow all IPv4/IPv6 ICMP traffic:

### icmp
##
## allow icmp/icmp6 in both directions
##
### keep state on any outbound icmp/icmp6 traffic. modulate the isn of
### outgoing packets. (initial sequence number) broken operating systems
### sometimes don't randomize this number, making it guessable.
##
pass out on $ext_if proto { icmp, icmp6 } modulate state
pass in on $ext_if proto { icmp, icmp6 }

I rely on blacklist tables defined before this to disallow ICMP/ICMPv6 traffic from bad actors (e.g., using blacklistd).

-- sw

@rgerke Thanks for your reply. I've checked out those links, two of them I've already read, and sent the guy who wrote about the solution an email, we'll see if he responds.

I am still getting the UDP connect no route to host message.

I've switched to pf.

@stevewi Thank you also for your reply. I'm as I said now using pf. I've added your rules and restarted, IPv6 did come up but still getting the UDP connect no route to host so something is still wrong when I do a ping6. I was wondering can you send me your complete rc.conf and pf.conf? I'd like to compare your obviously working configuration to my obviously not-working one. Also, do you use the SLAAC address only or are you using IPv6 pool? If so do you have jails?

Thanks.
Dave.

@tech43 --

You write:

@stevewi Thank you also for your reply. I'm as I said now using pf. I've added your rules and restarted,

You're welcome…

IPv6 did come up but still getting the UDP connect no route to host so something is still wrong when I do a ping6.

Are you blocking port 53 (DNS)? If you are, you shouldn't be. Typically you get this when a domain-name resolution fails. Try ping6'ing the IPv6 address. If that works, then your domain-name lookup is what's failing.

I was wondering can you send me your complete rc.conf and pf.conf? I'd like to compare your obviously working configuration to my obviously not-working one.

The relevant section for pf in rc.conf is:

pf_enable="YES"
pflog_enable="YES"
pf_rules="/usr/local/etc/pf.conf"
pflog_logfile="/var/log/pf.log"

My pf.conf is too long to post here…and it would take too much work to redact big portions of it. Here's the section I use to pass the stuff I want:

### udp
###
### keep state on any outbound udp traffic. modulate the isn of
### outgoing packets. (initial sequence number) broken operating systems
### sometimes don't randomize this number, making it guessable.
##
pass out on $ext_if proto { udp } from any to any modulate state
##
_udp_services = "{ domain, ntp }"

##
##      allow inbound dns and ntp
## 
pass in quick on $ext_if proto udp to any port $_udp_services

### tcp
##
### keep state on any outbound tcp traffic. modulate the isn of
### outgoing packets. (initial sequence number) broken operating systems
### sometimes don't randomize this number, making it guessable.
##
pass out on $ext_if proto { tcp } from any to any modulate state

### block probes that can possibly determine our operating system by disallowing
### certain combinations that are commonly used by nmap, queso and xprobe2, who
### are attempting to fingerprint the server.
### * F : FIN  - Finish; end of session
### * S : SYN  - Synchronize; indicates request to start session
### * R : RST  - Reset; drop a connection
### * P : PUSH - Push; packet is sent immediately
### * A : ACK  - Acknowledgement
### * U : URG  - Urgent
### * E : ECE  - Explicit Congestion Notification Echo
### * W : CWR  - Congestion Window Reduced
##
block in log quick on $ext_if proto tcp flags FUP/WEUAPRSF
block in log quick on $ext_if proto tcp flags WEUAPRSF/WEUAPRSF
block in log quick on $ext_if proto tcp flags SRAFU/WEUAPRSF
block in log quick on $ext_if proto tcp flags /WEUAPRSF
block in log quick on $ext_if proto tcp flags SR/SR
block in log quick on $ext_if proto tcp flags SF/SF

### normally, a client connects to the server and we handshake with them, then
### proceed to exchange data. by telling pf to handshake proxy between the client
### and our server, tcp syn flood attacts from ddos become uneffective because
### a spoofed client cannot complete a handshake.
###
### set a rule that allows inbound ssh traffic with synproxy handshaking.
##
_tcp_services = "{domain, ntp, smtp, smtps, submission, imaps, http, https, ssh}"

pass in on $ext_if proto tcp from any \
                             to any \
                             port $_tcp_services \
                             flags S/SA synproxy state

 

Also, do you use the SLAAC address only or are you using IPv6 pool?

Only the SLAAC address.

If so do you have jails?

No.

Do you have a copy of The Book of PF by Peter N.M. Hansteen (https://amazon.com/Book-PF-No-Nonsense-OpenBSD-Firewall/dp/159327274X/ref=pd_sbs_14_1/130-8220585-3441942 )? If not, you should…

DANGER WILL ROBINSON!!!! This is not a how-to book and is pretty dense…

-- sw

@stevewi Thanks for your reply. I do have "The Book of PF" it's the Second edition, I did check and realized there's a third edition out, I'm going to get that and give it a go. In answer to your question I am not blocking port 53. When I boot I've got to add a route command to be able to even ping6 my own ipv6 address. As of this writing I have pf disabled.
Here's information:

netstat -rn -6

Routing tables

Internet6:
Destination Gateway Flags Netif Expire
::/96 ::1 UGRS lo0
::1 link#2 UH lo0
::ffff:0.0.0.0/96 ::1 UGRS lo0
2600:3c03::/64 link#1 U vtnet0
2600:3c03::f03c:91ff:fedf:6fc link#1 UHS lo0
2600:3c03:e000:1aa:abcd::1 link#1 UHS lo0
fe80::/10 ::1 UGRS lo0
fe80::%vtnet0/64 link#1 U vtnet0
fe80::f03c:91ff:fedf:6fc%vtnet0 link#1 UHS lo0
fe80::%lo0/64 link#2 U lo0
fe80::1%lo0 link#2 UHS lo0
fe80::%epair0a/64 link#4 U epair0a
fe80::ad:9bff:fef9:5e0a%epair0a link#4 UHS lo0
ff02::/16 ::1 UGRS lo0

ifconfig vtnet0

vtnet0: flags=8943<up,broadcast,running,promisc,simplex,multicast> metric 0 mtu 1500
options=2c00b9<rxcsum,vlan_mtu,vlan_hwtagging,jumbo_mtu,vlan_hwcsum,vlan_hwtso,linkstate,rxcsum_ipv6>
ether f2:3c:91:df:06:fc
inet xxx.xxx.xxx.xxx netmask 0xffffff00 broadcast 66.228.47.255
inet6 fe80::f03c:91ff:fedf:6fc%vtnet0 prefixlen 64 scopeid 0x1
inet6 2600:3c03::f03c:91ff:fedf:6fc prefixlen 64 autoconf
inet6 2600:3c03:e000:1aa:abcd::1 prefixlen 128
media: Ethernet 10Gbase-T <full-duplex>
status: active
nd6 options=23<performnud,accept_rtadv,auto_linklocal></performnud,accept_rtadv,auto_linklocal></full-duplex></rxcsum,vlan_mtu,vlan_hwtagging,jumbo_mtu,vlan_hwcsum,vlan_hwtso,linkstate,rxcsum_ipv6></up,broadcast,running,promisc,simplex,multicast>

ping6 -c 1 davemehler.com

PING6(56=40+8+8 bytes) 2600:3c03::f03c:91ff:fedf:6fc --> 2600:3c03::f03c:91ff:fedf:6fc
16 bytes from 2600:3c03::f03c:91ff:fedf:6fc, icmp_seq=0 hlim=64 time=0.103 ms

--- davemehler.com ping6 statistics ---
1 packets transmitted, 1 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 0.103/0.103/0.103/0.000 ms

ping6 -c 1 ipv6.google.com

ping6: UDP connect: No route to host

route -n add -inet6 default fe80::1

add net default: gateway fe80::1

(That fe80::1 was in the linode control panel).

ping6 -c 1 ipv6.google.com

PING6(56=40+8+8 bytes) 2600:3c03::f03c:91ff:fedf:6fc --> 2607:f8b0:4006:800::200e

--- ipv6.l.google.com ping6 statistics ---
1 packets transmitted, 0 packets received, 100.0% packet loss

(Looks like dns is working, but it's not sending out anything, again this is with no firewall on at all).

netstat -rn -6

Routing tables

Internet6:
Destination Gateway Flags Netif Expire
::/96 ::1 UGRS lo0
default fe80::1 UGS lo0
::1 link#2 UH lo0
::ffff:0.0.0.0/96 ::1 UGRS lo0
2600:3c03::/64 link#1 U vtnet0
2600:3c03::f03c:91ff:fedf:6fc link#1 UHS lo0
2600:3c03:e000:1aa:abcd::1 link#1 UHS lo0
fe80::/10 ::1 UGRS lo0
fe80::%vtnet0/64 link#1 U vtnet0
fe80::f03c:91ff:fedf:6fc%vtnet0 link#1 UHS lo0
fe80::%lo0/64 link#2 U lo0
fe80::1%lo0 link#2 UHS lo0
fe80::%epair0a/64 link#4 U epair0a
fe80::ad:9bff:fef9:5e0a%epair0a link#4 UHS lo0
ff02::/16 ::1 UGRS lo0

It seems like my default route is not being added until I manually add it, then when I do still can't ping6 anything beyond my own IPv6 address.

Here's a link to my pf.conf file, does anything look wrong? Again this is from the second edition of the book.

https://www.dropbox.com/s/uiy8u38fpl15hbn/pf.conf?dl=0

You don't need to post your pf.conf file here, can you put it somewhere with a link? I'd like to see it as you've got a linode like I do and the single vtnet0 interface, and your configuration works, as mine does not i'd like to compare your complete file with mine see where I'm falling short.

I thought SLAAC was suppose to configure gateway and route, it seems like this isn't happening.

Keep the suggestions coming.
Thanks.
Dave.

@tech43 --

You can view mine at

https://niteflyte.net/pf.txt

I changed it to .txt so you could view it in your browser. The 'blacklist anchor' is generated by another process (it runs every 4 hours). I included the text of it as comments directly beneath the anchor declaration.

Your situation is much more complex than mine…

-- sw

@stevewi Thanks for the pf.txt file. I'll look at it and compare it with mine. One question, when you did your install did you select DHCP or static for IPv4 configuration and SLAAC or static configuration for IPv6? What I'm going to do next is do a FreeBSD 12.1 install on my nanode and see if I get different results.

@tech43

I used DHCP.

— sw

@stevewi Thanks for your help. I got it after some testing and tweaking, I had to turn some items off and ensure everything works. If you want I can send you the modifications I made to your firewall I started with your working config and combined items in my own configuration that I wanted to produce the results that all now is working. I have a question about your blacklists. You reference:

bl-nets4
bl-nets6
bl-nodes4
bl-nodes6
How do you load/populate these files? What are your sources for blacklist information? With regards PF I've turned on blacklistd on FreeBSD as well as hooked sshd in to it, and loaded up fail2ban and set an anchor. Is there anything else I should do to get either/or blacklistd/fail2ban going? In both cases I believe I have added my ISP's IP to each of there respective whitelists so I shouldn't be cut out.
Thanks again.

@tech43 --

These pf tables (on Linux, these are ipsets):

bl-nets4
bl-nets6
bl-nodes4
bl-nodes6

are created from files that are created by a Ruby program that runs as a cron(8) job. The program gets a lot of its input from here:

https://iplists.firehol.org/files

It also gets information some url's that contain "bad actor" lists. For example,

The biggest source of information, however, is a custom database of free geolocation information about the internet (which networks belong to which country, city, ASN, etc.) from maxmind.com and ip2location.com.

I have couple of cron(8) jobs that collect this free information and compiles it into a custom sqlite(1) database. The maxmind.com data is downloaded weekly (on Tues nights) and the ip2location.com data is downloaded monthly (on the first Thurs). This database is used for other things too -- so it's a system service (and I wrote a Ruby API to access it in a standard way). The structure of the database is pretty straightforward so it would be easy to come up with APIs in other languages…I just prefer Ruby.

The size of this geolocation database is currently 1.9GiB.

The blacklists allow me to ban traffic from entire countries and autonomous system numbers (ASNs). I use this mechanism to keep out the Russians, Chinese, (North & South) Koreans, etc. I can add or subtract whole countries from these blacklists by adding/deleting lines in a config file. As you can probably tell, this whole system handles both IPv4 and IPv6.

I found that fail2ban was so busy banning intrusion/spamming attempts that the lists of firewall rules created by fail2ban started to run to several pages.

Compiling these blacklists is a tougher problem that you think… Since (on Linux at least), these lists live in the kernel, you want them to be as absolutely small as possible. It's pretty obvious that you want to get rid duplicates. That's pretty easy. However, you want to discard any single IP addresses that are members of networks that are included. You also have to blacklist traffic from bogons/martians. You have to have the ability to whitelist traffic (for example, I live in Oregon, my ISP is in Seattle and my Linode is in California so I whitelist traffic from my ISPs local Portland DHCP pool). You have to worry about IPv4-mapped IPv6 addresses. If you're going to update the blacklists multiple times a day, the performance has to be pretty good.

I implemented blacklistd(8) but decided against going forward with it since, unlike fail2ban(1), there's no adjustable time limit for IP addresses to live in the blacklist. There's no client (like fail2ban-client(1)) to manage the blacklist (yeah, I know I could do it with pfctl(8)…). I suppose I could gin up something to do this but I decided to stick with fail2ban(1) since that "something" was already built…

I recently ported all this from Linux to FreeBSD. I'm working on some changes to the geolocation service at the moment. It's taken me several years to get all this where it is today.

I'd be happy to discuss this with you further but we should prob take it out of this forum. Go to https://niteflyte.net. You'll find an email address there…it's a mailto: url but the page has copy/paste disabled and the (encrypted) anchor tag is not formed with HTML to foil automated screen scrapers.

-- sw

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct