FreeBSD 9 PF macro & table changes

I secure my BSD servers with PF. In FreeBSD 9, PF has been updated to the same version as in OpenBSD 4.5.

I use lists in my PF configuration, as shown in this /etc/pf.conf snippet:

mgmt_hosts="{ 10.0.1.0/24, 172.19.8.0/24}"
...
pass in on $ext_if from $mgmt_hosts
...

When I have new management hosts, I add their IP address or subnets to the mgmt_hosts list. When PF reads this configuration file, every place that a rule references the list, an additional rule is created for each member of the list. Here, every subnet in the mgmt_hosts list gets a “pass in” rule. When I list these rules on a running FreeBSD 8 host, they’ll look something like this:

# pfctl -sr
...
pass in on em0 inet from 10.0.1.0/24 to any flags S/SA keep state
pass in on em0 inet from 172.19.8.0/24 to any flags S/SA keep state
...

Very useful for maintaining a readable rule file.

I updated a host to FreeBSD 9, and saw the following in my rules.

# pfctl -sr
...
pass in on vr0 inet from <__automatic_4c6aed29_0> to any flags S/SA keep state
...

Wait a minute. What is this __automatic crap? And where are my management hosts?

This version of PF automatically converts lists to tables. If you have a big rule set, using a table makes the rules shown by pfctl more readable. (I seem to recall that tables perform better than lists, but I can’t find a reference for that, so take that with a grain of sand.)

You can name tables, but tables created by PF have a name that starts with __automatic. To view all the tables, run:

# pfctl -sT
__automatic_4c6aed29_0
#

To see the hosts in this table, use pfctl’s -t and -T flags.

# pfctl -t __automatic_4c6aed29_0 -T show
10.0.1.0/24
172.19.8.0/24
#

Wow. This works, but it doesn’t look like fun. If I have to routinely type __automatic_4c6aed29_0, I will increase my subvocalized swearing by at least ten percent. But it does not interrupt service. Old rule sets continue to work. (I don’t mind needing to update my rules with a new OS version, but I need to know about it beforehand rather than just blindly updating.)

To make my life easier I can convert my PF rules to use tables instead of lists. Here’s the same pf.conf using a table instead of a list.

table <mgmt_hosts> const {10.0.1.0/24, 172.19.8.0/24}
...
pass in on $ext_if from <mgmt_hosts>
...

Unlike a list, a table is explicitly declared as a table. The name always appears in angle brackets.

I use the const keyword to tell PF that the contents of this table cannot be changed at the command line. PF tables can be adjusted at the command line without reloading the rules, which is a handy feature for, say, automatically blocking port scanners, feeding IDS data to your firewall, or DOSing yourself.

When I look at my parsed rules now, I’ll see:

# pfctl -sr
...
pass in on vr0 from <mgmt_hosts> to any flags S/SA keep state
...

I can now read my rules more easily.

(Bootnote: OpenBSD just came out with 5.0, so FreeBSD 9 is five versions behind. OpenBSD PF develops quickly. But thirty-month-old PF is better than a lot of other firewall software.)

sudo environment purging and OpenSSH

I recommend using sudo for privileged access to systems. I also recommend requiring keys for SSH authentication, with agent forwarding to trusted systems. The default settings in these two programs collide head-on when you become superuser via sudo and want to copy files from one server to another with scp or sftp.

If you’re using an SSH agent, your environment contains the location of your authentication socket.

# env | grep SSH
SSH_CLIENT=192.0.2.2 51502 22
SSH_CONNECTION=192.0.2.2 51502 198.0.2.10 22
SSH_TTY=/dev/pts/1
SSH_AUTH_SOCK=/tmp/ssh-aJpJNwwOTk/agent.35699
#

When you copy files with scp(1) or sftp(1), the client checks for a SSH authentication socket. If the client doesn’t find one, and the user account doesn’t have a private key on this system, and the remote server doesn’t support password auth, the client will not be able to log in.

