In vcl_synth I am trying to craft modified error pages; I may move this to vcl_backend_error, but that is moot as the problem remains the same. I am using CentOS 7, so only have access to 4.0, not 4.1. This is important as std.file_exists only exists in >= 4.1. It is unacceptable to use packages from untrusted, untested, sources that break forwards/backwards compatibility.
To handle issues where the 503.html file may not exist I would like to test the synthetic output, and if null/empty generate a fallback error page. For debugging I'm throwing all output to syslog; this will not persist to production, in its current form.
Sample:
sub vcl_synth {
if (resp.status == 503) {
set resp.http.Content-Type = "text/html; charset=utf-8";
synthetic(std.fileread("/var/www/vhost/" + req.http.host + "/error/503.html"));
std.syslog(3, "resp.http.body: " + resp.http.body);
return (deliver);
}
}
With the above I clearly see that resp.http.body is empty, but the page is returned and renders in my browser. So, if it does, which variable does synthetic set? And, can it be tested?
# journalctl -f
...
Sep 08 02:17:17 REDACTED_HOSTNAME varnishd[32498]: resp.http.body:
pls halp
Execution of synthetic(...) during vcl_synth does not populate resp.http.body. That's just a random header name. One possible approach would be to populate a 'temporary variable' with the response body:
sub vcl_synth {
if (resp.status == 503) {
set resp.http.Content-Type = "text/html; charset=utf-8";
set req.http.X-Synth-Body = std.fileread("/var/www/vhost/" + req.http.host + "/error/503.html");
synthetic(req.http.X-Synth-Body);
std.syslog(3, "req.http.X-Synth-Body: " + req.http.X-Synth-Body);
return (deliver);
}
}
Regarding the:
It is unacceptable to use packages from untrusted, untested, sources
that break forwards/backwards compatibility.
Varnish has a dedicated repository for 4.1.
Those packages are signed, specific to 4.1 branch only and should not break forward/backward compatibility.
Plus, since you're using their software you essentially already trust them. Moreover, there are recent security updates that might make it faster to their repository and not the EPEL, etc.
And Varnish 4.0 is officially EOL.
Related
I'm using Varnish version 4. I'd like to know if VCL allows a custom and reusable list of values like ACL. I want to use it to check against visitors' cookies. If he is a moderator, don't serve cached content.
Cookie String:
session=9urt2jipvkq77brfrf; UserID=158
Code:
acl moderator{
"158";
"114";
}
sub vcl_recv {
set req.http.UserID = regsub(req.http.Cookie,".*UserID=(\d+).*","\1"); // 158
if(req.http.UserID ~ moderator){ // 158 found in the moderator list
return(pass);
}
}
Short answer: no
ACL (access control list) is only used for specifying different IPs/hosts.
However you can use a VMOD to accomplish this. Checkout Variable
It has some basic functions for setting and getting variables.
set("my_var", "this is the value")
set req.http.x-my-var = get("my_var")
There is also some more advanced functions, like setting multiple variables from a single string using regex.
variable.regset("ttl:d=\1s,grace:d=\2s", "^(?:.*,)?max-age=([0-9]+)(?:+([0-9]+))", beresp.http.Surrogate-Control);
set beresp.ttl = variable.get_duration("ttl");
set beresp.grace = variable.get_duration("grace");
ttl is the name of the variable, grace is the name of the second variable
\1 & \2 are simple back-references to the regex
:d specifies the type, in this case duration
Your list of user id:s
You could just set them in a comma separated string
set("moderators", ",158,114,") //Notice the starting and ending comma-sign
if(","+req.http.UserID+"," ~ get("moderators")){
return(pass);
}
I am configuring Freeradius. Input message is Access-Request with Proxy-State = 3134
Freeradius succesfully performs authentication but he places Proxy-State at the bottom of Access-Accept. How can I canfigure that Freeradius places Framed-IP-Address at the bottom of the message?
It tried to configure "users" as:
381603854966 Auth-Type := Accept, User-Password == "123456"
Service-Type = Framed-User,
Framed-Protocol = PPP,
Framed-IP-Netmask = 255.255.255.0,
User-Name = 381603854966,
Framed-IP-Address = 10.10.40.22,
but without success - freeradius still puts Proxy-State and the bottom of Access-Accept. I also tried to configure policy.txt file like:
if (User-Name == "381603854966") {
reply .= {
Framed-IP-Address += "10.10.40.22"
}
}
I also tried this in policy.txt:
reply .= {
Framed-IP-Address = 10.10.40.22
}
didn't work. Anybody knows how can I place certain attribute at the bottom of the message?
Thank you, Mark
You can't. The server will add Proxy-State to the request before forwarding it upstream, and it'll always add it at the end of the list of attributes.
RFC 2865 section 5 states:
If multiple Attributes with the same Type are present, the order of
Attributes with the same Type MUST be preserved by any proxies. The
order of Attributes of different Types is not required to be
preserved. A RADIUS server or client MUST NOT have any dependencies
on the order of attributes of different types. A RADIUS server or
client MUST NOT require attributes of the same type to be contiguous.
If your application requires ordering of attributes of different types, it's not implementing the RADIUS protocol correctly and should be fixed.
I want to get the current states of sqlite pragma using Qt's QSqlQuery.
But I do not get a result for some values from the program but from sqlite console.
Qt version 5.2.1, Sqlite version 3.8.4.3, Windows 7, Ubuntu 12.4 LTS
Output:
application_id = "0"
auto_vacuum = "0"
automatic_index = "1"
busy_timeout = "5000"
cache_size = "2000"
cache_spill = [NoResult]
case_sensitive_like = [NoResult]
void MySqliteInfo::PrintState(QString state)
{
printf("%s = ", state.toStdString().c_str());
QSqlQuery query(*m_db);
query.prepare(QString("PRAGMA %1").arg(state));
query.exec();
if(0 == query.size()) {
printf("%s returns nothing\n", state.toStdString().c_str());
}
else {
if(query.next()) {
QVariant value = query.value(0);
if(value.canConvert(QMetaType::QString)) {
printf("\"%s\"\n", value.toString().toStdString().c_str());
}
else {
printf("[UnknownDataType]\n");
}
}
else {
printf("[NoResult]\n");
}
}
query.finish();
}
PrintState("application_id");
PrintState("auto_vacuum");
PrintState("automatic_index");
PrintState("busy_timeout");
PrintState("cache_size");
PrintState("cache_spill");
PrintState("case_sensitive_like");
The SQLite version that you are actually using in your Qt program does not yet implement PRAGMA cache_spill.
SQLite just ignores any PRAGMA it does not recognize.
As documented, PRAGMA case_sensitive_like does not allow reading the current value.
First of all, the query.size() test ist useless, since it returns -1 for every value. query.size() can only be used with SELECT queries.
Now [NoResult] can have two different meanings:
A pragma value does not exist
A pragma value is Not Set
In an example database created from another program, I observe the first case for cache_spill and the second case for case_sensitive_like. You might want to check the values using sqliteman on Ubuntu.
I found the solution tt least for cache_spill:
The used sqlite3.exe supports pragma cache_spill but not the sqlite version comes with Qt 5.2. (3.7.17).
Qt 5.3 comes with Sqlite 3.8.4.3 - the git repro says this.
I was trying out MonoTouch/MonoAndroid and everything was going
well until I called IsolatedStorageFile.GetFileNames(string) function. The
parameter was "Foo/Foo1/*". The result is SecurityException with no message.
The directory "Foo/Foo1" exists, because it has just been found using IsolatedStorageFile.GetDirectoryNames() call.
I identified this bit in Mono sources that throws the exception (in IsolatedStorageFile.cs):
DirectoryInfo[] subdirs = directory.GetDirectories (path);
// we're looking for a single result, identical to path (no pattern here)
// we're also looking for something under the current path (not
outside isolated storage)
if ((subdirs.Length == 1) && (subdirs [0].Name == path) && (subdirs[0].FullName.IndexOf(directory.FullName) >= 0)) {
afi = subdirs [0].GetFiles (pattern);
} else {
// CAS, even in FullTrust, normally enforce IsolatedStorage
throw new SecurityException ();
}
I can't step into it with the debugger so I don't know why the
condition is false. This happens both on iOS and Android. There was a
similar issue logged long time ago at
http://www.digipedia.pl/usenet/thread/12492/1724/#post1724, but there
are no replies.
The same code works on Windows Phone 7 without problems (with \ for path separators).
Has anyone got any ideas what might be causing it? Is it the uppercase in
directory names a problem?
It is a bug in Mono. IsolatedStorage will not work with paths that contain more than one directory in a row (such as Foo/Foo1/*)
I copied the code of GetFileNames() method from Mono to my project so that I can debug it. I found out that the problem is in the 2nd term of this condition (IsolatedStorageFile.cs:846):
if ((subdirs.Length == 1) && (subdirs [0].Name == path) &&(subdirs[0].FullName.IndexOf(directory.FullName) >= 0)) {
afi = subdirs [0].GetFiles (pattern);
} else {
// CAS, even in FullTrust, normally enforce IsolatedStorage
throw new SecurityException ();
}
For example when path passed to GetFileNames() is "Foo/Bar/*", subdirs[0].Name will be "Bar" while path will be "Foo/Bar" and the condition will fail causing the exception.
I am trying to work around a backend server that will from time to time start serving up blank pages with a 200 OK response, by having Varnish continue to serve old cached versions of these pages (aka. grace mode).
First I tried inspecting the response in vcl_fetch, but as far as I have been able to figure out, there is no way to figure out the content length in vcl_fetch. Then I attempted to do the work in vcl_deliver (where the Content-Length header is available). That does work, but I can't figure out how to expunge the bad cached object (the one with the blank page), so that seems to be a no-go.
I was advised to set obj.grace and obj.ttl in vcl_deliver, and this is my current code:
sub vcl_deliver {
# If the front page is blank, invalidate this cached object, in hope
# that we'll get a new one.
if (req.url == "/" && std.integer(resp.http.content-length, 0) < 1000) {
set obj.grace = 0m;
set obj.ttl = 0m;
return(restart);
}
}
However, Varnish doesn't like that, and gives me this error when I try to load the VCL:
Message from VCC-compiler:
'obj.grace': cannot be set in method 'vcl_deliver'.
At: ('input' Line 146 Pos 9)
set obj.grace = 0m;
--------#########------
I get the same error for obj.ttl if I remove the obj.grace line – neither seems to be writable in vcl_deliver, even though the docs say otherwise. This is on Varnish 3.0.2.
What i did is check the Content-Length for 0 and 20 in sub_vcl_fech and restart when this happens
if (beresp.http.Content-Length == "0" || beresp.http.Content-Length == "20"){
return(restart);
}
content length of 20 is what my server returned when an error occurs.
in the sub vcl_recv i added a check on amount of restarts maximum of 2
if(req.restarts == 2){
error 500 req.http.host;
}
Option 2
another option i got from the varnish documentation.
https://www.varnish-cache.org/docs/3.0/tutorial/handling_misbehaving_servers.html
Throw error in the vcl_fetch like: error 751 req.http.host;
add magic marker in the vcl_error.
add return(restart); in the vcl_error
check for magic marker set in vcl_recv or vcl_fetch
Doing this in vcl_deliver is too late. This sub is called right before sending content to the client and obj should not be available anymore (only 'resp' which doesn't contain any ttl or grace parameter).
Did you try doing this in vcl_fetch ? You won't need to call 'restart' but directly 'hit_for_pass'.
Anyway, (not sure about that) I don't think grace mode can be used depending on response content since it's supposed to be triggered when you can't get any content update (backend failure). Maybe it could work by changing backend to a "zombie" one and restarting request but for sure, once you're in vcl_fetch, a response is...fetched, and grace mode won't trigger.