Skip to content

Export-DbaLinkedServer not exposing passwords if DAC is blocked for remote connections #10549

Description

@edbmfo

Summarize Functionality

Export-DbaLinkedServer over the network does not expose passwords if DAC is not enabled for remote access.
This (DAC for remote access) should not be needed as shown in the technical details below.

My question is, can the current code be changed so that Export-DbaLinkedServer here does not need port 1434
to be open in the same way, or is the current situation intended.

Is there a command that is similiar or close to what you are looking for?

Yes

Technical Details

On version 2.7.20 of dbatools there was an issue where
Export-DbaLinkedServerdid not expose passwords for SQL servers in clusters since
the the DAC connection might be be busy since DAC might be available on multiple ipadresses.

A possible fix was discussed here where the Get-DecryptedObject.ps1 could be changed to
access 127.0.0.1 instead of $sourceName, making sure only that connection/ip was used.

This was the issue I commented on regarding DAC and Export-DbaLinkedServer:
#10040

I tested this my self on a dbatools clone from 2.7.2.0, and it worked perfectly.

Now that code did not end up in the public dbatools on its own; as several changes were
introduced, multiple rewrites of a lot of code. I could not follow the trail,
the refactiroing was done in multiple stages and i just waited it out and tried each released
version to check if this functionality worked for me.

It never did. So I kept on using my local fixed version for this functionality.

Current version 2.8.4 still does not work.

I've narrowed it down in that that code fails if DAC connection is not available
over the network - as in, if port 1434 is blocked, it fails, if port 1434 is open, it works as expected.

On that version 2.7.20 with the changed Get-DecryptedObject.ps1 to use 127.0.0.1 instead of $sourcename,
it still works without exposing 1434 over the network.

My understanding was and still is that the DAC portion was happening through psremoting, effectively
running locally on the sql server and so 127.0.0.1 was fine.

My question is, can the current code be changed so that export-dblink here does not need port 1434
to be open in the same way, or is the current situation intended.

Regards,
Marco