All as you would expect, right? But like any good firewall, sudo(8) removes all environment variables not explicitly permitted. To see what sudo(8) does to your environment, as well as all of sudo’s other settings, become root and run sudo -V.

# sudo -V
Sudo version 1.6.9p20

Sudoers path: /usr/local/etc/sudoers
Authentication methods: 'pam'
Syslog facility if syslog is being used for logging: local2
...
Environment variables to check for sanity:
TERM
LINGUAS
LC_*
LANGUAGE
LANG
COLORTERM
Environment variables to remove:
RUBYOPT
RUBYLIB
PYTHONINSPECT
...
Environment variables to preserve:
XAUTHORIZATION
XAUTHORITY
TZ
PS2
PS1
PATH
...

sudo sanity-checks some environment variables, deliberately strips others, and explicitly preserves a few.

To use agent forwarding for SSH authentication while running as root, add the SSH environment variables to sudo’s configuration. While I could restrict this by groups, I’ll make this a default setting. Call up visudo and add a new default.

Defaults env_keep += "SSH_CLIENT SSH_CONNECTION SSH_TTY SSH_AUTH_SOCK"

Exit superuser, use sudo to become superuser again, and your environment will retain your SSH environment.

While sudo can preserve any environment variables you wish, sudo strips the environment for very good reasons. Don’t retain environment variables unless you’re sure what they will do. And don’t retain easily-abused environment variables, such as LD_PRELOAD. If the superuser needs dangerous environment variables, put them in a separate configuration file and source that file after becoming superuser.

Replicating Routerboards

I needed to mass-configure MikroTik Routerboards. Each needed a very similar but not identical configuration: they would have a unique management IP, and a unique username and password for their VPN connection back to my employer’s headquarters. I don’t have time or desire to do this routine configuration myself, so I needed a method that would let a less technical person do the work.

You can back up and restore RouterOS configurations, but then I’d need to have the user do all sorts of pointy-clicky things to configure the device. Pointy-clicky is difficult to reliably reproduce. RouterOS also supports exporting the configuration as a script, but they warn that this script is not suitable for duplicating a system. I wound up using the export function, but modifying the resulting script to create a new configuration that could be loaded onto the new device.

All of this was tested with Routerboard 750s, running RouterOS 5.6. I used one device as a master, and a second to test loading the new configuration. I also created a list of hostnames, IP addresses, and VPN usernames and passwords. (My team will manage these devices remotely, so the user will never see the username and password. If I deployed more than a couple dozen boxes, I’d need a different auth scheme.)

First, make sure your Routerboard is in the default configuration. Reset to the factory defaults if necessary. Load the same version of RouterOS onto the new device as exists on your master device.

Log onto your master device. Configure it the way you want, and export the configuration.

admin@master> export file=cleanconfig
admin@master> file print
...
0 cleanconfig.rsc script 16 507 jan/02/1970 19:26:39
...

This file is the seed of my configuration script. copy it to your desktop. (The detail-oriented among you will note that my configuration should include “Set the system clock.” Feel free to stay after class and clean the blackboards as a reward.)

Unlike Cisco and its imitators, RouterOS isn’t modal. You don’t need to enter a configure mode to change the router. Instead, it has a hierarchical configuration method from the command line. For example, there’s an interface command, with an Ethernet subcommand. To work on the Ethernet interfaces, you would enter interface Ethernet. Starting a command with a leading slash tells RouterOS to go back to the root. Most of the actual commands within this level are fairly self-explanatory to anyone experienced with routers.

/interface ethernet
set 0 arp=enabled auto-negotiation=yes disabled=no full-duplex=yes l2mtu=1526 \
mac-address=00:0C:42:5A:D9:50 mtu=1500 name=ether1-gateway speed=100Mbps

The set command tells RouterOS to change a setting for an existing item. The Ethernet interface already exists, you just need to give it a configuration. Alternately, the add command tells RouterOS to add something new to a configuration, such as an IP address.

/ip address
add address=192.168.88.1/24 comment="default configuration" disabled=no \
interface=ether2-master-local network=192.168.88.0

The system has no IP address, so you must add one.

If your script tries to add something that already exists, it will fail. For example, if your configuration already has a DHCP client setting, adding a new, identical one will terminate your script early. For my application, I had to remove the following from my master configuration.

/interface ethernet switch
/interface wireless security-profiles
/ip hotspot profile
/ip hotspot user profile
/ip ipsec proposal
/queue type
/routing bgp instance
/routing ospf instance
/routing ospf area
/system routerboard settings
/user group
/interface ethernet switch port
/interface l2tp-server server
/interface ovpn-server server
/interface sstp-server server
/interface wireless align
/interface wireless sniffer
/interface wireless snooper
/ip accounting
/ip accounting web-access
/ip dhcp-client
/ip dhcp-server config
/ip firewall connection-tracking
/ip firewall nat
/ip firewall service
/ip hotspot service-port
/ip neighbor discovery
/ip proxy
/ip socks
/ip ssh
/ip traffic-flow
/ip upnp
/mpls
/mpls interface
/mpls ldp
/port firmware
/ppp aaa
/queue interface
/radius incoming
/routing bfd interface
/routing mme
/routing ospf network
/routing rip
/store
/system console
/system health
/system resource irq
/system upgrade mirror
/system watchdog
/tool bandwidth-server
/tool email
/tool graphing
/tool mac-server
/tool mac-server ping
/tool sms

I then had some items that were different in my desired configuration and the default configuration. For example, the default 750 configuration has a firewall. I needed a firewall configuration that had no overlap with the default configuration. I added entries at the beginning of my script to remove that configuration. Similarly, I didn’t want the default IP address on this device.

/ip pool remove 0
/ip dhcp-server network remove 0
/ip dns static remove 0
/ip firewall filter remove 3
/ip firewall filter remove 2
/ip firewall filter remove 1
/ip firewall filter remove 0
/system logging remove 3
/system logging remove 2
/system logging remove 1
/system logging remove 0
/ip address remove 0

Other parts were more tricky. I wanted to configure the Ethernet interfaces, but I didn’t want to change the MAC address of the interfaces. I removed the mac-addr statements from the Ethernet interface configuration.

Now that I have a clean master script, I copy it to a separate file for the slave configuration script. In the copy, I change the IP address, hostname, username, and passwords as necessary.

I could then copy the script to my target machine and run

admin@target> import configscript.rsc
admin@target>

If the script doesn’t exit silently, it failed. Compare the target platform’s new configuration to your script to see where it failed, or run your script piecemeal to see where it crashes.

This was a good day’s work to learn how to do, but now I can hand my script to a junior tech and tell him to set up a couple dozen of these without bothering me. It’ll save me days of my time in the long run.

Book updates, August 2011

I completed a first draft of the OpenSSH book last night around 10:30PM EDT. It’s out for tech edit now. At this point, I’m going systematically through the tech edits and making sure I’ve corrected the earlier chapters. After that, the manuscript goes to copyediting. Once copyedit is complete, I’ll release the ebook and start contracting out the POD version.

I normally write both nonfiction and fiction simultaneously. When I get frustrated with one project, I switch to the other. The context switch clears my brain. When I return to the vexing project, I can approach the problem fresh and work through it quickly.

I decided to do two nonfiction projects simultaneously this summer. In retrospect, this was a mistake. When I got frustrated with one project, I switched to the other… and found myself still frustrated. Perhaps I can do two nonfiction projects simultaneously, but OpenSSH and OpenBSD have a lot in common. One is just a subset of the other. My frustrations would probably be reduced if I knew what I was doing, but if I knew what I was doing, I wouldn’t write the book.

Lesson learned. If I want to write two nonfiction books simultaneously, they must be wildly diverse.

