I have a project that uses Entity Framework Model First. The data source is in the internet, and I need it work using a network/web proxy for it. I had google it but I can't find any useful result, because all results are about EF's Entities Proxies.
Some helpful code:
The connection string:
<add name="ConnectionName" connectionString="metadata=res://*/Latin.csdl|res://*/Latin.ssdl|res://*/Latin.msl;provider=System.Data.SqlClient;provider connection string="data source=mssqlserver.server.com;initial catalog=DatabaseName;user id=admin;password=adminPass;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
The usage:
static void Main(string[] args)
{
//set the proxy
var proxy = new WebProxy("109.32.24.24", 808);
proxy.Credentials = new NetworkCredential("", "");
WebRequest.DefaultWebProxy = proxy;
var db = new ContextName();
if (db.QNames.First().Name == "Testing")
{
Console.WriteLine("Success Connection!");
Console.ReadKey();
}
}
This raises a network connection error.
EDIT
The proxy that the network have is running over http protocol. I know that http is the protocol you normally use to browse the web with, you do not usually connect to databases with it but it is the only available and this question is about it. You can use web proxies for several .net connections, even Web Services, and my question is about using it with EF, I could't make this working. One last solution could be to use a program like Proxifier and redirect all computer's connections to the specified web proxy, but the idea is making it a bit more configurable.
this application may be running in a internetless network, that the only way for getting internet is using an HTTP proxy
Then you cannot do this, or at least not easily.
When a network is configured such that only HTTP traffic may leave the network, then you are restricted to ... only making HTTP calls. SQL Server's wire protocol is a custom, proprietary binary protocol, that does not resemble HTTP in any way. Hence you cannot connect to a remote instance of SQL Server through an HTTP proxy, if HTTP is your only way out. That's why I asked what kind of proxy you're talking about, because for example a SOCKS proxy does allow arbitrary TCP connections to run through it, and Windows supports it natively.
You can however set up an HTTP tunnel through the proxy. See Tunnel any kind of TCP traffic through HTTP/s. This assumes you control both sides of the connection, and can run or install arbitrary software (namely the tunneling software) next to your application software.
This also may or may not work depending on the configuration of the client's proxy server.
However, this looks like an XY problem. Depending on the actual problem, there are various approaches.
You do not want to expose, nor connect to SQL Server over the internet anyway.
Perhaps you could write a webservice instead, that your application then consumes. The web service talks HTTP, so it can be connected to through the HTTP proxy without any additional configuration or software. The webservice runs on, or nearby the SQL Server and you can expose your business logic through the service - without having to expose your SQL Server.
Another alternative would be a VPN connection, but again, all that depends on the actual problem and which sides of the connection you can control.
Related
I'm trying to connect to a remote local server to get data from their Rest API. I'm on a ASP.NET MVC project and using RestSharp. When I establish VPN connection to the remote local server (via default Windows VPN connection), I'm be able to use Postman and successfully get data from their APIs. I will use this data to add new records to my DB or only display to users in my project.
But without VPN connection, I can't connect to the remote local server with Restsharp. It gives me timeout error. My C# codes for RestSharp configurations is like:
public async Task<ActionResult> PersonalList()
{
var options = new RestClientOptions("http://5.2.xxx.xx") //Remote local server IP
{
Proxy = new WebProxy("192.168.1.240", 12001), //Remote local API url and port
ThrowOnAnyError = true
};
var client = new RestClient(options);
client.Authenticator = new HttpBasicAuthenticator("myUserNameWhichIuseAtWindowsVPNConnection", "myPasswordWhichIuseAtWindowsVPNConnection");
var req = new RestRequest("/datasnap/rest/ServerMethods/GetPersonalList", Method.Get); //Get personal list API url
var resp = await client.ExecuteAsync(req);
return View();
}
I haven't changed or add any configuration to function or web.config for default credientals.
Now, I'm confused about "Am I trying the right way? Or is this type of connection to remote local server is impossible?". If this is wrong way, how should I deploy this project? If I deploy it to their local server, they only use it locally (In additon, I can't use their internet connection when I connect to their local server via VPN. I can use only their "192.168.1.240:12001".). I want them to use it when they are out of their company, not only locally.
Maybe I mixed a lot of different problems because of my confussion, sorry for that. But I will be very glad if you could suggest me what is the best practice for the solution of this situation.
Not to be harsh here but a quick terminology correction... When you write: "remote local server" I think what you're saying is that you want to connect to a remote server 'remote server' from your 'local computer' over a VPN. You will only be able to do that when your VPN client is active. Putting both words together like that, "remote local", is to me at least, confusing. :)
When the VPN client is on - it will modify your local operating system and provide a mechanism (exact mechanism depends on your VPN) for your operating system to understand that the IP "5.2.xxx.xx" is somehow addressable from your local computer. Your operating system will pick up packets that you tell it to send to "5.2.xxx.xx" and it will transport them to the other side of your VPN. Once at the other side, the VPN knows how to send your traffic to the actual target.
When you turn your VPN off - you lose that "magic" the VPN is providing for your operating system. Suddenly your OS doesn't understand how to send IP packets from your local computer to "5.2.xxx.xx". That will result in your code returning some kind of "I can't connect" (like a timeout, or 'no route to host' or some error like that)
If this is wrong way, how should I deploy this project?
Hard to answer this question. You could expose the server to the open internet, but I suspect that's specifically what you don't want to do since you're using a VPN?
If I deploy it to their local server, they only use it locally (In additon, I can't use their internet connection when I connect to their local server via VPN. I can use only their "192.168.1.240:12001".).
If you can't use "their" internet connection when connected to the VPN (I would think you mean YOUR internet connection?) it sounds like the VPN is not a "split-tunnel". That means ALL your traffic is going through their VPN and your traffic is probably getting intercepted by the VPN's security rules (and blocking you).
I want them to use it when they are out of their company, not only locally.
They would need to be on the VPN or else they won't have access. That's how it works.
This is a 'pretty big' topic you're asking about. It probably would be worthwhile for you to watch some youtube videos about how VPNs work and IP networking in general. I think that'd help you understand. :| I know that's not a great answer but it's what you probably should do.
SQLConnection use randomly namedpipes(445) instead of tcp(1433). The namedpipes port is blocked by our firewall but not the tcp. This only happens when trying to connect to one of our sql servers. Most of the time the application use the tcp but randomly is trying to use namedpipes port. Our sql connection is very simple and we doesn't do something fancy with it.
We don't want to hardcoded the tcp port on our connection string. We already try and it's fixed the problem. The problem only appears during the last week and our web application that try to connection is live for a while.
Why the sql connection sometimes trying to connect with 445 instead of 1433? Is it a bug introduced by .net latest updates or does the server can dictate the next port to use?
UPDATE 2016-09-23 11:00
Here's a sample of the code we are using to connect
string connectionString = "Data Source=SERVERNAME;Initial Catalog=DATABASE;uid=username;pwd=mypass;MultipleActiveResultSets=True";
using (SqlConnection connection = new SqlConnection(connectionString))
{
try {
connection.Open();
…
We don't want to hardcoded the tcp port on our connection string.
You don't necessarily have to put the IP address/Port# in your connection string.
BUT, you can force the network protocol in the connection string.
Network Library=DBMSSOCN;
https://www.connectionstrings.com/define-sql-server-network-protocol/
But when I've had random named-pipes issues that slow performance, I make the connection string as "specific" as possible. Which is...specify the network-library and the ip address and the port number.
By the way, I really really hope you are not actually coding your connection string in compiled code, and the below is not your actual code.
string connectionString = "Data Source=SERVERNAME;Initial Catalog=DATABASE;uid=username;pwd=mypass;MultipleActiveResultSets=True";
APPEND:
You can "fish" around this registry-setting on the problem machines.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo\
I would look specifically if DSQUERY is set or not set.
https://support.microsoft.com/en-us/kb/328306
Check the protocol that is specified in the following registry subkey:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSSQLServer\Client\ConnectTo\DSQUERY This value typically reflects the settings in the CNU, but sometimes
it does not.
If the value is DBNETLIB, it uses one of the protocols in
the enabled protocols list of the CNU. If a specific protocol is
listed, that protocol is used instead.
If this is the issue.........ultimately, any other program can alter this value. So you don't have full-control. Again, the better solution is to put the network-library in the connection string, so "outside forces" cannot change the game on you, mid-game.
The reason I know this is because I got burnt at a client site......some other program changed the DSQUERY value one about 1/3 of the client machines (that also was using our application) and our application performance went to a crawl. Aka, some other company....did something to make our application performance horrible. So instead of fighting it, I put in the network library in our connection-string to permanently address the issue.
You never mention if this connection is made from end user PCs, a web server, other db servers, etc. However, whether named pipes is used or TCP as the primary protocol is a setting on the PC that creates the connection. This can be configured using SQL Server Native Client Configuration and it can also be overriden in the connection string.
To change the default protocol or the protocol order for client computers
In SQL Server Configuration Manager, expand SQL Server Native Client Configuration, right-click Client Protocols, and then click Properties.
In the Enabled Protocols box, click Move Up or Move Down, to change the order in which protocols are tried, when attempting to connect to SQL Server. The top protocol in the Enabled Protocols box is the default protocol.
To configure a client to use TCP/IP
In SQL Server Configuration Manager, expand SQL Server Native Client Configuration, right-click Client Protocols, and then click Properties.
In the Enabled Protocols box, click the up and down arrows to change the order in which protocols are tried, when attempting to connect to SQL Server. The top protocol in the Enabled Protocols box is the default protocol.
See Configure Client Protocols
Why the sql connection sometimes trying to connect with 445 instead of
1433? Is it a bug introduced by .net latest updates or does the server
can dictate the next port to use?
It is the client rather than the server that determines the protocol order. Most client drivers will use TCP/IP first and then fall back on named pipes when the TCP connection fails. Below is the relevant excerpt from the documentation that applies to SqlClient as well.
For example, if a client computer has both TCP and Named Pipes
available, and the order is:
TCP
Named Pipes
When the client computer tries to make a TCP
connection to the server and the connection attempt returns a non-zero
return code, the client transparently tries a connection by using the
next protocol in the list, which is Named Pipes. In this scenario, the
client cannot make a TCP connection; however, the client successfully
makes a Named Pipes connection.
Note
The client does not receive an error that indicates the first protocol failed.
If the client application uses the second protocol, and it also
returns an error, an error is returned to the client.
So to answer your question more directly, named pipes is attempted only because the initial TCP connection failed. The client error message indicates a named pipes connection failure but that's just a side effect of the initial TCP connection failure. The root cause based on your symptoms is an intermittent database or network connectivity problem, not at all related to using named pipes.
what about the server side?
what I would double check in SQL Server instance configuration on the servers:
which protocols are enabled on the servers behaving as expected
which protocols are enabled on the server that's showing that unexpected behaviour
my guess is that the 'broken' server has named pipes enabled while other servers does not so when the .NET client is choosing the connection protocol sometimes makes the wrong choice.
that's a wild guess because I don't know how the choice of the connection protocol is made by .NET...
I had this issue. I suspect it was either AppLocker restrictions OR running the app off a network drive that caused this. I copied the app locally and resolved the applocker restrictions and now it seems to use the correct port.
I received no errors and even forcing parameters with the connection string did not work to fix it. Now it uses port 1433 as expected.
Please actually read my post before placing it on hold!!
Let me start by saying I've been searching for a solution all afternoon and so far I have seen plenty of examples for WCF but none that would do what I need.
I have developed an application in c# that will be installed on customer servers and accesses a sql server on the customer's local network. The application also has the ability to control network relays on the customer's local network and records the status of these in sql. I am trying to figure out a way to have the customer's server establish a connection to our datacenter and be able to issue commands back to the customer's server (retrieve datasets from sql, control the network relays, etc). I have found plenty of ways to have a client call classes on a server but have so far been unsuccessful in finding the reverse. One consideration was writing a web service as part of the application on the customer's server but need a way to establish this connection for customers with dynamic IP addresses and without having to publish through firewalls, etc.
Have you considered using
VPN - Virtual private network
or
Configuring a Port Forwarding redirect on the ADSL modem, and using a solution like www.noip.com ?
If I understand correctly you want to get information from the customer's database, which is behind a firewall and has no known static ip, in addition there might be several hundred customers so a dedicated VPN to the customer is not viable.
First of all: you should not contact the customer database directly. Databases are not designed for this scenario and would probably be left open to attack if exposed directly to the internet.
So you need a service on top of the database. There are two main options you can use for this service:
Polling service
The service is actually a client calling some web service on your network and asking for instructions.
Benefits: easy to implement and deploy.
Downsides: With polling there is always the cost-benefit of scalability/bandwidth use vs. speed of service. There are also some considerations in selecting the time to poll to prevent all the client polling at the same time.
The service is a tcp-server
This can be a usual web service (or RESTfull service) or some other service. The only difference is that it needs to advertise itself. For that you need to have a known directory server. When the service starts it then connects to the directory service and tells it the port it can be contacted on (the directory knows the ip from the connection). It will then need to periodically contact the directory to let it know it is still alive and so any change in IP is detected.
A client on your network would now query the directory to find the address of the client and connect directly to it to issue commands.
Benefit: Scalable and bandwidth efficient.
Downside: More difficult to implement. Requires firewall traversal solutions (UPNP or firewall exceptions).
I'm having trouble really assessing whether or not I'm exposing our internal servers in a very unsecure and obvious way.
I have 2 domains, one internal and one external (dmz) on the firewall. I need information from the internal, and we don't want to start a migration thing, or open up ports directly to the internal server. I'm unable to connect from DMZ to internal, but the other way works fine.
I created a web api service on the dmz, which has a static TcpListener, and accepts only one connection.
I then created a simple console application on the internal server, connecting to this web api TcpListener. It holds on to the connection, and I'm able to send commands via rest-api calls to the dmz server, and send back Json data from the internal server, thus obtaining the bilateral connection I needed.
What I'm wondering is, whether this will pose a serious threat to our security? I don't know enough about network security to be able to say, but the TcpListener only has that one connection, and it's only open long enough for me to occupy this connection.
Can anyone give me a clue as to how (in)secure this solution is?
The server is in DMZ, so anyone can connect to your TcpListener. A port scan will reveal this listening socket. You need to apply authentication (client certificate / IP whitelist / basic / digest / ...).
I want all web traffic (HTTP, HTTPS and DNS - Are there any others?) goes through a local application and goes to a server application and from there goes to internet. How can I do this?
I have wrote an Async TCP server and I know socket Async programming in C# using SocketAsyncEventArgs (I am not a master with just one project but I think I can understand some basics).
The only way to do this is to write a Windows network driver - you cannot do this from userland. This is how VPNs work.
There are userland tunnels you can develop that tunnel a single connection, but they require the user to configure their applications to use it first, so you cannot unilaterally redirect all network activity.
From your question, I'm guessing you're not too familiar with Winsock internals or writing kernel network drivers, so for now I'm going to say I think this is a take above your level of competence right now.
However if you'll settle for a bit of an impure approach, you can implement a SOCKS proxy easily enough, but this requires configuring browsers to use your proxy server - at least this way you'll tunnel HTTP and HTTPS, however I'm uncertain about whether or not browsers use SOCKS servers for DNS or if they use the OS-provided DNS functionality.
Like #Dai suggested, use a SOCKS proxy. It operates above the transport layer, therefore a SOCKS server can be configured to serve any application protocol operating on typical TCP/UDP.
This is exactly what TOR does to mask all traffic, not just HTTP.