Every failure we hit while building an iSCSI target Windows Server lab came at the login, with one vague error. We produced that error, Authentication Failure, three different ways: a wrong secret, CHAP left off on the initiator, and an authentication type typed in mixed case. With all three fixed, the persistent session came back 11 seconds after a reboot (tested October 2026 against a Windows Server 2025 target).
Below, we install the iSCSI Target Server role with PowerShell, create a dynamic VHDX disk and a target limited to one initiator IQN, and turn on one-way CHAP. A Windows Server 2022 initiator then connects through both the GUI and PowerShell, and a Rocky Linux 10 host connects as a second initiator. The role installed the same way on the Server 2022 box. The Server 2019 walkthrough with the wizard screens stays online as the Windows Server 2019 iSCSI target guide.
How the lab fits together
One Windows Server 2025 machine, bench-san, holds the storage and runs the target service (WinTarget). Two initiators connect to it over TCP 3260, and each one gets its own target and its own virtual disk, because two hosts writing to one NTFS volume without a cluster file system will corrupt it.

Every value used below is in this table. Replace the IP addresses, host names and secrets with your own; everything else can stay as it is. The target names and IQNs only have to agree with each other, so keep a copy of this table with your values while you work, because the same strings come back on three machines.
| Host | Role | OS | IP | iSCSI name (IQN) |
|---|---|---|---|---|
| bench-san | iSCSI target | Windows Server 2025 Datacenter | 10.0.1.10 | targets bench-tgt, perf-tgt |
| bench01 | Windows initiator | Windows Server 2022 Standard | 10.0.1.21 | iqn.1991-05.com.microsoft:bench01 |
| perf-a | Linux initiator | Rocky Linux 10 | 10.0.1.22 | iqn.1994-05.com.redhat:perf-a |
All commands run in an elevated PowerShell session (Run as administrator) on the host named in each step. A domain is not needed; the three machines in this lab were standalone servers on one subnet. CHAP does its own authentication, so the CHAP user created in Step 4 is not a Windows account and needs no entry in Active Directory.
Step 1: Install the iSCSI Target Server role
The iSCSI Target Server is a role service under File and Storage Services, and one cmdlet installs it together with the Server Manager pages that manage it. Run it on the target, bench-san:
Install-WindowsFeature FS-iSCSITarget-Server -IncludeManagementTools
On the test box the install took 254 seconds and asked for no restart, so you can do it on a running file server without a maintenance window. The Feature Result column shows that it also pulled in the File Server role service.
Success Restart Needed Exit Code Feature Result
------- -------------- --------- --------------
True No Success {File and iSCSI Services, File Server, iSCSI Target Server}
In the Add Roles and Features wizard the same checkbox sits under File and Storage Services, File and iSCSI Services, iSCSI Target Server. The role starts the WinTarget service straight away and sets it to start automatically, which this check confirms:
Get-Service WinTarget | Select-Object Status,StartType,Name
Look for Running and Automatic in the output.
Status StartType Name
------ --------- ----
Running Automatic WinTarget
That is the state the rest of the guide expects, so the target comes back on its own after a restart of bench-san. Initiators can only restore their sessions when this service answers, which is why the reboot test in Step 7 restarted the initiator and left the target up.
Step 2: Check that TCP 3260 is open on the target
Installing the role also adds an inbound firewall rule, so on a default Windows Firewall setup there is nothing to open. It is still worth one look, because a group policy or a third-party firewall can override it, and a blocked port shows up on the initiator as a discovery timeout rather than a clear error:
Get-NetFirewallRule | Where-Object DisplayName -like '*iSCSI*' | Select-Object DisplayName,Direction,Enabled,Profile
Only the two target rules are enabled. The rule iSCSI Target (TCP-In) covers TCP 3260 on every profile, which mattered here because the lab network was classified as Public.
DisplayName Direction Enabled Profile
----------- --------- ------- -------
iSCSI Service (TCP-Out) Outbound False Any
iSCSI Service (TCP-In) Inbound False Any
iSCSI Target (TCP-In) Inbound True Any
iSCSI Target Service (RPC-In) Inbound True Any
Both disabled iSCSI Service rules belong to the initiator side, and they stayed disabled on bench01 for the whole test: Windows allows outbound traffic by default, so an initiator needs no rule to reach port 3260. Confirm the target is listening on its LAN address:
Get-NetTCPConnection -LocalPort 3260 -State Listen | Select-Object LocalAddress,LocalPort
WinTarget bound to the LAN address of the server rather than to every interface. That address is the portal you register on the initiators in Step 5, so note it now, because a mistyped portal fails at discovery before CHAP is ever checked.
LocalAddress LocalPort
------------ ---------
10.0.1.10 3260
If a policy has disabled that rule, the Windows Server firewall port guide covers creating and checking an inbound TCP rule with New-NetFirewallRule.
Step 3: Create the virtual disk and a target limited by IQN
A Windows iSCSI LUN is a VHDX file on the file system of the target, and a target is the access list that decides which initiators may see it. Find the initiator’s IQN first, because the target refers to it. On bench01, the Microsoft initiator builds the name from the computer name:
(Get-InitiatorPort).NodeAddress
Two lines came back on the test box. A line of zeros belongs to a second, unused initiator port, and the IQN below it is the value to copy.
0000000000000000
iqn.1991-05.com.microsoft:bench01
Back on bench-san, create a 20 GB virtual disk. The folder does not need to exist, because the cmdlet created C:\iSCSIVirtualDisks by itself in 1.51 seconds. On a real server, put the folder on a data volume rather than C:, since a full system drive stops the target and the operating system together.
New-IscsiVirtualDisk -Path C:\iSCSIVirtualDisks\bench-lun01.vhdx -SizeBytes 20GB
Without -UseFixed the disk type is Dynamic, which is why the new file took only 4 MiB on the drive of the target while reporting the full 20 GB to initiators.
Path : C:\iSCSIVirtualDisks\bench-lun01.vhdx
Size : 21474836480
Status : NotConnected
DiskType : Dynamic
Dynamic is the right default for a lab and for most file shares, since space is only used as data lands. The cost is that the file grows during writes; after formatting and about 256 MB of test writes from bench01 it stood at 644 MB. Use -UseFixed for databases and VM storage, where growth during writes adds latency you cannot control. Now create the target and allow only bench01 to see it:
New-IscsiServerTarget -TargetName bench-tgt -InitiatorIds "IQN:iqn.1991-05.com.microsoft:bench01"
Windows builds the target IQN from the server name and the target name. Copy the TargetIqn value, because the initiators connect to that exact string. Keep target names short and descriptive, since Windows embeds them in the IQN that every initiator stores.
TargetName : bench-tgt
TargetIqn : iqn.1991-05.com.microsoft:bench-san-bench-tgt-target
InitiatorIds : {Iqn:iqn.1991-05.com.microsoft:bench01}
Status : NotConnected
The -InitiatorIds parameter also accepts IPAddress:, IPv6Address:, DNSName: and MACAddress: entries, as listed in the New-IscsiServerTarget reference. We use the IQN because it survives a DHCP change and because it is what the Linux initiator in Step 8 had to match. Map the disk to the target as LUN 0:
Add-IscsiVirtualDiskTargetMapping -TargetName bench-tgt -Path C:\iSCSIVirtualDisks\bench-lun01.vhdx
Get-IscsiServerTarget -TargetName bench-tgt | Select-Object -ExpandProperty LunMappings
The second command lists the mapping, with the VHDX on LUN 0 of bench-tgt.
TargetName Path Lun
---------- ---- ---
bench-tgt C:\iSCSIVirtualDisks\bench-lun01.vhdx 0
Skipping the mapping is easy, since the Server Manager wizard does it silently, and without it the initiator logs in to an empty target with no disk behind it. With PowerShell you run it yourself for every disk you add, and an empty LunMappings list is the first thing to check when a connected initiator shows no new disk.
Step 4: Turn on CHAP for the target
An IQN list stops an unknown host from seeing the disk, but an IQN is not a secret: anyone can set their initiator name to bench01. One-way CHAP adds a user name and secret that the initiator must prove at login. The Windows target enforces a secret length of 12 to 16 characters, and we found that limit by trying a 7-character and then a 17-character secret, both of which failed with the same message:
The length of CHAP or reverse CHAP secret must be at least 12 characters, but no more than 16 characters.
Pick a 12 to 16 character secret, then set the CHAP user and enable it on the target. The user name does not have to match any Windows account; we used the initiator’s host name so the pairing is obvious in the target list:
$chap = New-Object PSCredential('bench01', (ConvertTo-SecureString 'Bench01Chap#26' -AsPlainText -Force))
Set-IscsiServerTarget -TargetName bench-tgt -EnableChap $true -Chap $chap
Get-IscsiServerTarget -TargetName bench-tgt | Format-List TargetName,EnableChap,ChapUserName,EnableReverseChap,InitiatorIds
EnableChap now reads True with the user bench01. Reverse (mutual) CHAP, where the target also proves itself to the initiator, stays off in this guide:
TargetName : bench-tgt
EnableChap : True
ChapUserName : bench01
EnableReverseChap : False
InitiatorIds : {Iqn:iqn.1991-05.com.microsoft:bench01}
CHAP takes effect immediately. Older guides restart WinTarget at this point; we did not, and both initiators logged in with CHAP straight afterwards. A restart would only drop any initiator that is already connected.
With CHAP on, the target is ready. Server Manager shows the same objects under File and Storage Services, iSCSI, and its TASKS menu holds the New iSCSI Virtual Disk wizard if you prefer to build the next one there:

We took that capture at the end of the test, so both virtual disks already show Connected with their initiator IQNs in the Initiator ID column. Yours will read Not Connected until Step 5.
Step 5: Connect the Windows iSCSI initiator with PowerShell
Windows Server ships the iSCSI Initiator, but its service (MSiSCSI) is stopped and set to manual on a fresh install. On bench01, start it and make it start at boot, otherwise the persistent connection in Step 7 has nothing to reconnect it:
Start-Service MSiSCSI
Set-Service MSiSCSI -StartupType Automatic
Register the target server as a portal. Discovery runs at this point, and the target answers with the targets that list the IQN of this initiator.
New-IscsiTargetPortal -TargetPortalAddress 10.0.1.10
Get-IscsiTarget
One target came back, not connected yet. The perf-tgt target created later for the Linux host never appears in this list, because its access list does not name bench01. An empty list at this point therefore points at the IQN on the target, not at the network.
NodeAddress IsConnected
----------- -----------
iqn.1991-05.com.microsoft:bench-san-bench-tgt-target False
Connect with one-way CHAP and -IsPersistent, which adds the target to the Favorite Targets list so Windows reconnects it at every boot. Type the authentication type in capitals: OneWayChap with the correct secret returned “Authentication Failure.” in our test, exactly like a wrong password, and the Connect-IscsiTarget reference states the value must be uppercase.
Connect-IscsiTarget -NodeAddress iqn.1991-05.com.microsoft:bench-san-bench-tgt-target -AuthenticationType ONEWAYCHAP -ChapUsername bench01 -ChapSecret 'Bench01Chap#26' -IsPersistent $true
Three fields matter in the session object: IsConnected and IsPersistent must both be True, and AuthenticationType must read ONEWAYCHAP:
AuthenticationType : ONEWAYCHAP
InitiatorInstanceName : ROOT\ISCSIPRT\0000_0
InitiatorNodeAddress : iqn.1991-05.com.microsoft:bench01
InitiatorPortalAddress : 0.0.0.0
InitiatorSideIdentifier : 400001370000
IsConnected : True
IsDataDigest : False
IsDiscovered : True
IsHeaderDigest : False
IsPersistent : True
NumberOfConnections : 1
SessionIdentifier : ffff948e85cff010-4000013700000007
TargetNodeAddress : iqn.1991-05.com.microsoft:bench-san-bench-tgt-target
TargetSideIdentifier : 0100
PSComputerName :
Step 6 makes the same connection through the iSCSI Initiator applet, so use one method or the other on a given initiator. If you connected above, skip Step 6. We tested the GUI path first, then removed that session with Get-IscsiSession | Unregister-IscsiSession and Disconnect-IscsiTarget before running the PowerShell connect, and the reboot test in Step 7 used the PowerShell session.
Step 6: Connect from the iSCSI Initiator GUI instead
Open Server Manager, Tools, iSCSI Initiator (or run iscsicpl). On a server where MSiSCSI has never been started, Windows first offers to start it and set it to start automatically. Click Yes, which does the same as the two MSiSCSI commands in Step 5:

Skip Quick Connect on a CHAP target, because it has no CHAP fields and so cannot send credentials. We registered the portal with the same PowerShell command as Step 5 and used the Connect button for the login, which is the path tested here:
- Register the portal with
New-IscsiTargetPortal -TargetPortalAddress 10.0.1.10from Step 5, which is how the target reached the GUI list in this test. - On the Targets tab, click Refresh, select the
bench-san-bench-tgt-targetentry and click Connect. - In Connect To Target, leave “Add this connection to the list of Favorite Targets” ticked and click Advanced.
Ticked by default, the Favorite Targets box is the GUI equivalent of -IsPersistent $true.

Advanced Settings is where CHAP lives. The Name field defaults to the IQN of the initiator, and that default is wrong for this target, because the target expects the CHAP user bench01.

- 1Enable CHAP log on
- 2Name
- 3Target secret
- Tick Enable CHAP log on.
- Replace the IQN in Name with the CHAP user from Step 4,
bench01. - Enter the 12 to 16 character secret in Target secret, then click OK twice.
On the Targets tab the status changes to Connected, and the Favorite Targets tab lists the target. Windows walks that list at boot to restore sessions.

In our test the GUI session matched the PowerShell one exactly, since Get-IscsiSession reported IsConnected True, IsPersistent True and AuthenticationType ONEWAYCHAP.
Step 7: Bring the iSCSI disk online and prove it survives a reboot
A new iSCSI LUN arrives offline and raw, like any new disk on Windows Server. Filter on the bus type so you do not pick the system disk by mistake:
Get-Disk | Where-Object BusType -eq iSCSI | Format-Table Number,FriendlyName,OperationalStatus,PartitionStyle,@{n='Size(GB)';e={[math]::Round($_.Size/1GB)}} -AutoSize
Disk 1 is the VHDX from the target, listed as an MSFT Virtual HD. Offline is the normal state for a new disk on Windows Server, so nothing is wrong yet, and the RAW partition style confirms the LUN is empty.
Number FriendlyName OperationalStatus PartitionStyle Size(GB)
------ ------------ ----------------- -------------- --------
1 MSFT Virtual HD Offline RAW 20
Bring it online, initialise it as GPT and format it with a fixed drive letter. Check the disk number from the previous output before running this, because Initialize-Disk on the wrong number wipes that disk:
Set-Disk -Number 1 -IsOffline $false
Initialize-Disk -Number 1 -PartitionStyle GPT
New-Partition -DiskNumber 1 -UseMaximumSize -DriveLetter S | Format-Volume -FileSystem NTFS -NewFileSystemLabel bench-lun01 -Confirm:$false
Formatting finished with a healthy volume and 19.98 GB usable out of the 20 GB LUN. From here you use S: like a local drive, and Server Manager on bench-san shows the virtual disk as Connected.
DriveLetter FileSystemLabel FileSystem HealthStatus Size(GB)
----------- --------------- ---------- ------------ --------
S bench-lun01 NTFS Healthy 19.98
To test persistence, we wrote a file to S:, restarted bench01 and checked the session, the volume and the file again after logon. The System log recorded the iSCSI session 11 seconds after the boot time, before anyone had logged on, and the file written before the restart was readable:

