PostgreSQL, by default, does not allow remote connections. I know I could change the configuration to allow remote connections, but the software vendor will not support making any changes to the configuration. Since we develop add-on products for this vendor, we cannot simply ignore their wishes.
I would like to access Postgres from a remote computer. But making connections must come from what appears to Postgres as localhost. I'm not at all familiar with what I believe is called a TCP Port Forwarder, or maybe it is called a proxy? or Relay? In any case, I need to make remote connections to Postgres as if the requests were coming from localhost.
I already have a Windows service running on the same server as Postgres, so I would like to add this port forwarder, proxy, rely on this service. We need to do this in c#.
Alternatively, if there is already a tool available for this purpose, that I can run as a service, that would be fine as well.
It is correct that by default Postgres doesn't allow remote connections. But this can easy be changed in the pg_hba.conf file.
For this you just need to add a line with the address of your remote host.
For example:
host postgres all 192.168.12.10/32 md5
Columns:
Type: in your case Host
User: I used postgres in this example, but I recommend you
using a dedicated user as postgres is a superuser.
Database: Which database you want to access via this user and host, I left it to all, but again it is advisable to be more specific
Address: The address of the remote host
The authentication method. (md5 for md5 encrypted password). You can also set trust if you don't want any authentication at all.
For more options I refer to the postgresql documentation: https://www.postgresql.org/docs/9.3/static/auth-pg-hba-conf.html
You say you have a windows service running on the same computer and I take it that you have the code of that service under your control. In theory you can add some code in the service and get the updated binaries installed on that computer. This code can do the proxying between incoming tcp connection from internet and local postgres. From postgres point of view it will look like a localhost connection.
But,
There are some very valid reasons why only local calls are allowed and calls over network are blocked.
Your service may or may not be running with sufficient privileges to listen on a publicly open port.
If any antivirus is running on the machine, it will most certainly flag your app as suspicious and frankly, it is.
Best way to approach this is to ask the vendor nicely to grant access - or to work within the limitations.
It smells of some legal or ethical wrongdoing, but i may be wrong.
Having said that, here are the basic steps:
The service onStart registers a TcpListener on ip 0.0.0.0 and some port known to you.
On a seperate thread in a while(true) loop attempt to GetStream()
Start a TcpClient on ip localhost and postgres port
On a seperate thread in a while(true) loop attempt to GetStream()
In a while(true) loop read from listener's stream and write to client's stream. You may want to use a buffer or an array.
loop until you read a -1
This algo should work in principle.
I hope you are not hacking someone. Please dont.
You need to create a user and allow remote connection to this or an existing user.
you should be able to connecte remotly.
good luck.
Steps that I've taken so far
I've disabled the firewall and configured the SQL Server to allow remote connections
Verified if the hybrid connection manager has the connection established
Modified the connection string to specify the TCP ports
Please let me know if you have any further suggestions.
Thanks for the replies, I've finally figured it out.The mistake i was making was that i was specifying the SQL Server Name AND port number(433 in my case) ONLY while deplying to azure and in my code behind the connection string only had the server name mentioned.
However when I updated the connection string in my code behind to include the TCP port, i was able to successfully run the app in conjunction with the Hybrid connection to query results from the SQL Server.
Recently I also worked on Azure hybrid connection and have made a list of all the possible problems that I faced. One of the following may be the cause:
Hybrid Connection may only work with Default Instance of SQL Server and may fail in case of using a Named Instance. Even if the named instance is configured to use static TCP port yet might not work with the Hybrid Connection.
The possible reason might be either your named instance might be listening on the same TCP port as your default instance. As hybrid connection uses port for communication so in case when multiple instances are listening on the same port then hybrid connection might communicate to any of the one regardless of what instance you have supplied in your named instance.
In order for hybrid connection to work you need to enable TLS 1.0 on your on premises machine for both server and client. You need to add following registery value (if not already added):
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0]
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Client]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.0\Server]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001
The hybrid connection will only work if the connection string uses SQL Authentication i.e., specifying the username and password in the connection string. Thus you can not use Windows Authentication.
Although you do not need to open any firewall ports for inbound connectivity yet you are required to allow outbound connections to the following list of ports:
9350 – 9354,
5671,
80,
443
Azure hybrid connection requires Windows 8/Windows Server 2012 or later to work with. The reason for this is that hybrid connection uses Web sockets that are not supported in the earlier windows version than these. Although you can use the classic hybrid connection (now depricated) to work with the earlier Windows.
It is preferred to use the Fully-Qualified machine names for the endpoint and not the IP address. In cases where the IP of your machine is unlikely to chnage there it might have no effect but in cases where the IP might change, you shuold use the machine name and let the HCM handle everything else for you.
Also a very comprehensive walkthrough of creating a hybrid connection can be find here
Hope this solves your problem.
So Im running a Sql Server 2012 in a virtual machine on my computer and I want to be able to connect on it with the SqlConnection on Visual Studio, but I have no idea what to put on the servername parameter.
I dont know if I have to put the vm ipaddress or the machine address "WIN-NIJ53etc\SQLEXPRESS"
UPDATED:
FOR MIGRATING BETWEEN SQL CE AND SQL SERVER: Please take a look at this instruction here.
You should follow these steps:
1- Set the virtual machine to have a physical IP address.
For configuring network on Microsoft Virtual PC: http://support.microsoft.com/kb/833134
2- Be sure that you can see the VM with a static IP address. (ping is a good idea for checking that, but don't forget to turn off the firewall on the target machine, I mean the machine you wanna ping. There is no need for the server to see the client, so check that your client (in this case your VM) can ping the server IP address like "ping 192.168.10.1 -t")
3- Use Configuration Manager (All Programs\Microsoft SQL Server\Configuration Tools) and set SQL port and visibility over network.
Reference: http://msdn.microsoft.com/en-us/library/ms189083(v=sql.105).aspx
4- Restart the SQL server.
5- Be sure that "SQL Server Browser" service is started. (incase you wanna use the instance name to access the SQL server)
6- Config the firewall on the host machine (machine that has SQL engine) and add the port you specified in the Configuration Manager to TCP Inbound rules.
Take a look at here: http://www.tavislovell.com/post/How-to-configure-Windows-Firewall-to-allow-access-to-SQL-Server.aspx
BUT be advised that you should set the port specified in the Configuration Manager (default is 1433 but sometimes it's dynamic and you should set it again)
7- After you set the port and network visibility, you should change the "Server" value in the connection string to this format "IPAddress, PORT" like "192.168.10.50, 1433" (When you specify the port, there is no need to set the instance name like this "192.168.10.50\SQLEXPRESS")
Hope it helps
Ahh the joys of SQL Server Installation setup.
Make sure you have:
Network communication between the VM and the client computer (ping will work)
The SQL Server Service configured to start automatically or that it is started
The service configured to use TCP (if you don't want to use Named Pipes)
Either the SQL Server Browser enabled and started or that a static port is configured (1433 or similar)
The firewall rules configured to allow 1433 (or the port you have chosen) and 1434 (if you are using browser)
The connection string using the proper format Computer Name\Instance (to use browser) or Computer Name,port (if you are using a static port
There is a good tutorial on MSDN that may prove helpful. With specific regard to the Server Name/IP question, it doesn't matter so long as the client computer can resolve it. If you are testing, "IP,Port" is the most reliable (E.g. 10.10.10.100,1433) as it does not depend on NetBIOS, DNS nor the SQL Browser service.
How can I check whether SQL Server is installed in a system on a network?
I have to find it using IP address. Is this possible?
How to achieve it in c# code?
You could try to use WMI.
Here's how to detect if SQL Server is installed using WMI: FAQ: Detecting SQL Server 2005 using WMI (works for 2005, should be easy to adapt for other versions).
To connect to a remote computer using WMI, read this.
Of course WMI must be installed, accessible, etc.
In general SQL Server listens on port 1433:
http://support.microsoft.com/kb/287932
so if you find that this port is open there is a good chance (but not certain) that SQL Server is installed on that machine and is accessible.
You can check that this port is open by opening a socket to it: see the Socket class (doc: http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.aspx) for details.
However, it's also possible to install SQL Server in many other modes where it is not accessible through this port. It's also possible to have this port open (and responsive) from other programs.
It's worth bearing in mind that best practice for securing a server accessible over the Internet would have the SQL Server on a non-standard port, no access to WMI, and (ideally) the server locked down to only open its port to the TCP/IP addresses of known white-listed clients. So in general: there is no way to do this scan that will always work. (Just as well, if you think about it...)
I have run into a situation with a C# application installed at two sites where the initial connection to SQL Server is extremely slow. I wrote a test application to verify where the slowdown occurs and it is on the first SQLConnection.Open statement. It was taking about 41 seconds to establish a connection to the server via named pipes. We thought it might be a DNS issue but its just as slow using a TCP/IP connection. After the initial connection is made the connection is pooled and the application responds normally. Both the workstation and the server are decent machines running Windows 7 Pro, Core 2 Duo 3.16 Ghz with 4 gig of Ram. I did find the following article on a microsoft forum:
http://social.msdn.microsoft.com/Forums/en/windowscompatibility/thread/f295994c-5812-4e46-8ac9-f05471d4dd54
Turning off the LLMNR protocol did cut the initial connection time in about half to 21 seconds. However, this is still a long time to get an initial connection to SQL Server. The only things slightly different from our norm is that DNS in this case is done thru a router and not an actual server. This has occurred at only two places so far, others run with no issues. Any help would be appreciated.
Thank You,
Dennis
In front of the server on the connection string, add np:
This becomes Server=np:server\instance and forces the Named Pipes instead of the default of TCP.
I could of probably changed the priority to use Named Pipes before TCP... but I did not want to mess with that on the server.
I saw similar problem but not sure it's the same as yours. In my case, it's not just the C# program being slow to make the SQL connection. It's any tools connecting to SQL server also experiencing the slowness. Also, once the initial connection made to the SQL server, any subsequent connections are fine for a period of time.
The reason was that SQL server was using a number of managed assemblies. It's trying to verify the cerfiticates assigned to the assemblies. It's connecting the crl.microsoft.com. My SQL server didn't have the internet connection. So, it waits for the timeout.
The solution was to make my SQL server to have internet access or disable the CRL checking. You can go to the SQL server machine. Select Tools > Internet Options > Advanced. Check if the publisher's certificate revocation under the secuity node is checked or not. If it's checked, uncheck it.
I tried specifying the connection string with integrated security = false (meaning the user id and password are in the connection string) and encrypt = false (just be be 100% sure SSL encryption is not being used). These specifications did not seem to help and I could not get a connection explicitly using the TCP/IP network library (NetworkLibrary = "dbmssocn"). This could have to do with the server firewall and the port not being open. I switched back to named pipes and put the named pipe network library specification in the connection string this time (NetworkLibrary = "dbnmpntw"). After this change, the connection was made instantaneously.
Establishing an integrated security connection to SQL Server using the IP address (instead of a host name), will prevent Kerberos authentication being used. In this scenario check the connection between the SQL Server and the domain controller.
If you connect using the host name (not the IP Address) Kerbos is in play, in this case you need to check the client machine's connection to the domain controller.
We had the same problem, and it turned out that our remotely-hosted Active Directory server was to blame.
We created a site-local Active Directory server to replicate the remotely hosted AD master and then all of our slow SQL Server integrated security authentication performance issues went away.
I hope that helps.
Yeah when you're using integrated security, Active Directory can be the one to blame, also the overall network since it all depends on it. Another thing I could think of is the edition of SQL Server you're using.
Also, when SQL Server is not being used by long periods of time, it behaves similar to IIS, putting the worker process to sleep, so when you contact the server again, depending on the machine (we can see that these have desktop machines configurations), it will take some time while the worker process gets back to life and is ready to work.
You did check the obvious I take it? That UDP port 1434 is open on the firewall and the browser service is running .... would take about 40 sec to authenticate otherwise.
there are other methods of creating connections to SQL databases. Try finding a tutorial which uses the
sqlconnection myCon = new sqlconnection(details);
myCon.Open()
instead of creating an object to instance the connection.
I don't have a concrete answer but have you tried running SQL Profiler to see what is going on from SQL's point of view?
Also have you tried connecting to SQL using the same credentials as your connection?
On the other hand it may all be much lower level but I always do the easy to check stuff first.
Good Luck.
It sounds like either name resolution is taking a while or authentication is taking a while. After the initial resolution or authentication's occured, then details of endpoints are cached by the server so it doesn't need to perform the lookups again until caches expire.
As an experiment, try ping'ing the server from the client box -- if this takes a long time to resolve the hostname, then you've found the culprit: hostname lookups (DNS or NBNS). Another alternative is to use the host IP address rather than name. So if you've got a SQL Server named instance of bob on server sql2005-01, and this server has an IP of 192.168.200.12, then try connecting to 192.168.200.12\bob instead of sql2005-01\bob.
Authentication's more awkward to resolve, but you might be able to test it with runas on the SQL server box (e.g., runas /user:domain\user cmd to see if you can open up a command prompt as the user you're attempting to authenticate as.
It could easily be a problem with either the connection or the authentication, it is normal that the first connection takes longer as ADO.NET has connection pool to avoid that long connection time.
There are many factors that can influence the speed:
- TCP/IP configuration
- Routers on the server-side
- etc.
Still if you are facing the issue, please see blow resolution:
Root Cause
The issue which we were seeing on Win7 VDIs could be due to the Network hardware device connected with the machine. If TCP/IP scaling is not supported by the network device then the performance will be slow.
Solution
Disable auto tuning level of the TCP. Please follow below steps:
1) Open command Prompt with admin right (Run as Admin)
2) Type “netsh interface tcp set global autotuninglevel=disabled”
3) After running above command restart the machine.
For other information on this command, visit link “http://support.microsoft.com/kb/935400”
I had the same problem. After vigorous research on google and stackoverflow, i changed the client computer's hosts file (In windows,located at C:\Windows\System32\drivers\etc).I entered my host's ip address and server name in this file and Viola!. Things became superfast!
Like everybody in stackoverflow said, it was the computer looking up the servername's address in the DNS service and getting a timeout.
The steps i did follows.Give it a try if nothing else works.
HOW TO ADD AN ENTRY IN HOSTS FILE
1.Open the command prompt and ping your server,where the remote database is located. To do this enter the following command:
ping servername
Here my remote computer name was Juno. So i should ping like this.
ping Juno
This command will ping my server and returns ip address like this.
Pinging Juno [192.168.0.3] with 32 bytes of data:
As you can see the ip address of the server is between the brackets.
Copy the ip address.
2.Now Open the Hosts file with elevated Notepad(Run as administrator).
At the end of the hosts file,there will be some lines like these:
#localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
At the very bottom (here,after the localhost),type # and enter the ip address of the server we just obtained preceeded by server name.
So, the hosts file should look like this.
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
# 169.254.63.1 Juno
Now save the hosts file and restart the Client PC. (For me,it worked instantly without restart.)
Annd there you go!
For more info about editing your hosts file,click here
In my case the answer was:
Try everything with no result.
Remote Desktop to the (non-prod) SQL Server to double check settings.
Close down Visual Studio you left running after doing a quick SSIS job.
Go somewhere quiet and kick yourself.
Open Start -> Microsoft SQL Server 20XX ->SQL Server Configuration Manager
SQL Native Client 11.0 Configuration (32bit) -> Client Protocols -> (Ensure all items are marked as "Enabled")
SQL Server Network Configuration -> Protocols for MSSQLSERVER -> (Ensure only Shared Memory item is marked as "Enabled", others should be "Disabled")
SQL Native Client 11.0 Configuration -> Client Protocols -> (Ensure all items are marked as "Enabled")
Reboot computer
Ensure SQL Services are running and attempt to connect to local MSSQL
Connection should be much more rapid