diff --git a/CHANGELOG b/CHANGELOG
index f749c8c..22d2022 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,7 @@
+10 Feb 2015: anyproxy 3.2.0:
+
+    * using SNI when intercepting https requests
+
 28 Jan 2015: anyproxy 3.1.2:
 
     * thanks to iconv-lite, almost webpage with any charset can be correctly decoded in web interface.
diff --git a/README.md b/README.md
index 7612675..0c88037 100644
--- a/README.md
+++ b/README.md
@@ -23,16 +23,15 @@ A fully configurable proxy in NodeJS, which can handle HTTPS requests perfectly.
 ------------
 * 支持https明文代理
 * 支持低网速模拟
-* 全流程开放,可以用javascript控制代理流程中的任意步骤。搭建前端个性化调试环境的利器。
-* 提供web版界面,供观测请求情况
+* 全流程开放,可以用javascript控制代理流程中的任意步骤,搭建前端个性化调试环境
+* 提供web版界面,观测请求情况
 
 Feature
 ------------
 * work as http or https proxy
-* fully configurable, you can modify a request at any stage by your own javascript code
-* when working as https proxy, it can generate and intercept https requests for any domain without complaint by browser (after you trust its root CA)
+* fully configurable, you could modify a request at any stage with your customized javascript code
+* when working as https proxy, it could generate and intercept https requests for any domain without complaint by browser (after you trust its root CA)
 * a web interface for you to watch realtime request details, where html string with (almost) any charset could be shown correctly
