15/05/2008
Every now and then, I encounter someone in a panic about the fact that a website they've surfed to knows their IP. This panic often results in the discovery of various anonymous web surfing services (sometimes called proxy servers) that purportedly allow you to browse the web without anyone knowing who you are. Now, everyone is welcome to be as paranoid on this topic as they choose. I will note, however, that in my opinion, most of the paranoia on this topic is rooted in a total lack of knowledge on the part of the paranoid.
Every web server has always been able to see the IP address of every visitor. This has been true from the beginnings of the web and is fundamental to TCP/IP. It has never changed. When you browse to a website, what is actually happening is that your DNS subsystem resolves a canonical/host name (like www.regnatarajan.com) to an IP address, and then your networking subsystem initiates a connection to that IP address -- in the case of an HTTP connection, it usually connects to port 80. The web server on the other end usually allows that port to be opened and sends back responses to the requests made by your system.
This is always true. There is no other way to browse to a website hosted on a web server, and all web sites are hosted on web servers of some kind or other. There are minor variances to the mechanisms described above, such as entering the IP address directly in the address line, but these result in the exact same thing minus the DNS resolution and they don't change the basic principles involved. Now, here's the important part: as soon as this connection is open, the web server knows your IP address. Every time. It has to, or it wouldn't know where to send back the responses.
Every web server you connect to knows your IP. Deal with it.
Now, anonymous web surfing services simply introduce a layer between you and the web server. You connect to the anonymizer service, it connects to wherever you want to go, and it passes the information back and forth like a relay agent. The web server only sees the anonymizer's IP and you never connect to the web server directly so you're anonymous, right? Wrong. You are simply now trusting the anonymizer service with your security instead of the web server, which is usually highly dubious. The CIA is strongly suspected of operating many of the popular anonymizer services, and some others are operated by kids and hobbyists who I, personally, wouldn't trust at all with my personal data. I know this to be true as many of them rent servers from my company to do it. Beyond this, any anonymizer service in the US, even if it honestly intends to be credible, is subject to the Patriot Act which allows government to inspect the service's logs and data and forbids that service from informing its clients that this has happened.
Now, if there's a site you particularly distrust but need to access, using an anonymizer service may be a credible thing to do in that case, but don't delude yourself into thinking you're anonymous. You've just shifted your vulnerability from one party to another. 12/05/2008
My mother sent me this. She's 74 and has time on her hands, it seems. 1 x 8 + 1 = 9 12 x 8 + 2 = 98 123 x 8 + 3 = 987 1234 x 8 + 4 = 9876 12345 x 8 + 5 = 98765 123456 x 8 + 6 = 987654 1234567 x 8 + 7 = 9876543 12345678 x 8 + 8 = 98765432 123456789 x 8 + 9 = 987654321 1 x 9 + 2 = 11 12 x 9 + 3 = 111 123 x 9 + 4 = 1111 1234 x 9 + 5 = 11111 12345 x 9 + 6 = 111111 123456 x 9 + 7 = 1111111 1234567 x 9 + 8 = 11111111 12345678 x 9 + 9 = 111111111 123456789 x 9 +10= 1111111111 9 x 9 + 7 = 88 98 x 9 + 6 = 888 987 x 9 + 5 = 8888 9876 x 9 + 4 = 88888 98765 x 9 + 3 = 888888 987654 x 9 + 2 = 8888888 9876543 x 9 + 1 = 88888888 98765432 x 9 + 0 = 888888888 1 x 1 = 1 11 x 11 = 121 111 x 111 = 12321 1111 x 1111 = 1234321 11111 x 11111 = 123454321 111111 x 111111 = 12345654321 1111111 x 1111111 = 1234567654321 11111111 x 11111111 = 123456787654321 111111111 x 111111111= 12345678987654321 08/04/2008
As with most of us, I've struggled with the basic problem of providing users with updated information without hitting the database endlessly, especially in cases where everyone is just requesting the same information. Well, I thought of a mildly novel solution to it the other day and, not being overly concerned with testing in this case (only a handful of non-critical users), I just put it into production over the last few days.
The concept is simple: create a Microsoft SQL Server stored procedure to generate a tiny raw HTML snapshot of the information I want to provide, and use Microsoft's SQL Agent to run the job every minute, which is plenty real-time enough for this situation. Unlimited users can simply hit the HTML file with almost no overhead and with almost no strain on the database at all. The HTML file in my case rarely exceeds a kilobyte, which means a million concurrent users accessing it once a minute wouldn't strain a single server in the data center.
Step 1: Create the Stored Procedure
-- If the stored procedure exists, kill it IF OBJECT_ID('dbo.sp_CreateRecentlyBloggedHTML') IS NOT NULL DROP PROC dbo.sp_CreateRecentlyBloggedHTML GO
-- Use the correct database
USE [www.bbad.com] ; GO
-- Create the procedure
CREATE PROCEDURE [dbo].sp_CreateRecentlyBloggedHTML AS
-- Declare some variables
Declare @myTmpStr sysname, @myTitle sysname, @myURL sysname, @myLastUpdate sysname, @myDaysSinceLastUpd sysname, @myLastUpdateTime sysname, @cmd sysname, @fname sysname;
-- Initialize a file name SET @fname='c:\data\SQLGeneratedHTML\recentblogs.htm';
-- Declare a cursor and open it using whatever SQL you need
Declare GetRecentBlogs Cursor for
select W.Title, W.FullUrl, DATEADD(hour, -8, max(D.TimeCreated)) AS LastUpdate, DATEDIFF(day, DATEADD(hour, -8, max(D.TimeCreated)), GETDATE()) AS DaysSinceLastUpdate, LEFT(CONVERT(CHAR(8),DATEADD(hour, -8, max(D.TimeCreated)),8),5) AS LastUpdateTime from AllDocs D inner join Webs W on D.WebID=W.ID inner join Webs B on (W.ParentWebId=B.Id) and (B.FullUrl='blogs')) group by W.Title, W.FullUrl order by LastUpdate DESC;
Open GetRecentBlogs;
-- Open an HTML page
SET @cmd='echo ^<HTML^>^<HEAD^> > ' + @fname; exec master..xp_cmdshell @cmd;
SET @cmd='echo ^<meta http-equiv="Content-Language" content="en-us"^> >> ' + @fname; exec master..xp_cmdshell @cmd;
SET @cmd='echo ^<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"^> >> ' + @fname; exec master..xp_cmdshell @cmd;
SET @cmd='echo ^<meta http-equiv="REFRESH" CONTENT="120"^> >> ' + @fname; exec master..xp_cmdshell @cmd;
SET @cmd='echo ^<base target="_top"^>^<^/HEAD^>^<BODY BGCOLOR="#000000"^> >> ' + @fname; exec master..xp_cmdshell @cmd;
-- Loop through the records
Fetch Next from GetRecentBlogs Into @myTitle, @myURL, @myLastUpdate, @myDaysSinceLastUpd, @myLastUpdateTime;
WHILE (@@fetch_status <> -1) BEGIN
--Wrap each entry with a div SET @cmd = 'echo ^<div STYLE="font-family: Tahoma; font-size: 8pt; color: ffffff"^> >> '+@fname; exec master..xp_cmdshell @cmd;
-- Blog name and hyperlink -- obviously change to use your own records here SET @cmd = 'echo ^<a href="http://www.bbad.com/' + @myURL + '"^>' + @myTitle + '^</a^>^<br /^> >> '+@fname; exec master..xp_cmdshell @cmd;
SET @cmd='echo ^</div^> >> ' + @fname; exec master..xp_cmdshell @cmd;
--Get the next row and loop Fetch Next from GetRecentBlogs Into @myTitle, @myURL, @myLastUpdate, @myDaysSinceLastUpd, @myLastUpdateTime;
END ;
-- Close the HTML page
SET @cmd='echo ^</BODY^>^</HTML^> >> ' + @fname; exec master..xp_cmdshell @cmd;
-- Clean up
close GetRecentBlogs; deAllocate GetRecentBlogs; GO |
Step 2: Schedule Your Procedure
- Open Microsoft's SQL Server Management Studio
- Start the Server Agent if it isn't already started.
- Create a new job and add your stored procedure to the steps (In my example, I used exec sp_CreateRecentlyBloggedHTML;).
- Schedule the job to run every minute.
- In the alternative, you may be able to get away with setting a trigger to execute your procedure whenever a record is changed, but I had issues in my Sharepoint environment doing this.
Gotchas
- Be sure to enable the xp_cmdshell or none of this will work. Start | Programs | Microsoft SQL Server 2005 | Configuration Tools | SQL Server Surface Area Configuration | Surface Area Configuration for Features. (Nice that they made it so obvious).
- Make sure the SQL Agent is set to autostart or your HTML won't update after a reboot. Administrative Tools | Services | Microsoft SQL Server Agent.
- Be sure to escape all your < and > characters in your code or they won't work. The Transact-SQL syntax for escaping those characters is ^.
- This code is presented as an example of how to do it. If you actually put it into production, you'll probably want to create some inline functions to call for the repetitive tasks.
- Good luck. I won't help you debug your code but I hope this helps.
|
|
|
|
|