The OpenBSD book has therefore moved slowly. It’s further complicated by moving over the next couple weeks. I’ll be full-out cranking on the OpenBSD book this fall, however.

I predicted that the OpenSSH book would be 30,000 words. The first draft came in at 29,977 words. I am amazed; usually my books come in at 25-50% over the predicted word count. Perhaps I’m learning. But I’m probably just lucky.

ISC dhcpd and MAC prefixes

We have a network at the office without a firewall. Several of our technical folks run a whole mess of oddball network protocols, and maintaining a network firewall would take more manpower than it’s worth. We hand these techs a network cable and tell them to not let their gear get broken into, and then heckle them mercilessly when their server becomes a haven for Eastern European porn.

But the boss just got back from ClueCon, where he learned about a whole bunch of nasty exploits for older Cisco phones. These techs have VoIP phones on their desks. The decision was made to give the VoIP phones private addresses, overlaid on the public addresses. Yes, a firewall would be much better, but the maintenance overhead was too high in this situation.

Our VoIP phones have have MAC addresses in particular ranges. For example, a certain model of phone has MAC addresses beginning with 00:03:e3, others begin with 00:03:6b, and the third begin with 00:07:eb. If a device’s MAC address begins with one of these, it should get an address in 172.19.22.0/24. Otherwise, it should get an address in the public pool of 192.0.2.0/24. I’m using ISC dhcpd 3.1.

Start by breaking the devices into classes. Each class will have its own IP configuration. dhcpd has a pattern-matching feature that lets you match MAC addresses like this dhcpd.conf snippet.

class "sip-phone" {
match if (binary-to-ascii (16,8,":",substring(hardware, 0, 4)) = "1:0:3:e3")
or (binary-to-ascii (16,8,":",substring(hardware, 0, 4)) = "1:0:3:6b")
or (binary-to-ascii (16,8,":",substring(hardware, 0, 4)) = "1:0:7:eb");
log (info, (binary-to-ascii (16,8,":",substring(hardware, 0, 4))));
}

class "other" {
match if not (binary-to-ascii (16,8,":",substring(hardware, 0, 4)) = "1:0:3:e3")
and not (binary-to-ascii (16,8,":",substring(hardware, 0, 4)) = "1:0:3:6b")
and not (binary-to-ascii (16,8,":",substring(hardware, 0, 4)) = "1:0:7:eb");
log (info, (binary-to-ascii (16,8,":",substring(hardware, 0, 4))));
}

So, if a host has a hardware (MAC) address matching one of the patterns in the “sip-phone” class, it’ll be classified as a sip phone. If the hardware address doesn’t match anything in the sip-phone class, it’ll be classified as other.

What does that horrible string mean? Read dhcp-eval for details, but here’s the short and nasty version. Inside dhcpd, hardware addresses are binary. The binary-to-ascii function transforms a binary field into characters. The 16,8,: tells binary-to-ascii how to parse the binary data and where to separate the characters. The substring function takes a small portion of the ASCII string, specifically places 0 through 4. The characters are a hardware label (a 1 means Ethernet) followed by a colon, followed by the MAC address. So, to match all Ethernet MAC addresses starting with 00:03:e3, we must search for 01:00:03:e3, shown without the leading zeroes as 1:0:3:e3.

The Boolean logic around these comparisons groups the MAC addresses into classes by MAC.

The interesting bit here is the “log” statement. I wanted to see how the binary-to-string and the substring functions mauled the original MAC address. This LAN has a sufficiently small DHCP request rate that I was able to log the first sixteen bytes of each hardware identifier (including the leading 01: for Ethernet). This helped me figure out what the heck I was finding as I struggled through dhcp-eval(5). These logs were written to the DHCP server log. Remove them when you’re done testing.

In this dhcpd.conf snippet we assign the two classes separate address ranges.