-* (beta)a web UI interface for you to replace some remote response with local data
 
 ![screenshot](http://gtms01.alicdn.com/tps/i1/TB1IdgqGXXXXXa9apXXLExM2pXX-854-480.gif)
  
diff --git a/diff.txt b/diff.txt
deleted file mode 100644
index 98ee805..0000000
--- a/diff.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-diff --git a/bin.js b/bin.js
-index 9b7f39b..86ccdee 100644
---- a/bin.js
-+++ b/bin.js
-@@ -4,6 +4,7 @@ var program     = require('commander'),
-     proxy       = require("./proxy.js"),
-     color       = require('colorful'),
-     fs          = require("fs"),
-+    path        = require("path"),
-     packageInfo = require("./package.json");
- 
- program
-@@ -33,15 +34,16 @@ if(program.clear){
-     var ruleModule;
- 
-     if(program.rule){
--        if(fs.existsSync(program.rule)){
--            try{ //for abs path
-+        var ruleFilePath = path.join(process.cwd(),program.rule);
-+        try{
-+            if(fs.existsSync(ruleFilePath)){
-                 ruleModule = require(program.rule);
--            }catch(e){ //for relative path
--                ruleModule = require(process.cwd() + '/' + program.rule.replace(/^\.\//,''));
-+                console.log("rule file loaded :" + ruleFilePath);
-+            }else{
-+                console.log(color.red("can not find rule file"));
-             }
--            console.log(color.green("rule file loaded"));
--        }else{
--            console.log(color.red("can not find rule file"));
-+        }catch(e){
-+            console.log("failed to load rule file :" + e.toString());
-         }
-     }
- 
-diff --git a/lib/requestHandler.js b/lib/requestHandler.js
-index 37f19d4..620b7f9 100644
---- a/lib/requestHandler.js
-+++ b/lib/requestHandler.js
-@@ -364,7 +364,7 @@ function setRules(newRule){
-         }
-         if('function' == typeof(userRule.summary)){
-             functions.push(function(cb){
--                userRule.summary();
-+                console.log(userRule.summary());
-                 cb(null);
-             });
-         }
-diff --git a/rule_sample/README.md b/rule_sample/README.md
-index 7a8eabb..7c29ff5 100644
---- a/rule_sample/README.md
-+++ b/rule_sample/README.md
-@@ -27,6 +27,9 @@ The following are sample rules.
- * rule_replace_response_status_code.js
-     * replace server's status code
-     * 改变服务端响应的http状态码
-+* rule_reverse_proxy.js
-+    * assign a specific ip address for request
-+    * 为请求绑定目标ip
- * rule_use_local_data.js
-     * map some requests to local file
-     * 把图片响应映射到本地
-\ No newline at end of file
diff --git a/lib/certMgr.js b/lib/certMgr.js
index 18dfde3..d9519e6 100644
--- a/lib/certMgr.js
+++ b/lib/certMgr.js
@@ -10,10 +10,10 @@ var exec = require('child_process').exec,
 
 //TODO : unstable in windows
 var certDir      = path.join(util.getUserHome(),"/.anyproxy_certs/"),
-    cmdDir       = path.join(__dirname,"..","./cert/"),
-    cmd_genRoot  = path.join(cmdDir,"./gen-rootCA"),
-    cmd_genCert  = path.join(cmdDir,"./gen-cer"),
-    asyncTaskMgr = new asyncTask();
+    cmdDir            = path.join(__dirname,"..","./cert/"),
+    cmd_genRoot       = path.join(cmdDir,"./gen-rootCA"),
+    cmd_genCert       = path.join(cmdDir,"./gen-cer"),
+    createCertTaskMgr = new asyncTask();
 
 if(!fs.existsSync(certDir)){
     try{
@@ -26,26 +26,31 @@ if(!fs.existsSync(certDir)){
     }
 }
 
-function getCertificate(hostname,cb){
+function getCertificate(hostname,certCallback){
+
     var keyFile = path.join(certDir , "__hostname.key".replace(/__hostname/,hostname) ),
         crtFile = path.join(certDir , "__hostname.crt".replace(/__hostname/,hostname) );
 
-    if(!fs.existsSync(keyFile) || !fs.existsSync(crtFile)){
-        asyncTaskMgr.addTask(hostname,function(cb){
+    createCertTaskMgr.addTask(hostname,function(callback){
+        if(!fs.existsSync(keyFile) || !fs.existsSync(crtFile)){
             createCert(hostname,function(err){
-                cb(err ? err : null);
+                if(err){
+                    callback(err);
+                }else{
+                    callback(null , fs.readFileSync(keyFile) , fs.readFileSync(crtFile));
+                }
             });
-        },function(err){
-            if(!err){
-                cb(null , fs.readFileSync(keyFile) , fs.readFileSync(crtFile) );
-            }else{
-                cb(err);
-            }
-        });
+        }else{
+            callback(null , fs.readFileSync(keyFile) , fs.readFileSync(crtFile));
+        }
 
-    }else{
-        cb(null , fs.readFileSync(keyFile) , fs.readFileSync(crtFile) );
-    }
+    },function(err,keyContent,crtContent){
+        if(!err){
+            certCallback(null ,keyContent,crtContent);
+        }else{
+            certCallback(err);
+        }
+    });
 }
 
 function createCert(hostname,callback){
diff --git a/lib/httpsServerMgr.js b/lib/httpsServerMgr.js
index f140f94..eb5148f 100644
--- a/lib/httpsServerMgr.js
+++ b/lib/httpsServerMgr.js
@@ -5,100 +5,61 @@ var getPort        = require('./getPort'),
     https          = require('https'),
     fs             = require('fs'),
     net            = require('net'),
-    url            = require('url'),
+    tls            = require('tls'),
     color          = require('colorful'),
     certMgr        = require("./certMgr"),
     asyncTask      = require("async-task-mgr");
 
-var DEFAULT_RELEASE_TIME = 2000;//120*1000;
+//using sni to avoid multiple ports
+function SNIPrepareCert(serverName,SNICallback){
+    var keyContent, crtContent,ctx;
 
-var asyncTaskMgr = new asyncTask();
-
-module.exports =function(){
-    var self = this;
-    self.serverList = {
-        /* schema sample 
-        "www.example.com":{
-            port:123,
-            server : serverInstance,
-            lastestUse: 99999 //unix time stamp
+    async.series([
+        function(callback){
+            certMgr.getCertificate(serverName,function(err,key,crt){
+                if(err){
+                    callback(err);
+                }else{
+                    keyContent = key;
+                    crtContent = crt;
+                    callback();
+                }
+            });
+        },
+        function(callback){
+            try{
+                ctx = tls.createSecureContext({
+                    key  :keyContent,
+                    cert :crtContent
+                });
+                callback();
+            }catch(e){
+                callback(e);
+            }
         }
-        */
-    };
-
-    //fetch a port for https server with hostname
-    this.fetchPort = function(hostname,userRequesthandler,userCB){
-        var serverInfo = self.serverList[hostname],
-            port;
-
-        //server exists
-        if(serverInfo){
-            serverInfo.lastestUse = new Date().getTime();
-            port = serverInfo.port;
-            userCB && userCB(null,port);
-
-        //create server with corresponding CA
+    ],function(err,result){
+        if(!err){
+            var tipText = "proxy server for __NAME established".replace("__NAME",serverName);
+            console.log(color.yellow(color.bold("[internal https]")) + color.yellow(tipText));
+            SNICallback(null,ctx);
         }else{
-
-            asyncTaskMgr.addTask(hostname, createServer ,userCB);
-
-            function createServer(cb){
-                async.series([
-                    //find a clean port
-                    function(callback){
-                        getPort(function(cleanPort){
-                            port = cleanPort;
-                            callback(null,port);
-                        });
-                    }
-
-                    //create server  
-                    ,function(callback){
-
-                        certMgr.getCertificate(hostname,function(err,keyContent,crtContent){
-                            var server = createHttpsServer(port,keyContent,crtContent,userRequesthandler);
-                            self.serverList[hostname] = {
-                                port   : port,
-                                server : server,
-                                lastestUse : new Date().getTime()
-                            };
-
-                            var tipText = "https server @port __portNum for __HOST established".replace(/__portNum/,port).replace(/__HOST/,hostname);
-                            console.log(color.yellow(color.bold("[internal https]")) + color.yellow(tipText));
-                            callback && callback(null,port);
-                            
-                        });
-                    }
-                ],function(err,result){
-                    cb && cb(err,result[result.length - 1]);
-
-                });                
-            }
+            console.log("err occurred when prepare certs for SNI - " + e);
         }
-    };
-
-    //clear servers which have been idle for some time
-    setInterval(function(){
-        var timeNow = new Date().getTime();
-        for(var serverName in self.serverList){
-            var item = self.serverList[serverName];
-            if( (timeNow - item.lastestUse) > DEFAULT_RELEASE_TIME){
-                item.server.close();
-                asyncTaskMgr.removeTask(serverName);
-                delete self.serverList[serverName];
-
-                console.log(color.yellow(color.bold("[internal https]")) + color.yellow("https server released : " + serverName));
-            }
-        }
-
-    },DEFAULT_RELEASE_TIME);
+    });
 }
 
-function createHttpsServer(port,keyContent,crtContent,userRequesthandler){
-    return https.createServer({
-        key : keyContent,
-        cert: crtContent
-    },userRequesthandler).listen(port);
+//config.port - port to start https server
+//config.handler - request handler
+module.exports =function(config){
+    var self = this;
 
+    if(!config || !config.port ){
+        throw(new Error("please assign a port"));
+    }
+
+    https.createServer({
+        SNICallback : SNIPrepareCert
+    },config.handler).listen(config.port);
 }
 
+
diff --git a/lib/requestHandler.js b/lib/requestHandler.js
index 620b7f9..bda9ff7 100644
--- a/lib/requestHandler.js
+++ b/lib/requestHandler.js
@@ -9,11 +9,11 @@ var http           = require("http"),
     color          = require("colorful"),
     Buffer         = require('buffer').Buffer,
     util           = require("./util"),
+    getPort        = require("./getPort"),
     Stream         = require("stream"),
     httpsServerMgr = require("./httpsServerMgr");
 
-var httpsServerMgrInstance = new httpsServerMgr(),
-    defaultRule            = require("./rule_default.js"),
+var defaultRule            = require("./rule_default.js"),
     userRule               = defaultRule; //init
 
 function userRequestHandler(req,userRes){
@@ -270,26 +270,40 @@ function connectReqHandler(req, socket, head){
     };
     resourceInfoId = GLOBAL.recorder.appendRecord(resourceInfo);
 
-    var proxyPort, proxyHost;
+    var proxyPort,
+        proxyHost,
+        internalHttpsPort,
+        httpsServerMgrInstance;
+
+
     async.series([
 
-        //find port 
+        //check if internal https server exists
+        function(callback){
+            if(internalHttpsPort){
+                callback();
+            }else{
+                getPort(function(port){
+                    internalHttpsPort = port;
+                    httpsServerMgrInstance = new httpsServerMgr({
+                        port    :port,
+                        handler :userRequestHandler
+                    });
+                    callback();
+                });
+            }
+        },
+
+        //determine the target server
         function(callback){
             
             if(shouldIntercept){
-                //TODO : remote port other than 433
-                httpsServerMgrInstance.fetchPort(host,userRequestHandler,function(err,port){
-                    if(!err && port){
-                        proxyPort = port;
-                        proxyHost = "127.0.0.1";
-                        callback();
-                    }else{
-                        callback(err);
-                    }
-                });
+                proxyPort = internalHttpsPort;
+                proxyHost = "127.0.0.1";
+                callback();
 
             }else{
-                proxyPort = targetPort;
+                proxyPort = 443;
                 proxyHost = host;
 
                 callback();
@@ -305,7 +319,6 @@ function connectReqHandler(req, socket, head){
                         if(GLOBAL._throttle && !shouldIntercept ){
                             var readable = conn.pipe(GLOBAL._throttle.throttle());
                             readable.pipe(socket);
-
                             socket.pipe(conn);
                         }else{
                             conn.pipe(socket);