A have an nginx reverse proxy behind ldap authentication.
I can read username in php from variable $_SERVER['PHP_AUTH_USER']. I think this means that username is passed from ldap to nginx and than to php.
Is it possible in nginx configuration to allow access to a folder only to a list of users?
UPDATE
In nginx the user is stored in $remote_user variable. Is it possible to compare $remote_user with a list of users stored in a file? And then deny or allow access to a folder?
UPDATE
Probably I have to use map directive, for example:
map $remote_user $allowed_user {
default 0;
user1 1;
user2 1;
}
and then test it in the appropriate location:
location /folder/ {
if($allowed_user != 1){
return 403;
}
proxy_pass http://site;
}
but when I do sudo nginx -t, I receive the following error:
nginx: [emerg] unknown directive "if($allowed_user" in /etc/nginx/nginx.conf:104
nginx: configuration file /etc/nginx/nginx.conf test failed
You can do it via map directive (please note that map translate definitions block should be placed in the http context outside the server block):
map $remote_user $deny
username1 0;
username2 0;
...
usernameN 0;
default 1;
}
server {
...
location /folder/ {
if ($deny) { return 403; }
...
}
}
You can pre-generate users list in the above form (username1 0; username 2 0; ...) and then include this list to the nginx configuration:
map $remote_user $deny {
include /path/userlist.txt;
default 1;
}
Whenever this user list file get changed you'd need to reload nginx configuration (nginx -s reload).
Structure of my nextcloud instance
/apps
/apps2
/myapp
/img
icon.svg
I'm looking for a solution to generate a full URL to the icon from a path relative to myapp.
I've injected initial state but should be a better solution
https://docs.nextcloud.com/server/18/developer_manual/app/view/js.html#loading-initial-state
$eventDispatcher->addListener(
'OCA\Files::loadAdditionalScripts', function () {
script('projects', 'filelist_plugin');
style('projects', 'filelist');
/* #var IInitialStateService $state */
$state = $this->getContainer()->query(IInitialStateService::class);
$state->provideInitialState('projects', 'project-icon', image_path('projects', 'folder.svg'));
}
);
I have "Server: Apache" in my HTTP response headers and want to remove it.
I followed instructions like adding this to httpd.conf:
ServerSignature Off
ServerTokens Prod
Header unset Server
But the last line has no effect. First two lines have changed header's content (earlier it contained also information about OS and PHP), but I need to remove it completely.
How to do this?
Apache don't allow you to unset this completely. In fact some of the developers are vehemently against adding this despite it being a simple code change that's been suggested (and even written!) several times. See here and here for just some of the discussions where this has been brought up and rejected.
They give various reasons for this, including:
It might make it more difficult to count the number of Apache installs in the wild. This is, I suspect, the main reason. Web server usage is fiercely contested and one of Apache's rivals (which may or may not begin with an N) regularly posts how it is gaining ground on Apache and most scans will be based on the HTTP Header, so I can understand this reluctance to make it easier to hide this.
Security by obscurity is a myth, and gives a false sense of security as it's easy to fingerprint a server to see which software it likely is, based on how it responds to certain requests. While there is an inkling of truth in that, specifying ServerTokens as Full by default definitely is a security issue leaking far too much information than should be shown by default on a public website.
It may or may not be against the HTTP spec to not supply a server header. This seems to be in some disputes and still doesn't answer why they don't allow you to change it to some random string rather than Apache.
It makes it difficult to debug issues, but you'd think anyone needing to debug would know, or be able to find out, the exact versions.
Proxy servers "might" handle requests differently if they know the server type at the other end. Which is wrong of proxy servers IMHO and I doubt it's done much anymore.
If people really want to amend or hide this header they can edit the source code. Which is, quite frankly, a dangerous recommendation to advise people with no experience of the code to do and could lead to other security issues if they run from a non-packaged version just to add this.
They even goes as far as adding this in the official documentation:
Setting ServerTokens to less than minimal is not recommended because
it makes it more difficult to debug interoperational problems. Also
note that disabling the Server: header does nothing at all to make
your server more secure. The idea of "security through obscurity" is a
myth and leads to a false sense of safety.
That reasoning is, IMHO, ridiculous and, as I say, if that's the main reason to not allow it then I don't see why they don't change their stance. At worse case it doesn't add anything as they say and it stops this whole question being raised every so often though personally I think the less unnecessary information you give out, the better so would prefer to be able to turn this off.
Until that unlikely u-turn, you're left with:
Setting it minimal (so it will show "Apache") - which is probably good enough
Editing the source code - which is overkill except for the most paranoid, and means the same change needs to be applied on each new version.
Installing ModSecurity - which (at least used to) allow you to overwrite (but not remove) this header to whatever you wanted to hide the server software. Probably overkill to install this just for that, though there are other benefits to a WAF.
Proxy Apache behind another web server which allows you to change this field.
Switch to another web server.
It should be noted however, for points 4 and 5, that most other web servers don't allow you to turn this off either so this is not a problem unique to Apache. For example Nginx doesn't allow this to be turned off without similarly editing the source code.
Header retrieval
To get the headers, this seems to work adequately if on the server (all tests done on Ubuntu 14.04 Trusty Tahr):
curl -v http://localhost:80/ | head
which produces something like:
< HTTP/1.1 200 OK
< Date: Mon, 25 Jan 2021 09:17:51 GMT
* Server Apache/2.4.7 (Ubuntu) is not blacklisted
< Server: Apache/2.4.7 (Ubuntu)
Removing the version number
To remove the version number, edit the file /etc/apache2/conf-enabled/security.conf and amend the lines:
ServerTokens OS to ServerTokens Prod
ServerSignature On to ServerSignature Off
and restart Apache:
sudo service apache2 restart
You should now get the a response like:
< HTTP/1.1 200 OK
< Date: Mon, 25 Jan 2021 09:20:03 GMT
* Server Apache is not blacklisted
< Server: Apache
Removing the word "Apache"
To remove the word Apache completely, first install ModSecurity:
sudo apt-get install libapache2-mod-security2
The following lines appear to not be required (enabling the module and restarting Apache) but for reference:
sudo a2enmod security2
sudo service apache2 restart
Check that the module is enabled:
apachectl -M | grep security
which should show:
security2_module (shared)
Then although you can amend /etc/modsecurity/modsecurity.conf (by renaming modsecurity.conf-recommended), instead amend /etc/apache2/apache.conf which seems easier (note you can use whatever name you want, in this case I've simply used a space):
<IfModule security2_module>
SecRuleEngine on
ServerTokens Min
SecServerSignature " "
</IfModule>
(Using Min rather than Full also prevents modules such as mod_fastcgi appearing after the blank server name.)
Then restart Apache:
sudo service apache2 restart
Final check
Now when you run the command:
curl -v http://localhost:80/ | head
you should get:
< HTTP/1.1 200 OK
< Date: Mon, 25 Jan 2021 09:31:11 GMT
* Server is not blacklisted
< Server:
I AM NOT RESPONSIBLE FOR ANYTHING CAUSED!MAKE SURE YOU FOLLOW THE LICENSE FILE INCLUDED WITH IT!THE FOLLOWING CURRENTLY WORKS FOR APACHE VERSION 2.4.46:
To remove the Server: header completely:
Download the Apache source from https://httpd.apache.org, extract it, and edit it.
Edit the file httpd-2.4.46/server/core.c, and change the following lines:
enum server_token_type {
SrvTk_MAJOR, /* eg: Apache/2 */
SrvTk_MINOR, /* eg. Apache/2.0 */
SrvTk_MINIMAL, /* eg: Apache/2.0.41 */
SrvTk_OS, /* eg: Apache/2.0.41 (UNIX) */
SrvTk_FULL, /* eg: Apache/2.0.41 (UNIX) PHP/4.2.2 FooBar/1.2b */
SrvTk_PRODUCT_ONLY /* eg: Apache */
};
TO:
enum server_token_type {
SrvTk_MAJOR, /* eg: Apache/2 */
SrvTk_MINOR, /* eg. Apache/2.0 */
SrvTk_MINIMAL, /* eg: Apache/2.0.41 */
SrvTk_OS, /* eg: Apache/2.0.41 (UNIX) */
SrvTk_FULL, /* eg: Apache/2.0.41 (UNIX) PHP/4.2.2 FooBar/1.2b */
SrvTk_PRODUCT_ONLY, /* eg: Apache */
SrvTk_NONE /* removes Server: header */
};
Change this other line:
if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
}
else if (ap_server_tokens == SrvTk_MINIMAL) {
ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
}
else if (ap_server_tokens == SrvTk_MINOR) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MINORREVISION);
}
else if (ap_server_tokens == SrvTk_MAJOR) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MAJORVERSION);
}
else {
ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
}
TO:
if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
}
else if (ap_server_tokens == SrvTk_MINIMAL) {
ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
}
else if (ap_server_tokens == SrvTk_MINOR) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MINORREVISION);
}
else if (ap_server_tokens == SrvTk_MAJOR) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MAJORVERSION);
}
else if (ap_server_tokens == SrvTk_NONE) {
ap_add_version_component(pconf, "");
}
else {
ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
}
And change this:
if (!strcasecmp(arg, "OS")) {
ap_server_tokens = SrvTk_OS;
}
else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal")) {
ap_server_tokens = SrvTk_MINIMAL;
}
else if (!strcasecmp(arg, "Major")) {
ap_server_tokens = SrvTk_MAJOR;
}
else if (!strcasecmp(arg, "Minor") ) {
ap_server_tokens = SrvTk_MINOR;
}
else if (!strcasecmp(arg, "Prod") || !strcasecmp(arg, "ProductOnly")) {
ap_server_tokens = SrvTk_PRODUCT_ONLY;
}
else if (!strcasecmp(arg, "Full")) {
ap_server_tokens = SrvTk_FULL;
}
else {
return "ServerTokens takes 1 argument: 'Prod(uctOnly)', 'Major', 'Minor', 'Min(imal)', 'OS', or 'Full'";
}
TO:
if (!strcasecmp(arg, "OS")) {
ap_server_tokens = SrvTk_OS;
}
else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal")) {
ap_server_tokens = SrvTk_MINIMAL;
}
else if (!strcasecmp(arg, "Major")) {
ap_server_tokens = SrvTk_MAJOR;
}
else if (!strcasecmp(arg, "Minor") ) {
ap_server_tokens = SrvTk_MINOR;
}
else if (!strcasecmp(arg, "Prod") || !strcasecmp(arg, "ProductOnly")) {
ap_server_tokens = SrvTk_PRODUCT_ONLY;
}
else if (!strcasecmp(arg, "Full")) {
ap_server_tokens = SrvTk_FULL;
}
else if (!strcasecmp(arg, "None")) {
ap_server_tokens = SrvTk_NONE;
}
else {
return "ServerTokens takes 1 argument: 'Prod(uctOnly)', 'Major', 'Minor', 'Min(imal)', 'OS', 'Full' or 'None'";
}
Compile Apache from the source you have modified. See: http://httpd.apache.org/docs/current/install.html
Set the following in httpd.conf:
ServerSignature Off
ServerTokens None
OR:
Download the Apache source from https://httpd.apache.org, extract it, and edit it.
Edit the file httpd-2.4.46/server/core.c, and change the following:
if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
}
else if (ap_server_tokens == SrvTk_MINIMAL) {
ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
}
else if (ap_server_tokens == SrvTk_MINOR) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MINORREVISION);
}
else if (ap_server_tokens == SrvTk_MAJOR) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MAJORVERSION);
}
else {
ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
}
TO:
if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT);
}
else if (ap_server_tokens == SrvTk_MINIMAL) {
ap_add_version_component(pconf, AP_SERVER_BASEVERSION);
}
else if (ap_server_tokens == SrvTk_MINOR) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MINORREVISION);
}
else if (ap_server_tokens == SrvTk_MAJOR) {
ap_add_version_component(pconf, AP_SERVER_BASEPRODUCT "/" AP_SERVER_MAJORVERSION);
}
else {
ap_add_version_component(pconf, AP_SERVER_BASEVERSION " (" PLATFORM ")");
}
ap_add_version_component(pconf, "");
So, if you change your mind, you could just set ServerTokens to Prod or something else... And the header will be back. Change to None again, it is gone :)
I know this is a late answer. But, still it can help a lot!
This aproach:
Header always set "Server" "Generic Web Server"
Only works for 2XX responses. If you have a rewrite rule with a redirection, it's ignored and returns the value set by ServerTokens option.
Finally I've modified the variable it's defining product name in include/ap_release.h. More simple and it can be done with a single sed:
sed 's/AP_SERVER_BASEPRODUCT\ "Apache"/AP_SERVER_BASEPRODUCT\ "Generic Web Server"/' include/ap_release.h
If the need is simply hide the information regarding which web-server is running, you can try to add the following row in the configuration file:
Header set "Server" "Generic Web Server".
You probably haven't enabled mod_headers.
Check if it's enabled:
root#host: a2query -m headers
If mod headersis enabled output should be something like headers (enabled by ...).
If it's not enabled activate the module by using:
a2enmod headers
I am trying to write a sample Apache module to read config file whose file path is specified in httpd.conf like that:
<Location ~ /(?!.*\.(png|jpeg|jpg|gif|bmp|tif)$)>
SetInputFilter SAMPLE_INPUT_FILTER
SetOutputFilter SAMPLE_OUTPUT_FILTER
ConfigFilePath "/etc/httpd/conf.d/sample/sample.config"
</Location>
At command record structure, I do:
static const command_rec config_check_cmds[] =
{
AP_INIT_TAKE1( "ConfigFilePath", read_config_file, NULL, OR_ALL, "sample config"),
{ NULL }
};
I also set:
module AP_MODULE_DECLARE_DATA SAMPLE_module = {
STANDARD20_MODULE_STUFF,
create_dir_config, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
NULL, /* create per-server config structures */
NULL, /* merge per-server config structures */
config_check_cmds, /* table of config file commands */
sample_register_hooks /* register hooks */
};
I could read config file path successfully. And now I want to check that if "ConfigFilePath" is not specified in httpd.conf, It will show error at console when I use "service httpd restart"
How could I do that?
You'd register a ap_hook_post_config hook and do the verification of required settings there. Be aware that that hook is called twice as documented in the answer here: Init modules in apache2
See an example post config hook implementation here: http://svn.apache.org/repos/asf/httpd/httpd/tags/2.3.0/modules/examples/mod_example_hooks.c
I want to write a test cgi program in C++. But when I set the configuration file as follow:
ScriptAlias /cgi-bin/ "F:/workbench/cgi-bin/"
<Directory "F:/workbench/cgi-bin">
AllowOverride None
Options ExecCGI
Order allow,deny
Allow from all
</Directory>
AddHandler cgi-script .exe .pl .cgi
then write a helloworld program as follows:
#include <stdio.h>
int main(void)
{
printf("\n");
printf("Hello, World!\n");
return 0;
}
and compile it with g++ hello.cpp -o hello.cgi
when I restart the server and visit the cgi: localhost\cgi-bin\hello.cgi
it didn't work.
You need to add an HTTP header to describe the output. The Http Header and Http body are separated by two new-line chars. I think your code will work if you include a simple header like "content-type: text/plain". In other words, try with:
#include <stdio.h>
int main(void) {
printf("Content-type: text/plain\n");
printf("\n");
printf("Hello, World!\n");
return 0;
}