IIS7 Block request to asp.net app using external IP - asp.net

I have a asp.net app (IIS7), and I want block access to it using external server IP. I only want to allow access using my domain.
For example, my domain is domain.com and IP 161.0.0.1 and I want to block the access to http://161.0.0.1/webapp/
I prefer do it using web.config
Thx in advance,

In IIS you configure exactly what IP / DNS name combination you want the site to respond to. You can easily force it to only respond on a particular IP.
For IIS 7:
Open the Internet Information Services (IIS) Manager
Expand Sites and right click on your website.
Click on Edit Bindings.
Edit the existing entry and set the IP address to 161.0.0.1. Also set the domain name to domain.com.
Click OK, the Click Close.
Now your site wil only respond to that particular domain name and won't respond via IP address only.
If your site uses an SSL certificate then see the following question which talks about how to configure IIS to force the hostname to be used:
https://serverfault.com/questions/96810/iis7-cant-set-host-name-on-site-with-ssl-cert-and-port-443
which links to:
http://www.sslshopper.com/article-ssl-host-headers-in-iis-7.html
This link is even better for doing it entirely through the UI: http://blog.armgasys.com/?p=80

OK so if you want the Site to be accessible via DNS name but not via IP, the only way to distinguish that is to examine the requested host name in the header. There are two ways to do that I know of:
1) Configure Bindings dialog in IIS Manager. This is the easiest to set up but doesn't work for HTTPS. Just put www.domain.com into the hostname field and requests to the IP will be rejected. For HTTPS if your security certificate is for a specific hostname, the user will get a security warning if they try to connect via IP, but typically they can override the warning (depending on browser settings).
Edit: Chris Lively has linked to a way to make this method work for HTTPS bindings as well, see his answer for more information.
2) Alternately you can examine the header in code. Here is an example of an IHttpModule which accomplishes what you want. It is also a drop-in solution that is configured in web.config.
Code:
Public Class HostNameCheck
Implements IHttpModule
Public Sub Dispose() Implements System.Web.IHttpModule.Dispose
End Sub
Public Sub Init(context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
AddHandler context.BeginRequest, AddressOf context_BeginRequest
End Sub
Private Sub context_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)
Dim objApp As HttpApplication = DirectCast(sender, HttpApplication)
If objApp.Request.Url.Host <> ConfigurationManager.AppSettings("AcceptedHostName") Then
objApp.Response.Clear()
objApp.Response.StatusCode = 403
objApp.Response.SubStatusCode = 6
objApp.Response.Flush()
End If
End Sub
End Class
Web.config:
<configuration>
<appSettings>
<add key="AcceptedHostName" value="www.domain.com"/>
</appSettings>
<system.webServer>
<modules>
<add name="HostNameCheck" type="HostNameCheck"/>
</modules>
</system.webServer>
</configuration>

Related

problem using Active Directory LDAPS authentication with ASP .NET Membership

I’m using asp.net framework 4.8
I’m trying to use the membership class with Active directory provider.
security team insists to use LDAPS protocol with ca certificate, so I set the config in this way:
web.config
<connectionStrings>
<add name="ADService" connectionString="LDAPS://ipaddress:636/OU=ou,DC=dc,DC=dc"/> (censored)
</connectionStrings>
<system.web>
<membership defaultProvider="AspNetActiveDirectoryMembershipProvider">
<providers>
<add name="AspNetActiveDirectoryMembershipProvider"
type="System.Web.Security.ActiveDirectoryMembershipProvider"
connectionStringName="ADService"
connectionUsername="MYUSERNAME"
connectionPassword="MYPASSWORD "
connectionProtection="Secure"/>
</providers>
</membership>
</system.web>
When I try to use Membership.GetUser() I get the following exception:
{"Error HRESULT E_FAIL has been returned from a call to a COM
component. (C:\Projects\ \project\web.config line 83)"}
I tired to do the steps in:
Error HRESULT E_FAIL has been returned from a call to a COM component VS2012 when debugging
I was able to connect to the active directory using LDAP browser but no through my code.
When I try to connect to another active directory on my local domain, which is not secured (LDAP on port 389) it does work.
any suggestions?
LDAP over SSL follows all the same rules as HTTP over SSL (HTTPS). The two most important parts are:
The domain name you use to connect must match one of the domains names on the certificate.
The SSL certificate must be issued by an entity that your computer trusts, and
Rule #1 means that you cannot use an IP address to connect, which it seems you are trying to do. You must use a domain name. That might be your only problem.
For rule #2, you can check the certificate by downloading it to your computer using this PowerShell script:
$webRequest = [Net.WebRequest]::Create("https://example.com:636")
try { $webRequest.GetResponse() } catch {}
$cert = $webRequest.ServicePoint.Certificate
$bytes = $cert.Export([Security.Cryptography.X509Certificates.X509ContentType]::Cert)
set-content -value $bytes -encoding byte -path "certificate.cer"
Change example.com to your domain name (you can actually use the IP address here since it's just downloading the cert, not evaluating whether it will be trusted). After running it, you will have a certificate.cer file that you can double-click on and inspect. It will tell you obviously whether the certificate is not trusted. If that's the case, you will have to install the root certificate as a Trusted Root Certificate on your computer.
To help with rule #1, you can also look at all the domains listed in the certificate by looking at the Details tab and looking at "Subject Alternative Name" in the list. There may only be one, but there might be more. If there are more than one, just make sure you use on that DNS resolves to the right IP address.

Error when call google map static api in asp.net web application:The remote name could not be resolved:'maps.googleapis.com'

I used google map static api to get map image, but I got an error "The remote name could not be resolved:'maps.googleapis.com'" when executing using (HttpWebResponse response = request.GetResponse() as HttpWebResponse).
But I can got image of google map in windows application(same code with web application), I don't know what happened
This thing is happen due to proxy setting in your system.Please add this code in your web.config file and it will work.
<system.net>
<defaultProxy enabled="true" useDefaultCredentials="true">
</defaultProxy>
</system.net>
The problem can go from invalid url (hostname) to your firewall or proxy blocking the request or even misconfigured host file or DNS.
I also faced same issue.
If you are connected with local area network and protected by Proxy server then Go in google chrome settings.
Our system takes default settings from google chrome.
In settings of chrome, go in proxy settings.Click on Lan setting.Click on proxy setting checkbox and click as well on by pass proxy server for local addresses.Also fill details of your proxy server in textbox.
Go in advance and in exceptions field type localhost.Run project again.It will work.

Stopping cookies being set from a domain (aka "cookieless domain") to increase site performance

I was reading in Google's documentation about improving site speed. One of their recommendations is serving static content (images, css, js, etc.) from a "cookieless domain":
Static content, such as images, JS and
CSS files, don't need to be
accompanied by cookies, as there is
no user interaction with these
resources. You can decrease request
latency by serving static resources
from a domain that doesn't serve
cookies.
Google then says that the best way to do this is to buy a new domain and set it to point to your current one:
To reserve a cookieless domain for
serving static content, register a new
domain name and configure your DNS
database with a CNAME record that
points the new domain to your existing
domain A record. Configure your web
server to serve static resources from
the new domain, and do not allow any
cookies to be set anywhere on this
domain. In your web pages, reference
the domain name in the URLs for the
static resources.
This is pretty straight forward stuff, except for the bit where it says to "configure your web server to serve static resources from the new domain, and do not allow any cookies to be set anywhere on this domain". From what I've read, there's no setting in IIS that allows you to say "serve static resources", so how do I prevent ASP.NET from setting cookies on this new domain?
At present, even if I'm just requesting a .jpg from the new domain, it sets a cookie on my browser, even though our application's cookies are set to our old domain. For example, ASP.NET sets an ".ASPXANONYMOUS" cookie that (as far as I'm aware) we're not telling it to do.
Apologies if this is a real newb question, I'm new at this!
Thanks.
This is how I've done in my website:
Setup a website on IIS with an ASP.NET application pool
Set the binding host to your.domain.com
Note: you cannot use domain.com or else the sub-domain will not be cookieless
Create a folder on the website called Static
Setup another website, point it to Static folder created earlier.
Set the binding host to static.domain.com
Use an application pool with unmanaged code
On the settings open Session State and check Not enabled.
Now you have a static website. To setup open the web.config file under Static folder and replace with this one:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<sessionState mode="Off" />
<pages enableSessionState="false" validateRequest="false" />
<roleManager>
<providers>
<remove name="AspNetWindowsTokenRoleProvider" />
</providers>
</roleManager>
</system.web>
<system.webServer>
<staticContent>
<clientCache cacheControlMode="UseMaxAge" cacheControlMaxAge="30.00:00:00" />
</staticContent>
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
This is going to cache the files for 30 days, remove a RoleManager (I don't know if it changes anything but I removed all I could find), and remove an item from Response Headers.
But here is a problem, your content will be cached even when a new version is deployed, so to avoid this I made an helper method for MVC. Basically you have to append some QueryString that will change every time you change these files.
default.css?v=1 ?v=2 ...
My MVC method gets the last write date and appends on the file url:
public static string GetContent(this UrlHelper url, string link)
{
link = link.ToLower();
// last write date ticks to hex
var cacheBreaker = Convert.ToString(File.GetLastWriteTimeUtc(url.RequestContext.HttpContext.Request.MapPath(link)).Ticks, 16);
// static folder is in the website folders, but instead of
// www.domain.com/static/default.css I convert to
// static.domain.com/default.css
if (link.StartsWith("~/static", StringComparison.InvariantCultureIgnoreCase))
{
var host = url.RequestContext.HttpContext.Request.Url.Host;
host = String.Format("static.{0}", host.Substring(host.IndexOf('.') + 1));
link = String.Format("http://{0}/{1}", host, link.Substring(9));
// returns the file URL in static domain
return String.Format("{0}?v={1}", link, cacheBreaker);
}
// returns file url in normal domain
return String.Format("{0}?v={1}", url.Content(link), cacheBreaker);
}
And to use it (MVC3 Razor):
<link href="#Url.GetContent("~/static/default.css")" rel="stylesheet" type="text/css" />
If you are using another kind of application you can do the same, make a method that to append HtmlLink on the page.
If you don't write cookies from domain, the domain will be cookie-less.
When the domain is set to host only resource content like scripts, images, etc., they are requested by plain HTTP-GET requests from browsers. These contents should be served as-is. This will make your domain cookieless. This cannot be done by web-server configuration. Http is completely state-less and web-servers have no idea about the cookies at all. Cookies are written or sent to clients via server-side scripts. The best you can do is disable asp.net, classic-asp or php script capabilities on the IIS application.
The way we do it is.
We have a sub-domain setup to serve cookie-less resources. So we host all our images and scripts on the sub-domain. and from the primary application we just point the resource by it's url. We make sure sub-domain remains cookie-free by not serving any dynamic script on that domain or by creating any asp.net or php sessions.
http://cf.mydomain.com/resources/images/*.images
http://cf.mydomain.com/resources/scripts/*.scripts
http://cf.mydomain.com/resources/styles/*.styles
from primary domain we just refer a resource as following.
<img src="http://cf.mydomain.com/resources/images/logo.png" />
Serving resources from Cookie-less domains is great technique if you have more than 5 of combined images/styleshees/javascript then its benefit is noticeable and is gain even with that extra DNS lookup. Also its very easy to implement :). There's how you can easily set it in web.config[system.web] and have completely cookieless subdomain (unless its cookie-fested by Google Analytics but thats easily curable as well) :)
<!-- anonymousIdentification configuration:
enabled="[true|false]" Feature is enabled?
cookieName=".ASPXANONYMOUS" Cookie Name
cookieTimeout="100000" Cookie Timeout in minutes
cookiePath="/" Cookie Path
cookieRequireSSL="[true|false]" Set Secure bit in Cookie
cookieSlidingExpiration="[true|false]" Reissue expiring cookies?
cookieProtection="[None|Validation|Encryption|All]" How to protect cookies from being read/tampered
domain="[domain]" Enables output of the "domain" cookie attribute set to the specified value
-->
To give you example
<anonymousIdentification enabled="true" cookieName=".ASPXANONYMOUS" cookieTimeout="100000" cookiePath="/" cookieRequireSSL="false" cookieSlidingExpiration="true" cookieProtection="None" domain="www.domain." />
This will set .ASPXANONYMOUS cookie only on www.domain.anyTLD but not myStatic.domain.anyTLD ... no need to create new pools and stuff :).
If you aren't using that cookie, in any way, you could just disable session state in IIS 6:
http://support.microsoft.com/kb/244465
In IIS, go to the Home Directory tab, then click the "Configuration" button.
Next go to the Options tab and un-check "Enable session state". The cookie will go away, and you can leave your files where they are with no need for an extra domain or sub-doamin.
Plus, by using additional domains, you increase dns lookups, which partially defeats the intent of the overall optimization.

How to have multiple logins with ASP.Net?

I'm working on a website with an internal and an external section.
The users for both sections are different so they require a different login page. I wanted to configure the authentication differently for both folders, but ASP.Net but it's not allowed.
Example (in my main web.config):
<authentication mode="Forms">
<forms loginUrl="~/Pages/Internal/Main.aspx" defaultUrl="~/Pages/Internal/Main.aspx" cookieless="UseDeviceProfile" name=".ApplicationAuthenticatedUser" path="/" protection="All" slidingExpiration="true" timeout="45"/>
</authentication>
And in the external subfolder, I try to overwrite the settings:
<authentication mode="Forms">
<forms loginUrl="~/Pages/External/Default.aspx" defaultUrl="~/Pages/External/Default.aspx" cookieless="UseDeviceProfile" name=".ApplicationAuthenticatedUser" path="/Pages/External" protection="All" slidingExpiration="true" timeout="45"/>
</authentication>
However this gives me an error.
I tried putting both of them in their subfolders but I get the same error, the authentication configuration section must be set at the application level (I'm guessing that means the root web.config).
A possible solution is to centralize the login page and redirect depending on where the request came from, if it came from an external page, send it to the external login page, otherwise to the internal one.
It would work, but if it's possible I'd like the solution where I can configure this in the web.config.
Thanks
I am confused? Why two user data stores? I understand internal versus external, but if this is the same application, you can assign roles to give more permissions to your internal users. In addition, you can allow your internal users to access the site from home without VPN.
Even so, if you must have two stores, your best bet is duping the application. It can be the exact application, but you put it on one internal server and one external. Then you can authenticate the users at different locations. Note, however, that you still need roles, unless you are kludging up the application.
If you need to authenticate against two stores, you can do it with a custom provider. The ASP.NET login model allows for custom providers and it is very easy to build one:
http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx
http://msdn.microsoft.com/en-us/library/aa479048.aspx
Now, if you must redirect to different pages (you are stuck in this model for some reason?), you can possibly do it by IP address. It is likely your internal network uses a 10 dot or 192 dot IP scheme. If so, those addresses get transfered to internal. The rest to external. This will require you setting up something that does the redirect. I know you can do this on the login page, if not with an HTTP Handler.
This seems like an awful lot of work, however. I still do not see the picture of why you have to accomplish the task in this manner.
If you can run as two different IIS applications then you can have different authentication providers (or different instances of the same provider... possibly using the same database with the application attribute on the provider to distinguish).
But different web apps means no shared state (Application and Session) and duplicating the install. For an intranet/internet this would allow the external deployment to not include components that no internet user can access (and thus improve security by reducing surface area).
Otherwise you might need a custom authentication provider that forwards to one of the built in ones depending on who is logging in.
If your your site is a single web application, you could probably use the ASP.NET Role Provider model for that, having two roles, one for internal and one for external pages (you can configure that pr. folder with the <location> configuration element).
For more information, see http://msdn.microsoft.com/en-us/library/9ab2fxh0.aspx
I have a simple way of handling this that might be of use to somebody. I basically want to be able to use the same code for a guest login and a registered user. I also have a mobile version of the website that I want to send to a different login page when the authentication ticket expires.
Probably not the most elegant solution, but simple enough:
Public Sub btnSubmit_Click(ByVal sender As Object, ByVal e As EventArgs)
If Page.IsValid Then
Dim userLogin As String = ""
userLogin = System.Guid.NewGuid.ToString
FormsAuthentication.RedirectFromLoginPage(userLogin, False)
' place a url param throughout my app, only four pages so no
' big problem there in this case g stands for guest
Response.Redirect("menu.aspx?m=g", False)
End If
End Sub
Then, in Global.asax:
Protected Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As System.EventArgs)
If Not Request.IsAuthenticated And _
(Not Request.RawUrl.ToLower.Contains("guestlogin.aspx")) And _
(Not Request.RawUrl.ToLower.Contains("registeredlogin.aspx")) And _
(Not Request.RawUrl.ToLower.Contains("mobilelogin.aspx")) Then
Response.Redirect("spLogin.aspx?m=" & Request.QueryString("m"))
End If
End Sub
Then, in your login page (the one specified in your Web.config):
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not Page.IsPostBack Then
if request.querystring("m")="g" then
Response.Redirect("guestlogin.aspx?m=g")
elseif request.querystring("m")="r" then
Response.Redirect("registeredlogin.aspx?m=r")
elseif request.querystring("m")="m" then
Response.Redirect("mobilelogin.aspx?m=m")
end if
End If
End Sib

How to use HTTPS in an ASP.Net Application

I want to use HTTPS in my ASP.NET web application, but only for the Login.aspx page.
How can this be accomplished?
First get or create a certificate
Get the SecureWebPageModule module from http://www.codeproject.com/Articles/7206/Switching-Between-HTTP-and-HTTPS-Automatically-Ver. Instructions for setup can be found in the article.
Add secureWebPages tag to web.config
<configuration>
...
<secureWebPages enabled="true">
...
</secureWebPages>
...
<system.web>
...
</system.web>
</configuration>
Add files and directories to be use for https protocol:
<secureWebPages enabled="true">
<file path="Login.aspx" />
<file path="Admin/Calendar.aspx" ignore="True" />
<file path="Members/Users.aspx" />
<directory path="Admin" />
<directory path="Members/Secure" />
</secureWebPages>
Hope this helps!
You can publish your own certificate or you can purchase one. The caveat is that purchasing one, depending on the company, means that it's already stored in the certificate store for most browsers. Your self published one will not be and your users will have to take the extra step of installing your cert.
You don't say what version of IIS you're using, but here are some detailed instructions for IIS 6
You can purchase relatively cheap certs or you can go with the big boys (verisign) and get an extended validation certificate which turns your address bar in IE, green. It's also a somewhat rigorous validation process and takes time.
If you know all of the users that will be hitting your website, there's no problem with installing your own. However, for an open website with anonymous users (that you don't know), it's probably best to purchase one that is already in most major browsers, certificate stores.
You can enable SSL via IIS and require it for only your login.aspx page and not for the rest.
After you get SSL setup/installed, you want to do some sort of redirect on the login page to https://. Then whatever page the user is sent to after validation, it can just be http://.
Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
If Request.IsSecureConnection = False And _
Not Request.Url.Host.Contains("localhost") Then
Response.Redirect(Request.Url.AbsoluteUri.Replace("http://", "https://"))
End If
End Sub
This may be easier to implement on a master page or just all the pages you require https. By checking for "localhost" you will avoid getting an error in your testing environment (Unless your test server has another name than check for that: "mytestservername").
disclaimer - I was involved in the development of this project
I would recommend using http://nuget.org/packages/SecurePages/ It gives you the ability to secure specific pages or use Regex to define matches. It will also force all pages not matching the Regex or directly specified back to HTTP.
You can install it via NuGet: Install-Package SecurePages
Docs are here: https://github.com/webadvanced/Secure-Page-manager-for-asp.net#secure-pages
Simple Usage:
SecurePagesConfiguration.Urls.AddUrl("/cart");
or
SecurePagesConfiguration.Urls.AddRegex(#"(.*)account", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Singleline);
You can enable HTTPS in your IIS config, but it won't be "secure" unless you acquire an SSL Certificate and plug it into IIS. Make sure you have port 443 open.

Resources