Hi Sander,
I have mixed news for you. I can't achieve what you want with a ULA (bad news), but I can achieve it with another GUA.
Note: I tested with Windows 7 - Linux may yield different results.
Here's my default prefix policy table in Windows 7 (Microsoft's implementation of RFC 3484):
Precedence Label Prefix
---------- ----- --------------------------------
50 0 ::1/128
40 1 ::/0
30 2 2002::/16
20 3 ::/96
10 4 ::ffff:0:0/96
5 5 2001::/32
I have a ULA address and a GUA:
2001:470:c4e8:1::/64
fd01:0:0:1::/64 (illegally created address for example purposes only)
If I alter my prefix policy table like this it doesn't work:
Precedence Label Prefix
---------- ----- --------------------------------
70 6 fd01:0:0:1::/64
60 6 2001:470:c4e8:2::/64
50 0 ::1/128
40 1 ::/0
30 2 2002::/16
20 3 ::/96
10 4 ::ffff:0:0/96
5 5 2001::/32
However, if I add a different GUA - 2004:1:2:3::/64 and add that to the prefix policy table:
Precedence Label Prefix
---------- ----- --------------------------------
80 6 2004:1:2:3::/64
70 6 fd01:0:0:1::/64
60 6 2001:470:c4e8:2::/64
50 0 ::1/128
40 1 ::/0
30 2 2002::/16
20 3 ::/96
10 4 ::ffff:0:0/96
5 5 2001::/32
This works as you desire - when I access something with a prefix of 2001:470:c4e8:2::/64 (destination) Windows uses an address with the prefix 2004:1:2:3::/64 (source). For any other IPv6 prefix (destination) it uses 2001:470:c4e8:2::/64 (source).
This makes me suspect at least in Windows that ULA addresses aren't treated as having the same scope. From looking at the 3484 rules:
Destination Address Selection - N/A, we have chosen the destination address.
Source Address Selection:
(N/A) 1. Prefer the same address - If the a source address = the destination address, prefer it
(Susp) 2. Prefer appropriate scope - Use the address with the same/closest scope
(N/A) 3. Avoid deprecated addresses - Prefer "preferred" addresses
(N/A) 4. For Mobile IP Addresses (...)
(Poss) 5. Prefer outgoing interface - Use the interface that will be chosen give the destination
(Yes) 6. Prefer matching label - If a source address has a matching label (from the policy table) to the destination address, prefer it
7. Prefer public addresses - Prefer public addresses over temporary addresses (there should be a way to reverse this too)
8. Use the longest matching prefix - Starting from the left most bit, prefer the address that has the most bits in common with the destination address
So I suspect what's happening with my Windows box is ULAs aren't making it past step 2. In other words, Windows doesn't treat ULA as having the same scope as GUAs. However, I freely admit that this is conjecture on my part. In Linux you have the advantage of being able to look through the source code...
Where it is working I'm hitting Rule 6 - I set the destination and source prefixes/addresses to have the same label number (6 in the example above).
I also mention rule 5 because if you can use two interfaces on the server in your case and can put the ULA on one and the GUA on the other then I believe you can solve your issue with routing which will use rule 5 in your favor.
Sorry this isn't exactly what you wanted but hope it helps,
--Jim