UCE currently only allows you to scope filter policy branches based on Boolean combinations of Connection IP, Client IP, Location, User Name and User Groups. This is nice, but what if clients are using IP based authentication through a shared IP like a child proxy? The child proxy could insert headers indicating the original client IP or user name. How can I use the headers for policy application? This article shows how to next hop proxy to UCE from MWG and add headers.
Solved! Go to Solution.
Updated 4/9/21 with much more efficient policy code
Prerequisite: IP based authentication must be configured in UCE for the public egress IPs that will be used by the child proxy.
Policy code modification is currently required. To keep the modification to a minimum I would suggest the following procedure for using X-Forwarded-For header matched against a list of ranges. (The concept could be extrapolated to use any header to set User Name or Groups.) At a high level here are the steps
1) Create range lists that will be checked against the XFF address to apply specific policies
2) Create string lists to specify groups you will add by default and for a match to a given list
3) Create a new branch at the top of the policy and insert policy code to set User Name and Groups based on range list matches
4) Use those groups and or User Names in your scoping for the policy rule branches.
5) (optional) If you want a match to a given branch to terminate the top level branch rather than executing the remaining branches in the branch edit the policy code to change the end statements to reference the top level rule branch name.
Here are the details:
1) Create range lists for use in mapping users and groups:
From MVISION Cloud Management Console go to Policy > Web Policy > List Catalog > IP Range and select Add New List from the menu (*** to the right of the IP Range list type)
Give the list a descriptive name and enter the relevant IPs that you want to apply a special policy to (in this example XFF IPs that are in 192.168.11.0/24 will be matched for the purposes of setting user name and optionally user groups that will be used in policy scoping.
Repeat for as many sets of IPs that you want to match policy for. Save and Publiish.
2) Create string lists to specify groups you will add
From MVISION Cloud Management Console go to Policy > Web Policy > List Catalog > String and select Add New List from the menu (*** to the right of the String list type)
Create a list of groups you want to add if the user isn't already authenticated and either XFF doesn't match in your range lists or there is no XFF.
Repeat for as many sets of Groups that you want to add for a specific range list match. I've also added a default group set (XFF Default Groups) that I will always apply if XFF is present. Save and Publish
3) Create a new policy branch and modify policy code:
From MVISION Cloud Management Console go to Policy >Web Policy > Policy > Getting Started > Advanced Editing in Code View and in the lower right hand corner of the screen click on "here".
Edit the code to add an INCLUDE statement to the list of INCLUDES near the bottom of the code. Place the statement before global bypass with the name of your new branch.
Save and publish then activate Code View for the newly created branch.
Edit the first line of code to give yourself an activate button, operate on web request only and customize the branch name if desired.
ROUTINE Set_Default_Username_and_Groups ON (Web.Request) [enabled="true"] { // Set Default Username and Groups
Add the policy code by inserting your modified version of the code after the first line and before the routine end signified by } (replace items in red to match list names and user name strings):
-------------------Code to insert----------------------------
// Initialize variables
VECTOR<STRING> Usergroups
STRING Username
VECTOR<Net.IP> xffIPs
Net.IP xffIP
STRING xffheader
// If Username is empty set default username and default groups
IF MWG.Username == "" THEN {
Username = "No_Auth"
Usergroups = list_NoAuthDefaultGroups
// Set Users and Groups from XFF headers
// Only execute if X-Forwarded-For exists
IF MWG.Request.Headers.HasHeader("X-Forwarded-For") THEN {
// Get XFF Header
xffheader = MWG.Request.Headers.Get("X-Forwarded-For")
// Convert XFF header to a string of IPs (UCE adds ", <Connection IP>")
xffIPs = Net.ToIPList(Split(xffheader,", "))
// If User Name is default
IF Username == "No_Auth" THEN {
// Set a default User Name string
Username = "XFF_No_IP_Match"
// Set default User Groups when XFF used
Usergroups = list_XFFDefaultGroups
}
// Loop through the IPs to set User Name and Groups on match of IP to range list
FOR xffIP IN xffIPs DO {
IF Net.IsInRangeList(xffIP, XFFPolicy1) THEN {
Username = "XFF_User_1"
Usergroups = Join(Usergroups, listXFFGroups1)
}
IF Net.IsInRangeList(xffIP, XFFPolicy2) THEN {
Username = "XFF_User_2"
Usergroups = Join(Usergroups, listXFFGroups2)
}
IF Net.IsInRangeList(xffIP, XFFPolicy3) THEN {
Username = "XFF_User_3"
Usergroups = Join(Usergroups, listXFFGroups3)
}
}
}
MWG.SetUserName (Username)
MWG.SetUserGroups(Usergroups)
}
-------------------END Code to insert------------------------
If you need to find the names for your lists. Go to Policy >Web Policy > Policy > Getting Started > Advanced Editing in Code View and in the lower right hand corner of the screen click on here. Your list names will be in red and are the given names without the spaces prefixed by "list_".
The code above will append groups for each policy IPRange match. This is fine if your range lists don't overlap but might not be the desired operation if they do overlap. Alternate operation is possible by modifying the code. If you only want groups from the first match you would add an END statement within each conditional. If you wanted only the last policy match group set you could simply replace the for loop in each conditional with MWG.SetUserGroups(<grouplistname>).
4) Use those groups and or User Names in your scoping for the policy rule branches.
Now that we have the username and groups set from the headers, they can easily be applied for scoping of any policy rules through the standard UI.
Here is scoping a Global Bypass branch based on user name matching in a list:
For user names that don't match in the list this branch would apply
Here is scoping Web Filtering based on User Groups matching in a list
You could obviously do the inverse not in list as above was done for user names.
Note that each remaining branch in the same filter will still run if the scoping matches for the respective branch. See step 5 if you don't want this operation.
5) (Optional) Terminate top level branch (filter)
What if you don't want remaining branches of a filter to execute even if their scoping matches?
You have to dive back into policy code to do this but it is fairly simple. I will use my global bypass filter set as an example. First you need to get the name of the top level filter.
Open code view for the top level filter and note the name:
Insert the statement END(<top level name>) before the last } in code view
Save and Publish
And here is the full example code for also looking at X-Authenticated-User and X-Authenticated Groups to get missing group and user names from a child proxy....
Also updated 9/8/21 to reflect better performance implementation
// Initialize variables
VECTOR<STRING> Usergroups
STRING Username
VECTOR<Net.IP> xffIPs
Net.IP xffIP
STRING xffheader
// If MWG.Username is empty set default username and default groups
IF MWG.Username == "" THEN {
Username = "No_Auth"
Usergroups = list_NoAuthDefaultGroups
}
// Set Users and Groups from X-Authenticated headers
// Only execute if X-Authenticated-User exists
IF MWG.Request.Headers.HasHeader("X-Authenticated-User") THEN {
// Set Username from XAU Header
Username = MWG.Request.Headers.Get("X-Authenticated-User")
// Remove XAU Headers
MWG.Request.Headers.Remove("X-Authenticated-User")
// Set default User Groups when XAU used
Usergroups = list_XAUDefaultGroups
// Only execute if X-Authenticated-Groups exists
IF MWG.Request.Headers.HasHeader("X-Authenticated-Groups") THEN {
// Set groups from header
Usergroups = (Split(MWG.Request.Headers.Get("X-Authenticated-Groups"),","))
// Remove XAG Headers
MWG.Request.Headers.Remove("X-Authenticated-Groups")
}
}
// Set Users and Groups from XFF headers if Username not set
// Only execute if X-Forwarded-For exists
IF MWG.Request.Headers.HasHeader("X-Forwarded-For") THEN {
// Get XFF Header
xffheader = MWG.Request.Headers.Get("X-Forwarded-For")
// Convert XFF header to a vector of IPs (UCE adds ", <Connection IP>")
xffIPs = Net.ToIPList(Split(xffheader,", "))
// If User Name is default
IF Username == "No_Auth" THEN {
// Set a default User Name string
Username = "XFF_No_IP_Match"
// Set default User Groups when XFF used
Usergroups = list_XFFDefaultGroups
// Loop through the IPs to set User Name and Groups on match of IP to range list
FOR xffIP IN xffIPs DO {
IF Net.IsInRangeList(xffIP, list_XFFPolicy1) THEN {
Username = "XFF_User_1"
Usergroups = Join(Usergroups, list_XFFGroups1)
}
IF Net.IsInRangeList(xffIP, list_XFFPolicy2) THEN {
Username = "XFF_User_2"
Usergroups = Join(Usergroups, list_XFFGroups2)
}
IF Net.IsInRangeList(xffIP, list_XFFPolicy3) THEN {
Username = "XFF_User_3"
Usergroups = Join(Usergroups, list_XFFGroups3)
}
}
}
}
IF MWG.Username == "" THEN {
MWG.SetUserName(Username)
MWG.SetUserGroups(Usergroups)
}
One additional note. When using UCE an XFF Header will always be present. UCE will add an XFF header if there is none. The header will be a string containing the Connection IP. If there is already an XFF header, the Connection IP will be appended. For example if the client connects from public address 1.2.3.4 and the header received by UCE contains "X-Forwarded-For: 10.0.0.10", when the policy code is hit the X-Forwarded-For header will have been modified to "X-Forwarded-For: 10.0.0.10, 1.2.3.4"
Updated 4/9/21 with much more efficient policy code
Prerequisite: IP based authentication must be configured in UCE for the public egress IPs that will be used by the child proxy.
Policy code modification is currently required. To keep the modification to a minimum I would suggest the following procedure for using X-Forwarded-For header matched against a list of ranges. (The concept could be extrapolated to use any header to set User Name or Groups.) At a high level here are the steps
1) Create range lists that will be checked against the XFF address to apply specific policies
2) Create string lists to specify groups you will add by default and for a match to a given list
3) Create a new branch at the top of the policy and insert policy code to set User Name and Groups based on range list matches
4) Use those groups and or User Names in your scoping for the policy rule branches.
5) (optional) If you want a match to a given branch to terminate the top level branch rather than executing the remaining branches in the branch edit the policy code to change the end statements to reference the top level rule branch name.
Here are the details:
1) Create range lists for use in mapping users and groups:
From MVISION Cloud Management Console go to Policy > Web Policy > List Catalog > IP Range and select Add New List from the menu (*** to the right of the IP Range list type)
Give the list a descriptive name and enter the relevant IPs that you want to apply a special policy to (in this example XFF IPs that are in 192.168.11.0/24 will be matched for the purposes of setting user name and optionally user groups that will be used in policy scoping.
Repeat for as many sets of IPs that you want to match policy for. Save and Publiish.
2) Create string lists to specify groups you will add
From MVISION Cloud Management Console go to Policy > Web Policy > List Catalog > String and select Add New List from the menu (*** to the right of the String list type)
Create a list of groups you want to add if the user isn't already authenticated and either XFF doesn't match in your range lists or there is no XFF.
Repeat for as many sets of Groups that you want to add for a specific range list match. I've also added a default group set (XFF Default Groups) that I will always apply if XFF is present. Save and Publish
3) Create a new policy branch and modify policy code:
From MVISION Cloud Management Console go to Policy >Web Policy > Policy > Getting Started > Advanced Editing in Code View and in the lower right hand corner of the screen click on "here".
Edit the code to add an INCLUDE statement to the list of INCLUDES near the bottom of the code. Place the statement before global bypass with the name of your new branch.
Save and publish then activate Code View for the newly created branch.
Edit the first line of code to give yourself an activate button, operate on web request only and customize the branch name if desired.
ROUTINE Set_Default_Username_and_Groups ON (Web.Request) [enabled="true"] { // Set Default Username and Groups
Add the policy code by inserting your modified version of the code after the first line and before the routine end signified by } (replace items in red to match list names and user name strings):
-------------------Code to insert----------------------------
// Initialize variables
VECTOR<STRING> Usergroups
STRING Username
VECTOR<Net.IP> xffIPs
Net.IP xffIP
STRING xffheader
// If Username is empty set default username and default groups
IF MWG.Username == "" THEN {
Username = "No_Auth"
Usergroups = list_NoAuthDefaultGroups
// Set Users and Groups from XFF headers
// Only execute if X-Forwarded-For exists
IF MWG.Request.Headers.HasHeader("X-Forwarded-For") THEN {
// Get XFF Header
xffheader = MWG.Request.Headers.Get("X-Forwarded-For")
// Convert XFF header to a string of IPs (UCE adds ", <Connection IP>")
xffIPs = Net.ToIPList(Split(xffheader,", "))
// If User Name is default
IF Username == "No_Auth" THEN {
// Set a default User Name string
Username = "XFF_No_IP_Match"
// Set default User Groups when XFF used
Usergroups = list_XFFDefaultGroups
}
// Loop through the IPs to set User Name and Groups on match of IP to range list
FOR xffIP IN xffIPs DO {
IF Net.IsInRangeList(xffIP, XFFPolicy1) THEN {
Username = "XFF_User_1"
Usergroups = Join(Usergroups, listXFFGroups1)
}
IF Net.IsInRangeList(xffIP, XFFPolicy2) THEN {
Username = "XFF_User_2"
Usergroups = Join(Usergroups, listXFFGroups2)
}
IF Net.IsInRangeList(xffIP, XFFPolicy3) THEN {
Username = "XFF_User_3"
Usergroups = Join(Usergroups, listXFFGroups3)
}
}
}
MWG.SetUserName (Username)
MWG.SetUserGroups(Usergroups)
}
-------------------END Code to insert------------------------
If you need to find the names for your lists. Go to Policy >Web Policy > Policy > Getting Started > Advanced Editing in Code View and in the lower right hand corner of the screen click on here. Your list names will be in red and are the given names without the spaces prefixed by "list_".
The code above will append groups for each policy IPRange match. This is fine if your range lists don't overlap but might not be the desired operation if they do overlap. Alternate operation is possible by modifying the code. If you only want groups from the first match you would add an END statement within each conditional. If you wanted only the last policy match group set you could simply replace the for loop in each conditional with MWG.SetUserGroups(<grouplistname>).
4) Use those groups and or User Names in your scoping for the policy rule branches.
Now that we have the username and groups set from the headers, they can easily be applied for scoping of any policy rules through the standard UI.
Here is scoping a Global Bypass branch based on user name matching in a list:
For user names that don't match in the list this branch would apply
Here is scoping Web Filtering based on User Groups matching in a list
You could obviously do the inverse not in list as above was done for user names.
Note that each remaining branch in the same filter will still run if the scoping matches for the respective branch. See step 5 if you don't want this operation.
5) (Optional) Terminate top level branch (filter)
What if you don't want remaining branches of a filter to execute even if their scoping matches?
You have to dive back into policy code to do this but it is fairly simple. I will use my global bypass filter set as an example. First you need to get the name of the top level filter.
Open code view for the top level filter and note the name:
Insert the statement END(<top level name>) before the last } in code view
Save and Publish
And here is the full example code for also looking at X-Authenticated-User and X-Authenticated Groups to get missing group and user names from a child proxy....
Also updated 9/8/21 to reflect better performance implementation
// Initialize variables
VECTOR<STRING> Usergroups
STRING Username
VECTOR<Net.IP> xffIPs
Net.IP xffIP
STRING xffheader
// If MWG.Username is empty set default username and default groups
IF MWG.Username == "" THEN {
Username = "No_Auth"
Usergroups = list_NoAuthDefaultGroups
}
// Set Users and Groups from X-Authenticated headers
// Only execute if X-Authenticated-User exists
IF MWG.Request.Headers.HasHeader("X-Authenticated-User") THEN {
// Set Username from XAU Header
Username = MWG.Request.Headers.Get("X-Authenticated-User")
// Remove XAU Headers
MWG.Request.Headers.Remove("X-Authenticated-User")
// Set default User Groups when XAU used
Usergroups = list_XAUDefaultGroups
// Only execute if X-Authenticated-Groups exists
IF MWG.Request.Headers.HasHeader("X-Authenticated-Groups") THEN {
// Set groups from header
Usergroups = (Split(MWG.Request.Headers.Get("X-Authenticated-Groups"),","))
// Remove XAG Headers
MWG.Request.Headers.Remove("X-Authenticated-Groups")
}
}
// Set Users and Groups from XFF headers if Username not set
// Only execute if X-Forwarded-For exists
IF MWG.Request.Headers.HasHeader("X-Forwarded-For") THEN {
// Get XFF Header
xffheader = MWG.Request.Headers.Get("X-Forwarded-For")
// Convert XFF header to a vector of IPs (UCE adds ", <Connection IP>")
xffIPs = Net.ToIPList(Split(xffheader,", "))
// If User Name is default
IF Username == "No_Auth" THEN {
// Set a default User Name string
Username = "XFF_No_IP_Match"
// Set default User Groups when XFF used
Usergroups = list_XFFDefaultGroups
// Loop through the IPs to set User Name and Groups on match of IP to range list
FOR xffIP IN xffIPs DO {
IF Net.IsInRangeList(xffIP, list_XFFPolicy1) THEN {
Username = "XFF_User_1"
Usergroups = Join(Usergroups, list_XFFGroups1)
}
IF Net.IsInRangeList(xffIP, list_XFFPolicy2) THEN {
Username = "XFF_User_2"
Usergroups = Join(Usergroups, list_XFFGroups2)
}
IF Net.IsInRangeList(xffIP, list_XFFPolicy3) THEN {
Username = "XFF_User_3"
Usergroups = Join(Usergroups, list_XFFGroups3)
}
}
}
}
IF MWG.Username == "" THEN {
MWG.SetUserName(Username)
MWG.SetUserGroups(Usergroups)
}
One additional note. When using UCE an XFF Header will always be present. UCE will add an XFF header if there is none. The header will be a string containing the Connection IP. If there is already an XFF header, the Connection IP will be appended. For example if the client connects from public address 1.2.3.4 and the header received by UCE contains "X-Forwarded-For: 10.0.0.10", when the policy code is hit the X-Forwarded-For header will have been modified to "X-Forwarded-For: 10.0.0.10, 1.2.3.4"
New to the forums or need help finding your way around the forums? There's a whole hub of community resources to help you.
Thousands of customers use our Community for peer-to-peer and expert product support. Enjoy these benefits with a free membership: