I have an application that needs to communicate with a web server hosted on an external provider. It's been configured to only allow incoming connections from IP addresses that it recognizes.
If I needed to connect when I was working remotely and connected through VPN, I would add routes through a terminal window like sudo route -n add -net 22.222.222.22/32 192.168.133.1
I don't want every user that works remotely to have to do this. Can I do something in the application layer to allow a user that connected through the VPN to connect to the remote web server and use the VPN tunnel? It is a C# Winforms application.
I'm assuming all of the users of your app are behind the same firewall? If that's the case, then your network admin should be able to setup the routing for you either on the router directly or on your NAT server. It's also worth noting that, at least at my company, we've always had to add the routing statements twice - one for internal and one for outside over VPN. It would be a massive security vulnerability if an app could modify your computer's routing table so I wouldn't do that.
One more thought - it's possible that your VPN uses a common feature called split tunneling which means that all destinations behind your firewall would go over VPN (and have the associated routing rules applied), but any destinations outside (such as your external provider) are split and instead go straight out without any routing. The only way around this would be to setup a VPN tunnel between your firewall and your external provider (e.g. at my company we've done this with our cloud servers so they are accessible over VPN).
http://en.wikipedia.org/wiki/Split_tunneling
I could discern in your comments, that you are trying to add a route in a windows environment, but only found a command that works on linux?!
But I actually don't get your drift, and what the result of your application should be.
First of all I'll try to help you adding a route to your routing table with C# on a windows machine. (Server-sided)
I've created a little WinForm with a Button-Control btnAddRoute and a Textbox-Control textBox1 to give you an example:
Adding routes only works as administrator btw
private void btnAddRoute_Click(object sender, EventArgs e)
{
// route -p add xxx.xxx.xxx.xxx mask 255.255.0.0 xxx.xxx.xxx.xxx
string netIp = "22.222.222.22";
string mask = "255.255.255.255";
string exitIp = "192.168.133.1";
string arg = String.Format("-p add {0} mask {1} {2}", netIp, mask, exitIp);
Process p = new Process
{
StartInfo =
{
UseShellExecute = false,
FileName = "route",
Arguments = arg,
RedirectStandardOutput = true,
StandardOutputEncoding = Encoding.ASCII
}
};
p.Start();
textBox1.Text = p.StandardOutput.ReadToEnd();
}
This adds a route with the specified IP's to your routing table, and returns OK! or Failed! depending on if the action was successfully or not.
Is this more or less what you want? Or did I totally amiss?
Related
I am following Azure's Mobile Quickstart Tutorial (Xamarin.Android) and I was able to have the Facebook Authentication and Push Notification running.
Now, I wanted to know how to have a local development environment or have the Mobile App Service (Nodejs) run on my local machine instead (not on Azure Cloud). And I followed this tutorial:
https://shellmonger.com/2016/04/01/30-days-of-zumo-v2-azure-mobile-apps-day-2-local-development/
However, things break just after I open the app. See screenshots below:
Error:
Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException: Cannot PUT /push/installations/cc69e3d2-5d18-4077-a23a-56a845a73698
Couple of notes:
- This app works as it should if I connect it to the remote app service on Azure Cloud.
- Yes, I have the app server (nodejs) cloned in my local machine - installed required modules, and is running as it should (screenshot)
// This is a base-level Azure Mobile App SDK.
var express = require('express'),
azureMobileApps = require('azure-mobile-apps');
// Set up a standard Express app
var app = express();
// If you are producing a combined Web + Mobile app, then you should handle
// anything like logging, registering middleware, etc. here
// Configuration of the Azure Mobile Apps can be done via an object, the
// environment or an auxiliary file. For more information, see
// http://azure.github.io/azure-mobile-apps-node/global.html#configuration
var mobileApp = azureMobileApps({
// Explicitly enable the Azure Mobile Apps home page
homePage: true,
// Explicitly enable swagger support. UI support is enabled by
// installing the swagger-ui npm module.
// swagger: true,
// App will use MS_SqliteFilename or MS_TableConnectionString to choose the SQLite or SQL data provider
data: {
dynamicSchema: true
}
});
// Import the files from the tables directory to configure the /tables endpoint
mobileApp.tables.import('./tables');
// Import the files from the api directory to configure the /api endpoint
mobileApp.api.import('./api');
// Initialize the database before listening for incoming requests
// The tables.initialize() method does the initialization asynchronously
// and returns a Promise.
mobileApp.tables.initialize()
.then(function () {
app.use(mobileApp); // Register the Azure Mobile Apps middleware
app.listen(process.env.PORT || 3000); // Listen for requests
});
- And also yes, I changed the mobile app client's needed ApplicationURL to the one I have running locally (screenshot)
...
const string applicationURL = #"http://192.168.1.221:3000";
const string localDbFilename = "newlocalstore.db";
protected override async void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Activity_To_Do);
CurrentPlatform.Init();
...
- Lastly, I have my IP address already white-listed on the firewall setting of the MS SQL Server. So it shouldn't be an issue since I was also able to fully up my local app service (nodejs).
What do you think causes the error?
When you run locally, you must provide ALL the connection strings required - including ones that are automatically generated for you in the cloud. In this case, you have not defined the Notification Hubs connection string in the local
environment.
Go to Kudu (https://yoursite.scm.azurewebsites.net) and look at the environment variables for connection strings. They are rather obvious when you look for them. Make sure you have all the connection strings defined as the same environment variables.
I am creating a Nancy Module that will eventually be hosted inside of a Windows Service. To start the Nancy hosting, I am using Nancy.Hosting.Self. Below is the code to start Nancy host.
string strHostProtocol = Convert.ToString(ConfigurationManager.AppSettings["HostProtocol"]);
string strHostIP = Convert.ToString(ConfigurationManager.AppSettings["HostIP"]);
string strHostPort = Convert.ToString(ConfigurationManager.AppSettings["HostPort"]);
//Here strHostProtocol="https", strHostIP = "192.168.100.88" i.e. System IPv4, strHostPort = "9003"
var url = strHostProtocol + "://" + strHostIP + ":" + strHostPort;
//url ="https://192.168.100.88:9003"
this.host = new NancyHost(new Uri(url));
this.host.Start();
Now once the windows service starts, it will start the above host and I could see this in netstat -a command. When I browse this in browser using https://192.168.100.88:9003 I will get proper response.
The problem arises when the same is browsed using its external IP. Say this system has been assigned with external IP of 208.91.158.66 and when I try browsing this as https://208.91.158.66:9003 I will just get a browser default loading progress continuosly which does not stop and without any error thrown. I have also added the below command and reserved URL successfully.
netsh http add urlacl url=https://192.168.100.88:9003/ user=everyone
But even after this the host cannot be browsed using external IP assigned to that system. Is there any restricting Nancy is putting up? Firewalls are turned off, defenders are turned off. Anyone has any idea on this?
UPDATE
The duplicate linked question talks about LAN but here I am trying through external IP and I've tried answer mentioned over there and also specified the same in question
Alright. This issue was also posted to GitHub Nancy Repo and below is what #Khellang had to say.
When you bind to https://192.168.100.88:9003, the
TcpListener/HttpListener won't listen on other interfaces. You either
have to bind to https://208.91.158.66:9003 or https://localhost:9003
and set RewriteLocalhost = true (default).
Further he also said that
If you also want to listen to requests coming to the external IP, yes.
Or you could use a wildcard, like https://+:9003/, https://*:9003/ or
https://localhost:9003/ (with RewriteLocalhost = true, this will
result in https://+:9003/). You can read more about them in the link I
posted.
and thanks to #TimBourguignon as he suggested the same in his comments. Hope this helps someone in future.
He has also suggested to read this link to know more about the Strong Wildcard and Weak Wildcard
I'm trying to figure out how if there's a way to make a hostname resolve to a certain IP without DNS or host file modification.
Using C#, I'm making a request from client to server, but I have to use the hostname in the request so that the certificates will properly authenticate the request. However, my program is meant to run without admin rights, so I can't modify the host file. I have the correct IP and the host name, is there any other way to make the computer resolve the host name to the IP?
It looks like the simplest way to solve this is to create a service with the rights to modify the host file, then invoke that service from the main program. The service runs a single command and exits. Since a service can have elevated status, you can essentially encapsulate admin rights inside a standard user program.
If you're making an HTTP request, then you don't need to resolve the hostname; use the IP address in the URL and pass the host header in your HTTP request.
HttpWebRequest.Host Property
Update: sorry didn't see the certificates requirements. I think you should be able to modify the hosts file during installation (because installation usually happens under admin rights). Add the host name you're interested in to point to 127.0.0.1 (local machine). Then, your app can open a listening socket and act as a proxy, channeling the data to the actual Web server. This may or may not work depending on the client having a firewall enabled.
public bool ModifyHostsFile(string sEntryIPAddr, string sEntryURL)
{
try
{
using (StreamWriter w = File.AppendText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), #"drivers\etc\hosts")))
{
w.WriteLine(sEntryIPAddr+" "+ sEntryURL);
return true;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return false;
}
}
this worked for me:
Step 1. Open your Windows start menu, search for the notepad application and then right click the notepad icon.
Step 2. Choose “Run as administrator” and then, while inside notepad, browse to folder (/windows/system32/drivers/etc) that contains the hosts file.
Is anyone else having a difficult time getting Twitters oAuth's callback URL to hit their localhost development environment.
Apparently it has been disabled recently. http://code.google.com/p/twitter-api/issues/detail?id=534#c1
Does anyone have a workaround. I don't really want to stop my development
Alternative 1.
Set up your .hosts (Windows) or etc/hosts file to point a live domain to your localhost IP. such as:
127.0.0.1 xyz.example
where xyz.example is your real domain.
Alternative 2.
Also, the article gives the tip to alternatively use a URL shortener service. Shorten your local URL and provide the result as callback.
Alternative 3.
Furthermore, it seems that it works to provide for example http://127.0.0.1:8080 as callback to Twitter, instead of http://localhost:8080.
I just had to do this last week. Apparently localhost doesn't work but 127.0.0.1 does Go figure.
This of course assumes that you are registering two apps with Twitter, one for your live www.mysite.example and another for 127.0.0.1.
Just put http://127.0.0.1:xxxx/ as the callback URL, where xxxx is the port for your framework
Yes, it was disabled because of the recent security issue that was found in OAuth. The only solution for now is to create two OAuth applications - one for production and one for development. In the development application you set your localhost callback URL instead of the live one.
Callback URL edited
http://localhost:8585/logintwitter.aspx
Convert to
http://127.0.0.1:8585/logintwitter.aspx
This is how i did it:
Registered Callback URL:
http://127.0.0.1/Callback.aspx
OAuthTokenResponse authorizationTokens =
OAuthUtility.GetRequestToken(ConfigSettings.getConsumerKey(),
ConfigSettings.getConsumerSecret(),
"http://127.0.0.1:1066/Twitter/Callback.aspx");
ConfigSettings:
public static class ConfigSettings
{
public static String getConsumerKey()
{
return System.Configuration.ConfigurationManager.AppSettings["ConsumerKey"].ToString();
}
public static String getConsumerSecret()
{
return System.Configuration.ConfigurationManager.AppSettings["ConsumerSecret"].ToString();
}
}
Web.config:
<appSettings>
<add key="ConsumerKey" value="xxxxxxxxxxxxxxxxxxxx"/>
<add key="ConsumerSecret" value="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"/>
</appSettings>
Make sure you set the property 'use dynamic ports' of you project to 'false' and enter a static port number instead. (I used 1066).
I hope this helps!
Use http://smackaho.st
What it does is a simple DNS association to 127.0.0.1 which allows you to bypass the filters on localhost or 127.0.0.1 :
smackaho.st. 28800 IN A 127.0.0.1
So if you click on the link, it will display you what you have on your local webserver (and if you don't have one, you'll get a 404). You can of course set it to any page/port you want :
http://smackaho.st:54878/twitter/callback
I was working with Twitter callback url on my localhost. If you are not sure how to create a virtual host ( this is important ) use Ampps. He is really cool and easy. In a few steps you have your own virtual host and then every url will work on it. For example:
download and install ampps
Add new domain. ( here you can set for example twitter.local) that means your virtual host will be http://twitter.local and it will work after step 3.
I am working on Win so go under to your host file -> C:\Windows\System32\Drivers\etc\hosts and add line: 127.0.0.1 twitter.local
Restart your Ampps and you can use your callback. You can specify any url, even if you are using some framework MVC or you have htaccess url rewrite.
Hope This Help!
Cheers.
Seems nowadays http://127.0.0.1 also stopped working.
A simple solution is to use http://localtest.me instead of http://localhost it is always pointing to 127.0.0.1 And you can even add any arbitrary subdomain to it, and it will still point to 127.0.0.1
See Website
When I develop locally, I always set up a locally hosted dev name that reflects the project I'm working on. I set this up in xampp through xampp\apache\conf\extra\httpd-vhosts.conf and then also in \Windows\System32\drivers\etc\hosts.
So if I am setting up a local dev site for example.com, I would set it up as example.dev in those two files.
Short Answer: Once this is set up properly, you can simply treat this url (http://example.dev) as if it were live (rather than local) as you set up your Twitter Application.
A similar answer was given here: https://dev.twitter.com/discussions/5749
Direct Quote (emphasis added):
You can provide any valid URL with a domain name we recognize on the
application details page. OAuth 1.0a requires you to send a
oauth_callback value on the request token step of the flow and we'll
accept a dynamic locahost-based callback on that step.
This worked like a charm for me. Hope this helps.
It can be done very conveniently with Fiddler:
Open menu Tools > HOSTS...
Insert a line like 127.0.0.1 your-production-domain.com, make sure that "Enable remapping of requests..." is checked. Don't forget to press Save.
If access to your real production server is needed, simply exit Fiddler or disable remapping.
Starting Fiddler again will turn on remapping (if it is checked).
A pleasant bonus is that you can specify a custom port, like this:
127.0.0.1:3000 your-production-domain.com (it would be impossible to achieve this via the hosts file). Also, instead of IP you can use any domain name (e.g., localhost).
This way, it is possible (but not necessary) to register your Twitter app only once (provided that you don't mind using the same keys for local development and production).
edit this function on TwitterAPIExchange.php at line #180
public function performRequest($return = true)
{
if (!is_bool($return))
{
throw new Exception('performRequest parameter must be true or false');
}
$header = array($this->buildAuthorizationHeader($this->oauth), 'Expect:');
$getfield = $this->getGetfield();
$postfields = $this->getPostfields();
$options = array(
CURLOPT_HTTPHEADER => $header,
CURLOPT_HEADER => false,
CURLOPT_URL => $this->url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false
);
if (!is_null($postfields))
{
$options[CURLOPT_POSTFIELDS] = $postfields;
}
else
{
if ($getfield !== '')
{
$options[CURLOPT_URL] .= $getfield;
}
}
$feed = curl_init();
curl_setopt_array($feed, $options);
$json = curl_exec($feed);
curl_close($feed);
if ($return) { return $json; }
}
I had the same challenge and I was not able to give localhost as a valid callback URL. So I created a simple domain to help us developers out:
https://tolocalhost.com
It will redirect any path to your localhost domain and port you need. Hope it can be of use to other developers.
set callbackurl in twitter app : 127.0.0.1:3000
and set WEBrick to bind on 127.0.0.1 instead of 0.0.0.0
command : rails s -b 127.0.0.1
Looks like Twitter now allows localhost alongside whatever you have in the Callback URL settings, so long as there is a value there.
I struggled with this and followed a dozen solutions, in the end all I had to do to work with any ssl apis on local host was:
Go download: cacert.pem file
In php.ini * un-comment and change:
curl.cainfo = "c:/wamp/bin/php/php5.5.12/cacert.pem"
You can find where your php.ini file is on your machine by running php --ini in your CLI
I placed my cacert.pem in the same directory as php.ini for ease.
These are the steps that worked for me to get Facebook working with a local application on my laptop:
goto apps.twitter.com
enter the name, app description and your site URL
Note: for localhost:8000, use 127.0.0.1:8000 since the former will not work
enter the callback URL matching your callback URL defined in TWITTER_REDIRECT_URI your application
Note: eg: http://127.0.0.1/login/twitter/callback (localhost will not work).
Important enter both the "privacy policy" and "terms of use" URLs if you wish to request the user's email address
check the agree to terms checkbox
click [Create Your Twitter Application]
switch to the [Keys and Access Tokens] tab at the top
copy the "Consumer Key (API Key)" and "Consumer Secret (API Secret)" to TWITTER_KEY and TWITTER_SECRET in your application
click the "Permissions" tab and set appropriately to "read only", "read and write" or "read, write and direct message" (use the least intrusive option needed for your application, for just and OAuth login "read only" is sufficient
Under "Additional Permissions" check the "request email addresses from users" checkbox if you wish for the user's email address to be returned to the OAuth login data (in most cases check yes)
First question!
Environment
MVC, C#, AppHarbor.
Problem
I am calling an openid provider, and generating an absolute callback url based on the domain.
On my local machine, this works fine if I hit http://localhost:12345/login
Request.Url; //gives me `http://localhost:12345/callback`
However, on AppHarbor where I'm deploying, because they are using non-standard ports, even if I'm hitting it at "http://sub.example.com/login"
Request.Url; //gives me http://sub.example.com:15232/callback
And this screws up my callback, because the port number wasn't in the original source url!
I've tried
Request.Url
Request.Url.OriginalString
Request.RawUrl
All gives me "http://sub.example.com:15232/callback".
Also to clear up that this isn't a Realm issue, the error message I am getting from DotNetOpenAuth is
'http://sub.example.com:14107/accounts/openidcallback' not under realm 'http://*.example.com/'.
I don't think I've stuffed that up?
Now, I'm about to consider some hacky stuff like
preprocessor commands (#IF DEBUG THEN PUT PORT)
string replace (Request.URL.Contains("localhost"))
All of these are not 100% solutions, but I'm sick of mulling over what could be a simple property that I am missing. I have also read this but that doesn't seem to have an accepted answer (and is more about the path rather than the authority). So I'm putting it towards you guys.
Summary
So if I had http://localhost:12345/login, I need to get http://localhost:12345/callback from the Request context.
And if I had "http://sub.example.com/login", I should get "http://sub.example.com/callback", regardless of what port it is on.
Thanks! (Sleep time, will answer any questions in the morning)
This is a common problem in load balanced setups like AppHarbor's - we've provided an example workaround.
Update: A more desirable solution for many ASP.NET applications may be to set the aspnet:UseHostHeaderForRequestUrl appSetting to true. We (AppHarbor) have seen several customers experience issues using it with their WCF apps, which is why we haven't enabled it by default and stil recommend the above solution for those situations. You can configure it using AppHarbor's "Configuration Variables" to inject the appsettings when deployed. More information can be found in this article.
I recently ran into an issue where I compared a URL to the current URL, and then highlighted navigation based on that. It worked locally, but not in production.
I had http://example.com/path/to/file.aspx as my file, but when viewing that file and running Request.Url.ToString() it produced https://example.com:81/path/to/file.aspx in a load balanced production environment.
Now I am using Request.Url.AbsolutePath to just give me /path/to/file.aspx, thus ignoring the schema, hostname, and port numbers.
When I need to compare it to the URL on each navigation item I used:
New Uri(theLink.Href).AbsolutePath
My initial thoughts are get the referrer variable and check if that includes a port, if so use it otherwise don't.
If that’s not an option because a proxy might remove the referrer header variable then you might need to use some client side script to get the location and pass it back to the server.
I'm guessing that AppHarbor use port forwarding to the IIS server so even though publicly the site is on port 80 IIS has it hosted on another port so it can't know what port the client connected on.
Something like
String port = Request.ServerVariables["SERVER_PORT"] == "80" ? "" : ":" + Request.ServerVariables["SERVER_PORT"];
String virtualRoot = Url.Content("~/");
destinationUrl = String.Format("http://{0}{1}{2}", Request.ServerVariables["SERVER_NAME"], port + virtualRoot, "/callback");
If you use the UrlBuilder class in the framework you can easly get around this. On the builder class if you set the port to -1 then the port number will be removed:
new UriBuilder("http://sub.example.com:15232/callback"){ Port = -1}
returns : http://sub.example.com/callback
To keep the port number on a local machine just check Request.IsLocal and don't apply -1 to the port.
I would wrap this into a extension method to keep it clean.
I see that this is an old thread. I had this issue running MVC5, on IIS 7.5, with an Apache proxy in front. Outside of the server, I would get "Empty Response", since the asp.net app gets the Url from apache with the custom port.
In order to have the app redirect to a subpath without including the "custom" port, forget the Response/Request objects, and use the Transfer method. For instance, if I want that users are automatically redirected to the login page in case they are not logged already:
if (!User.Identity.IsAuthenticated)
Server.TransferRequest("Account/Login");