Jump to content
Welcome to our new Citrix community!

Error binding a responder policy to an LB vServer

Ross Helfand

Recommended Posts

Hey all!


I'm trying to do what I think is a simple allowlist (I got the idea from this page), but getting an error:


>add policy patset patset_test

>bind policy patset patset_test_allowed ""

>add responder action respondwith403 respondwith "\"HTTP/1.1 403 Forbidden\r\n\r\n\""

>add policy expression polexp_test_allowed "(CLIENT.IP.SRC + \"/32\").EQUALS_ANY(\"patset_test_allowed\") || (CLIENT.IP.SRC.SUBNET(31) + \"/31\").EQUALS_ANY(\"patset_test_allowed\")"

>add responder policy policy_test_allowed polexp_test_allowed.NOT respondwith403

>bind lb vserver my_lbvs -policyName policy_test_allowed -priority 90 -gotoPriorityExpression END -type REQUEST
ERROR: Policy action must be DROP|RESET

I think I can figure out a way around this, but I'd love to understand why it doesn't work?


Link to comment
Share on other sites

One thing I can't tell from above is the protocol of your vserver?

  • Is your lb vserver type HTTP/SSL or some other protocol?
  • RespondWith (in this example) can only bind to WEB content and not a TCP or ANY vserver.

That is most likely the reason for your issue here.



I then looked at your policy action and expression to see if anything else was going on. Just some minor comments in case it is useful


1) minor issue in above commands you create patternset "patset_test" but all the commands reference "patset_test_allowed". (Minor so I just adjusted it in the test commands.)

2) minor cli issue regarding the 403 header format. The literal Header in the GUI needs to actually say. (Note letters in [brackets] are so I refer to specific examples. Not part of the syntax.  Technically, what you have works BUT you won't see the carriage return\new line as char references and instead it would be interpreted in gui and the cli when you look back at it.

[a] "HTTP/1.1 403 Forbidden\r\n\r\n"

When this is converted to commandline the literal \r\n needs to be literalized. If you enter "\r\n\r\n" in cli without escaping the characters, you'll end up with actual interpeted string:

[b] "HTTP/1.1


"  ##<< expression line return ends here...

Which isn't what we want.  


To enter 

"HTTP/1.1 403 Forbiddent\r\n\r\n" in cli as a literal string, you need to escape it, more as:



add responder action respondwith403_fixed_ex1 respondwith q{"HTTP/1.1 403 Forbidden\r\n\r\n"}

## The q{<stuff>} is a quoting mechanism for complex expressions.


add responder action respondwith403_fixed_ex2 respondwith "\"HTTP/1.1 403 Forbidden\\r\\n\\r\\n\""

## When entering "\" in the cli, even within double quotes, the singe backslash must entered as a double backslash "\\" so that it is stored as a singular backslash.


Compare entering both in the CLI with the view you get in the GUI.

Also try configuring the GUI with the literal string:  "HTTP/1.1 403 Forbidden\r\n\r\n"

And see how it displays in the runningconfig afterwards.


This is again a MINOR issue as it will still be interpreted as a 403 error in a browser, but the latter two are more likely what you were trying to encode.

With error message body content it would be with body content something like this.  The body content is also terminated by a double carriage return/newline combo: \r\n\r\n. In GUI you can enter it like so; in cli you may want to escape the characters for future editability.

"HTTP/1.1 403 Forbidden\r\n\r\n" + "403 Forbidden: You don’t have permission to access this resource on this server\r\n\r\n"


3) The BINDING issue.

Confirmed a RespondWith action is a WEB Response so it can only bind to lb/cs vservers of type SSL or HTTP and not resources that are using non-web protocoles like TCP/DNS/ANY.



4) Your actual filter expression for whitelisting or backlisting subnets.

Whether you use a named expression or an inline expression doesn't matter.   But your expression itself looked weird until I realized what you are doing. It should work but depending on the number of subnets/networks involved, there might be easier ways to do this (and their might not).  


If you want to see an alternate way to compare source IPs to individual IPs or subnets, this thread has several examples too:  https://discussions.citrix.com/topic/409145-netscaler-policy-assistance/page/2/.

Depending on how long the list or how finite, might affect which method is most efficient for you to maintain. This is one of those there really is more than one way to do it scenarios.


What your doing should work with parsing the "/xx" subnet mask in the string, But it might be easier to split to two pattern sets, one for individual IPs (/32) and one with specific subnet masks OR convert to the subnets and look for IPs with the subnet operator instead of the In_Subnet operator.    IF there is a LARGE number of IPs and subnets and they change often, you might be better off using a callout and letting an external system make the evaluation decision.


This is just because the in_subnet(<IP>/<netmask>) operator doesn't have an _any  variant, so you can't easily search on IPs in the x.x.x.x/nn  subnet notation easily.  Its not impossible, but its awkward.  Your method agove should work, but see if the variant example makes it easier or not.


If you made two patternsets, one for /32 addresses and one for /31 netmasks and just put the network without the cider notation, you could easily write an expression like:

client.ip.src.equals_any("ps_ip32_whitelist) || client.ip.src.subnet(31).equals_any("ps_network31_whitelest)

The network31 whitelist would just be the networks with the netmask applied:  x.x.x.y  and not the slash notation.


However, if this isn't convenient the expression you build should work.

NOTE: Compound named expressions cannot be edited after creation, so build them inline unless you think the length will exceed the advanced engine OR

Use a named expressions for small sections so you can still edit down the road.


So, to drop anything not on whitelist:

You need the logic to be:

!(A || B || C ...)   Where A, B, C are clauses representing allowed ip/networks.

And that part of your logic is working.  So no problems there.

  • Like 1
Link to comment
Share on other sites

Rhonda, you're the best!  My lb_vserver is of type SSL_BRIDGE.


The "minor issue 1)" listed above was me trying to be slick in copy/pasting.  That is just an error on my part.


Thanks very much for all of the suggestions.  I'm going to read the other thread you linked.




Link to comment
Share on other sites

  • 1 month later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Create New...