shared-network techs {
subnet 172.19.22.0 netmask 255.255.255.0 {
option routers 172.19.22.1;
pool {
allow members of "sip-phone";
range 172.19.22.10 172.19.22.100;
next-server 192.0.2.130;
}
}

subnet 192.0.2.0 netmask 255.255.255.0 {
option routers 192.0.2.1;
pool {
allow members of "other";
range 192.0.2.100 192.0.2.200;
}
}
}

The DHCP server has an interface on this subnet. I added a private IP to the interface, so that it has both 192.0.2.0/24 and a 172.19.22.0/24 addresses. The shared-network statement tells the DHCP server to not be shocked when it sees both subnets on the local interface.

So far, this works.

UPDATE: To all the folks who say that this network could certainly be VLAN’d and firewalled. There is no technical reason this couldn’t happen. The problems are political. Political problems are just as real as technical problems.

How to Lose your Job with SSH, part 2

Like last week’s How to Lose your Job with SSH, Part 1, a less dramatic title for this would be Dynamic Port Forwarding with SSH, but that’s dreadfully dull.

Many corporations try to tightly secure their network. Connections to the outside world are strictly limited. If you have a single open TCP/IP port to the outside world, however, you can leverage this into blanket Internet access by using your SSH client as a SOCKS proxy. This is called dynamic forwarding.

SOCKS is a generic TCP/IP proxy. SOCKS tunnels arbitrary protocols, as long as the client program supports SOCKS. Many clients, including the major Web browsers, do.

To do this, you would SSH from your client on the protected network to a server on the public Internet. The client opens a SOCKS proxy on a TCP port on the local machine. When a client connects to this proxy, the traffic is forwarded across the Internet to the SSH server. The SSH server processes the request and feeds the data back to you. It’s not a terribly fast proxy, but it is encrypted and it will bypass the corporate firewall and Web proxies.

Use the -D flag to tell the OpenSSH client to use dynamic port forwarding. (You can do the same thing with PuTTY, but that’s a separate walk-through.)

$ ssh -D localaddress:localport hostname

If you don’t specify a local IP, the client automatically binds to 127.0.0.1.

Here, I open a dynamic proxy on port 9999 to the server pride.blackhelicopters.org

$ ssh -D 9999 pride.blackhelicopters.org

Leaving the SSH session up, now go to the Web browser on the local machine. Somewhere in the browser preferences you’ll find a place for proxy servers. Tell your browser it has a proxy at 127.0.0.1 on port 9999. Save the settings and start browsing the Internet. Your Web browsing will be slow, but it’ll get you on the Internet.

If I list a network-facing IP on my client, anyone who can connect to that port on the client can use my proxy.

$ ssh -D 10.10.10.105:9999 pride.blackhelicopters.org

This is, of course, a violation of the security policy at these security-sensitive companies. Doing it will get you fired.

As a network administrator responsible for such an environment, what can you do about this?

  • If you run an external SSH server that your users need to log into, disable SSH forwarding with the AllowTcpForwarding option in sshd_config.
  • Watch your traffic. See how much traffic various protocols use on your network. This will not only help you catch SSH tunnels, it will help you catch any other sort of tunnel. You must know what is normal before you can catch strangeness, however.
  • You could forbid external SSH, and only permit protocols that can be proxies, such as Telnet.
  • You can set up a legitimate SOCKS server, with logging, and require all traffic pass through it. Anyone tunneling large amounts of traffic through the server will stand out in the logs.
  • Most of these solutions require the network administrator to know what happens on his network. You must have basic network awareness, in advance, or you’ll never find these people.

    And if you’re an end-user who creates his own SOCKS proxy in such an environment, gets caught, and gets fired for it, do let me know. I can always use a good laugh at someone else’s expense.

    Practical Packet Analysis, 2nd Edition

    The second edition of Chris SandersPractical Packet Analysis is about twice as large as the first edition and twice as useful.

    I learned Wireshark in the traditional manner: got annoyed with tcpdump, installed Wireshark, and started poking menus and buttons until I got a result. Chapters 1-5 of PPA takes you through the important menus and buttons. There’s not much you can do to make descriptions of software options interesting, but Sanders demonstrates real-world uses as he goes along. Demonstrating how to use round-trip-time graphing with real data, for example, gives the buttons and menus relevance to our work. Chapters 6 and 7 cover a few basic network protocols, from ICMP to HTTP to social media logins and DHCP and so on, to ground you in what traffic should look like.

    The really interesting part of the book is the second half. Starting in Chapter 8, Sanders dives into real-world problems and shows how to investigate them with Wireshark. He covers topics from difficult developers to network latency to security. What does a worm look like on the network? How about wireless?

    The book organization invites me to keep it at hand for troubleshooting. The next time I investigate a slow network, I’ll turn to PPA2e chapter 9. And that’s perhaps the best praise I can offer on any technical book.

    Practical Packet Analysis invites comparison with my own Network Flow Analysis. As you might guess, I consider network awareness skills absolutely vital for any network engineer. Where my work is about broad-scale network flows, however, Sanders’ work lets you dig deep into individual packets. Jitter, latency, loss, and all the details of protocol transactions are resistant to flow analysis, whereas packet analysis will lay them bare. I know my readers have already bought and devoured my book, but you really need to master both tools.

    Plus, the author proceeds from Practical Packet Analysis are all being donated to the Rural Technology Fund. The narrator of NFA recommends using flow analysis to blackmail your coworker into washing and waxing your car. I am forced to conclude that Sanders is probably a better human being than I am.

    Buy this book.

    Disclaimer: No Starch Press also publishes books by yours truly. I have no problem calling them out if I disagree with them. Watch, I’ll demonstrate:

    “Hey, guys, I really liked the color text boxes we did in PGP & GPG. I know they were more expensive than plain black and white pages, and I know that book sold fewer copies than anything else I’ve written, but it looked really cool. Why don’t we do that everywhere?”

    OK, maybe that’s me being an entitled prima donna rather than disagreeing with them, but still, I wouldn’t write a positive review on a book I didn’t like.

    How to Lose your Job with SSH, part 1

    A less sensational title for this post would have been “SSH Remote Forwarding,” but that’s not nearly as fun.

    I used to be responsible for one of the few entry points into a global network. The company had actual manufacturing secrets — their products included various machines of war. We had internal firewalls to protect sites from each other, even when the site didn’t have Internet access. All Internet connections had to go through proxies. We did not allow external DNS to reach the desktop. If you typed ping google.com on your desktop, you’d get a “host unknown” error. The company had invested in VPN technology that blocked all but approved clients, and only permitted clients on the approved list if they were running the approved anti-virus scanners and other security software.

    I was frequently asked to open direct Internal access for random applications. Most of these requests were rejected unless the user could explain what they wanted and why it was business-critical. Some of the people who asked were technically literate, and became indignant when I rejected their request for outbound SSH to external servers or equipment. After all, SSH is “Secure Shell.” It says secure RIGHT IN THE NAME. They just want to check their personal email. How could I possibly reject this eminently sensible request?

    I’ve since had left this job, but I’ve had the same discussion more than once afterwards.

    Most SSH users have no idea of SSH’s flexibility. Arbitrary SSH connections are a nightmare for maintaining any sort of secure information perimeter. Remote port forwarding is one reason why.

    When most people mention SSH port forwarding, they’re thinking of local port forwarding. You forward a TCP port on your client to a TCP port on the SSH server. This lets you, say, tunnel SMTP inside SSH, so your client can relay mail through your server without any complicated Sendmail rules.

    Remote forwarding lets you do the reverse: forward a TCP port on the SSH server to a TCP port on the SSH client.

    Suppose I permit a user to SSH to an external server. The desktop is behind a NAT. There are no port mappings from the NAT to the desktop; it has the same connectivity you might give a secretary, except for the outbound SSH access to a single host. That user sets up remote port forwarding from a TCP port attached to the server’s public IP to the client’s SSH daemon. I’m using an OpenBSD desktop, but you can get SSH clients for most other operating systems, including Windows. I’m using OpenSSH, of course, but most clients (including PuTTY) does remote port forwarding.

    To do remote port forwarding in OpenSSH, run:

    $ ssh -R remoteIP:remoteport:localIP:localport hostname

    If you don’t specify an IP address to attach to the SSH server, the server attaches to 127.0.0.1. (You can also skip the first colon in this case.)

    My desktop runs sshd. I want to attach port 2222 on the SSH server pride.blackhelicopters.org to port 22 on my SSH client using remote port forwarding.

    client$ ssh -R 2222:localhost:22 pride

    I leave this connection up and go home. Perhaps I run top in the command window, to prevent the SSH session from timing out at the corporate firewall. Now at home, I log into the SSH server and run:

    pride$ ssh -p 2222 localhost

    My SSH request to the local machine will get tunneled inside the existing SSH connection out of the network. I will get a logon prompt for my client inside the secure network. When I can access one supposedly secure machine, I can start ripping data out of the local file servers and maybe even access other internal sites. All of the trouble the company expended to prevent unauthorized access is now moot.

    If you attach the remote port forwarding to the server’s public IP, then anyone on the Internet can attack your desktop’s SSH daemon. People are attacking SSH servers, even on odd ports.

    Of course, remote port forwarding in this environment would violate company policy. If caught, you’d lose your job. But to catch this abuse, the network administrator would need to realize that large data transfers were taking place in off hours over these limited-use channels. You could, say, use flow analysis to write automated reports that notice and alarm when large amounts of traffic pass over these “rarely-used” channels. You’d have to be a real bastard to think of that. But the reports are easy to write, and the look on the abuser’s face when you confront them with graphs and numbers is priceless.

    The point is, the next time your employer’s network administrator rejects your sensible request for SSH access to your home server, don’t be too hard on the poor slob.

    Want more SSH fun? Check out the book recommended by the OpenSSH project, SSH Mastery.

    creating FreeNAS 8 iSCSI target

    I didn’t find an up-to-date tutorial on how to set up a FreeNAS 8 iSCSI target, so I took notes as I set one up. Figuring this out by brute force is fairly straightforward: just keep adding iSCSI stuff until you can actually discover iSCSI targets. But for those of you who value your time, here’s how you do it.

    1) Go to services, enable iscsi. Under iSCSI, choose Target Global Configuration. In Discovery Auth Method choose CHAP. Leave all other settings unchanged

    2) It seems that FreeNAS doesn’t yet let you export a whole drive via iSCSI; you must create an extent. Under iSCSI, select Extents, then Add Extent. Name your extent, give it a path, and set a size.

    3) On the Target Global Configuration, on the “authentication” tab, create an iSCSI user and assign it a secret

    4) You need an iSCSI Portal. Click the Portals tab. This is where you define the iSCSI target. The default is to listen for iSCSI connections on all IP addresses, on port 3260. If you have multiple IP addresses, and want separate portals for each, be more specific.

    5) You must authorize initiators. Choose “Authorized Initiator,” then “Add Authorized Initiator.” List the IP subnet of your initiators under Authorized Network.

    6) Go to the Targets tab. Add a target.

  • Give the target a name and and an alias.
  • The type will be “disk.”
  • flags read-write
  • portal group ID is the number of the portal (probably 1)
  • initiator group ID is the number of the authorized initiators you created (probably 1)
  • Set auth method to CHAP
  • authentication group number from the user you created (also probably 1)
  • 7) Under “Associated Targets,” attach the extent to the target.

    Now go to your iSCSI initiator and log in.

    To create new iSCSI targets, create a device extent, add a target for that extent, and attach the extent to the target.