Drive letter S: came back as well, with no extra step. If S: is missing after a restart, check Get-IscsiSession first: an empty result means the target was not on the Favorite Targets list or MSiSCSI was not set to Automatic, the two settings this guide changed for persistence.
Step 8: Connect a Linux initiator to the same target server
A Windows target serves Linux initiators without any change on the Windows side beyond its own target entry. The Linux host gets a separate disk and target, because bench01 already owns the NTFS volume on bench-tgt. On bench-san, create a 10 GB disk and a target named perf-tgt that allows the Rocky IQN, with its own CHAP user and a 12 to 16 character secret:
New-IscsiVirtualDisk -Path C:\iSCSIVirtualDisks\perf-lun02.vhdx -SizeBytes 10GB
New-IscsiServerTarget -TargetName perf-tgt -InitiatorIds "IQN:iqn.1994-05.com.redhat:perf-a"
Add-IscsiVirtualDiskTargetMapping -TargetName perf-tgt -Path C:\iSCSIVirtualDisks\perf-lun02.vhdx
$chap2 = New-Object PSCredential('perf-a', (ConvertTo-SecureString 'PerfAChap#2026' -AsPlainText -Force))
Set-IscsiServerTarget -TargetName perf-tgt -EnableChap $true -Chap $chap2
List both targets to confirm CHAP is on and to copy the new target IQN:
Get-IscsiServerTarget | Format-Table TargetName,TargetIqn,EnableChap,Status -AutoSize
Both targets show EnableChap True. We created perf-tgt before connecting bench01, so both read NotConnected here; on your server bench-tgt will already show Connected:
TargetName TargetIqn EnableChap Status
---------- --------- ---------- ------
bench-tgt iqn.1991-05.com.microsoft:bench-san-bench-tgt-target True NotConnected
perf-tgt iqn.1991-05.com.microsoft:bench-san-perf-tgt-target True NotConnected
The target IQN follows the same pattern as before, iqn.1991-05.com.microsoft:bench-san-perf-tgt-target. On Rocky Linux 10 the initiator package is iscsi-initiator-utils. In our run, /etc/iscsi/initiatorname.iscsi did not exist until iscsid first started, and then it held a random name, which we replaced. Writing the file before the first start, as below, avoids that step, because the package’s iscsi-init unit only generates a name when the file is missing. Install the package and set a readable name that matches the access list of the target:
sudo dnf -y install iscsi-initiator-utils
echo "InitiatorName=iqn.1994-05.com.redhat:perf-a" | sudo tee /etc/iscsi/initiatorname.iscsi
sudo systemctl restart iscsid
Discover the targets, store the CHAP values on the node record, and log in. Setting CHAP per node with iscsiadm -o update keeps it out of the global /etc/iscsi/iscsid.conf, so another target on a different array is not affected. The password must be the exact secret set on perf-tgt above:
sudo iscsiadm -m discovery -t sendtargets -p 10.0.1.10
sudo iscsiadm -m node -T iqn.1991-05.com.microsoft:bench-san-perf-tgt-target -p 10.0.1.10 -o update -n node.session.auth.authmethod -v CHAP
sudo iscsiadm -m node -T iqn.1991-05.com.microsoft:bench-san-perf-tgt-target -p 10.0.1.10 -o update -n node.session.auth.username -v perf-a
sudo iscsiadm -m node -T iqn.1991-05.com.microsoft:bench-san-perf-tgt-target -p 10.0.1.10 -o update -n node.session.auth.password -v 'PerfAChap#2026'
sudo iscsiadm -m node -T iqn.1991-05.com.microsoft:bench-san-perf-tgt-target -p 10.0.1.10 --login
Discovery listed only perf-tgt, and the login succeeded. The bench-tgt target stayed hidden from perf-a, so the Linux host could never mount the NTFS volume that bench01 is writing to.
10.0.1.10:3260,1 iqn.1991-05.com.microsoft:bench-san-perf-tgt-target
Login to [iface: default, target: iqn.1991-05.com.microsoft:bench-san-perf-tgt-target, portal: 10.0.1.10,3260] successful.
The LUN shows up as a SCSI disk with the iscsi transport. Confirm it with lsblk -S:
lsblk -S -o NAME,SIZE,TRAN,VENDOR,MODEL
On perf-a the Windows VHDX is sdb, vendor MSFT. Read the TRAN column rather than the size, because the local disk and the LUN are both 10 GB here and only the iSCSI one shows iscsi.
NAME SIZE TRAN VENDOR MODEL
sda 10G QEMU QEMU HARDDISK
sdb 10G iscsi MSFT Virtual HD
sr0 4M sata QEMU QEMU DVD-ROM
New node records default to node.startup = automatic on Rocky, and after sudo systemctl reboot the session was back within the first minute of uptime with no extra unit to enable. A 512 MiB direct write of random data to the raw LUN ran at 41.7 MB/s, and a direct read at 363 MB/s. The target and this initiator sat on the same ZFS-backed Proxmox node, so treat those numbers as a lab baseline, not a NIC benchmark. For a setup with no Windows box at all, the Rocky Linux iSCSI target and initiator guide builds the target on Linux too, and the KVM iSCSI storage pool guide shows the same LUN feeding virtual machines.
Fix iSCSI login and CHAP errors
Every error below was produced on purpose in the lab, with the exact text each side printed. The Windows initiator also writes event ID 10 from source iScsiPrt to the System log at each failed login (“Login request failed. The login response packet is given in the dump data.”), which is the quickest place to confirm a failure happened at login rather than at discovery.
Connect-IscsiTarget: “Authentication Failure.” (HRESULT 0xefff0009)
Windows gives no other message for a rejected login, and in our tests three different mistakes produced it.
- No CHAP on the initiator:
Connect-IscsiTargetwithout-AuthenticationTypesends no credentials to a target that requires them. - Wrong secret or user: the secret must match the target character for character, and the GUI Name field must hold the CHAP user, not the default IQN.
- Mixed-case authentication type:
-AuthenticationType OneWayChapfailed with the correct secret;ONEWAYCHAPworked.
Check them in that order. If all three are right, run Get-IscsiServerTarget on the target and compare ChapUserName with what the initiator sends.
Set-IscsiServerTarget: “The length of CHAP or reverse CHAP secret must be at least 12 characters”
Windows rejects any secret shorter than 12 or longer than 16 characters, with error code 80070018. A 7-character and a 17-character secret both failed in the lab, and a 14-character one was accepted. The same limit applies to the reverse CHAP secret.
iscsiadm: No portals found
Discovery from perf-a returned this with exit code 21 while its IQN was not on the access list of any target. A Windows target answers discovery only with targets that name the asking initiator, so an empty answer usually means an IQN mismatch rather than a network fault. Compare /etc/iscsi/initiatorname.iscsi with the InitiatorIds of the target, and restart iscsid after editing the file.
iscsiadm: “iSCSI login failed due to authorization failure” (error 24)
Discovery worked but the login failed, because CHAP was enabled on perf-tgt and the node record had no credentials yet:
iscsiadm: Could not login to [iface: default, target: iqn.1991-05.com.microsoft:bench-san-perf-tgt-target, portal: 10.0.1.10,3260].
iscsiadm: initiator reported error (24 - iSCSI login failed due to authorization failure)
iscsiadm: Could not log into all portals
Set the three node.session.auth values from Step 8 and log in again. A wrong password produces the same error, so check the user name and secret on both sides.
New-IscsiVirtualDisk: “A virtual disk with that file path already exists.”
Running the create command a second time with the same path fails with code 80070050. The target already tracks that VHDX, so map the existing disk with Add-IscsiVirtualDiskTargetMapping instead of creating it again. A VHDX copied in from another server is brought under the target’s control with Import-IscsiVirtualDisk.
With the target and initiators working, the usual next step is shared storage for a cluster, and the Windows Server failover clustering guide builds on exactly this kind of LUN. For a wider reference on the server roles around it, see our list of Windows Server administration books.