Activity

  1. andreasjordan commented on Aug 11, 2026

    @andreasjordan
    Collaborator

    Thanks for the detailed write-up, Marco — your analysis is correct, and I can show exactly where the behaviour changed.

    Your 127.0.0.1 fix did land: PR #10106 on 2026-01-25, commit a0d6a67f8, credited to you. It was removed on 2026-02-19 by PR #10174, "Part 2 of refactoring of Get-DecryptedObject" (1a510a12d), which deleted the whole Invoke-Command2 block that opened the DAC on the SQL Server host.

    Your understanding of the mechanism is also right. Before that refactor, Get-DecryptedObject opened the DAC inside the PowerShell remoting session on the SQL Server itself, connecting to ADMIN:127.0.0.1\<instance>. That is a local DAC, which needs neither remote admin connections nor a reachable DAC port. Today the calling command opens the DAC from your machine (Connect-DbaInstance -DedicatedAdminConnection) and passes it in, which is a remote DAC and needs both.

    Why it changed. The old design opened and closed a DAC per command, from inside a WinRM session. SQL Server allows exactly one DAC at a time, and that combination produced a steady stream of failures — your own #10040 among them, plus #9921 and, more recently, #10475 where Sync-DbaAvailabilityGroup was opening three DACs for one operation. The strategy we settled on is: open one DAC as early as possible and share it across all the commands that need it. Local-DAC-over-WinRM was also a recurring source of trouble in its own right. So the current situation is a deliberate trade — a stricter network prerequisite in exchange for DAC handling that behaves predictably.

    That means the honest answer to "can this be changed?" is: technically yes, but it isn't a change we'd make on a single request. Reintroducing a second DAC path costs us reliability in the area we just spent several releases stabilising, and reliability with fewer moving parts is worth more here than the extra flexibility.

    So this is a question for contributors rather than something to just implement:

    Should a remote DAC be a documented, fixed prerequisite for the password-decrypting commands, with this issue resolved by documentation only?

    That would mean stating plainly in the help for Export-DbaLinkedServer, Export-DbaCredential, Copy-DbaLinkedServer, Copy-DbaCredential and Copy-DbaDbMail (and by extension Export-DbaInstance, Start-DbaMigration and Sync-DbaAvailabilityGroup) that exporting or copying passwords requires:

    • sp_configure 'remote admin connections', 1 on the source instance
    • the DAC port reachable from the client — TCP 1434 for a default instance, a dynamic port published via SQL Browser for a named one
    • PowerShell remoting to the host, which is already required for reading the service master key

    None of that is documented today; Export-DbaLinkedServer only mentions "accesses the local registry", which is why this came as a surprise.

    Marco, in the meantime there's a third option beyond your two that needs no firewall change: run the export inside a remoting session on the SQL Server itself, where the DAC is local. Your patched copy obviously also stays valid.

    Views welcome — particularly from anyone running dbatools against instances where opening the DAC port isn't an option.


    This comment was written by Claude and reviewed by Andreas Jordan.

  2. edbmfo commented on Aug 12, 2026

    @edbmfo
    Author

    Thanks for your response and time used .

    views welcome

    Well I am biased and would prefer remote DAC implemented. One open port less might be trivial, but its one port less

    I understand though that if that may introduce those recurring
    troubles again that the maintainers prefer to just update documentation/requirements.

    I'll just await yours and others decision on it.

    Marco

  3. andreasjordan commented on Aug 26, 2026

    @andreasjordan
    Collaborator

    @potatoqualitee the linked PR is still in review because we need your decision:

    • Only changing the documentation with the linked PR and closing this issue
    • Changing the documentation with the linked PR but still working on solution via code
    • Closing the linked PR and only working on a solution via code

    I personally prefer the first.

  4. andreasjordan commented on Sep 12, 2026

    @andreasjordan
    Collaborator

    The documentation PR #10551 is now out of draft and up for review. It describes what the commands need today, which stays correct whichever way the code question here is decided, so the two no longer wait on each other. Whether Get-DecryptedObject should regain a local DAC path over remoting remains open on this issue.

    created by Claude and reviewed by Andreas Jordan

  5. potatoqualitee commented on Sep 26, 2026

    @potatoqualitee
    Member

    @andreasjordan can we control this using configs? that way if it's needed, first it can be detected and proposed to the user. or alternatively, have two paths and use that one only when needed. it's extra code but it seems like a common scenario.

  6. andreasjordan commented on Sep 26, 2026

    @andreasjordan
    Collaborator

    I'll have a look later.

  7. andreasjordan commented on Oct 5, 2026

    @andreasjordan
    Collaborator

    @potatoqualitee I had a look. Here is what the lab shows and what I propose.

    Lab results

    • When the commands cannot open the DAC, today's warning is only Failure | An existing connection was forcibly closed by the remote host. (Export-DbaLinkedServer and Export-DbaCredential, reproduced by holding the DAC in another session). Nothing tells the user that a DAC is needed, what it requires, or that -ExcludePassword exists.
    • A local DAC opened inside a PowerShell remoting session on the SQL Server host still works: ADMIN:127.0.0.1\<instance> and ADMIN:localhost\<instance> both connect and can read master.sys.syslnklgns.
    • On a failover cluster instance the loopback address does not work (ADMIN:127.0.0.1 fails with SNI error 42), but ADMIN:<virtual name> from the node that owns the instance does.

    Proposal

    1. A configuration with two values:

      • Remote (default): today's behaviour. The command opens the DAC from the client and shares it.
      • Local: the command does not open a DAC. Get-DecryptedObject runs the two password queries inside the PowerShell remoting call it already makes to unprotect the service master key, over a local DAC on the host. That is one remoting round trip, and the decryption stays on the client.

      Working name commands.passworddecryption.dac, happy to take a better one.

    2. Detect and propose: when the remote DAC cannot be opened, the warning says that the DAC is needed for the passwords, lists the prerequisites and offers both ways out: -ExcludePassword, or setting the configuration to Local.

    With Remote as the default nothing changes for anyone who does not opt in, and whoever opts in gets exactly one DAC path. That keeps the predictable DAC handling we gained with #10174.

    A third value Auto (try remote, fall back to local) could be added later. I would leave it out of this change: in Start-DbaMigration and Sync-DbaAvailabilityGroup each child command would retry the remote DAC and wait for its connection timeout before falling back, and that needs a design of its own.

    Limits of the Local path (these would go into the help)

    • Inside the remoting session the connection uses Windows authentication as the remoting identity (-Credential or the current user), not -SqlCredential. That identity must be sysadmin.
    • On a failover cluster instance, remote admin connections must still be enabled, because the DAC is reached via the virtual name, not the loopback address. Unlike the code before Part 2 of refactoring of Get-DecryptedObject #10174, dbatools would not switch that setting on and off by itself, it would tell the user instead.
    • Before implementing I will still test remote admin connections = 0 on a standalone instance, and a named instance with SQL Browser stopped.

    Two questions

    1. Is Remote the right default?
    2. Invoke-DbaDbDecryptObject also needs a DAC, but it opens its own and does not use Get-DecryptedObject, so it would not get the Local path from this change. Should it follow the same configuration, in this change or later, or stay as it is?

    If that works for you, I would implement it as one PR covering the configuration, the Local path and the better warning in all eight commands that decrypt passwords.


    This text was created by Claude and reviewed by Andreas Jordan.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

featuretriage requiredNew issue that has not been reviewed by maintainers

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions