diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,8 @@
+1.0.0.30
+--------
+* Add `deny-list` option to specify an access control list file for blocking a
+    large list of IPs.
+
 1.0.0.20
 --------
 * Fix respect '--disable-socks5'
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -53,7 +53,7 @@
 * TCP per connection throttling (as a side effect of trying to find a bug in the
 remote)
 * SOCKS5 service on local can be turned off
-* Understand ss' configuration file
+* Understand ss's configuration file
 
 Drawbacks
 ==========
@@ -97,24 +97,6 @@
 
     tcpdump port 8388 -i any -X -v
 
-Explicit Congestion Notification ([ECN])
-=========================================
-
-## No buffer by default
-
-After version v1.0.0.0, moesocks will default to no buffer at the application
-level. Smart buffer is expected from the kernel.
-
-In app buffer can still be tuned on by setting "tcpBufferSize" in
-`config.json` a value greater then 1.
-
-## Force ECN
-
-On Linux 2.4.20+ (as root)
-
-    echo 1 > /proc/sys/net/ipv4/tcp_ecn
-
-ECN is recommended only on `remote`.
 
 Credits
 =======
diff --git a/moesocks.cabal b/moesocks.cabal
--- a/moesocks.cabal
+++ b/moesocks.cabal
@@ -1,6 +1,6 @@
 name:               moesocks
 category:           Network
-version:            1.0.0.20
+version:            1.0.0.30
 license:            Apache-2.0
 synopsis:           A functional firewall killer
 description:        A SOCKS5 proxy using the client / server architecture.
diff --git a/src/Network/MoeSocks/Common.hs b/src/Network/MoeSocks/Common.hs
--- a/src/Network/MoeSocks/Common.hs
+++ b/src/Network/MoeSocks/Common.hs
@@ -16,28 +16,39 @@
 
 makePrisms ''IPRange
 
-checkForbidden_IP_List :: AddressType -> [IPRange] -> Bool
-checkForbidden_IP_List _address@(IPv4_Address _) aForbidden_IP_List =
+check_IP_List :: AddressType -> [IPRange] -> Bool
+check_IP_List _address@(IPv4_Address _) a_IP_List =
   isJust - 
     do
       _ip <- show _address  ^? _Show
-      findOf (each . _IPv4Range) (isMatchedTo _ip) aForbidden_IP_List
+      findOf (each . _IPv4Range) (isMatchedTo _ip) a_IP_List
 
-checkForbidden_IP_List _address@(IPv6_Address _) aForbidden_IP_List =
+check_IP_List _address@(IPv6_Address _) a_IP_List =
   isJust -
     do
       _ip <- show _address ^? _Show
-      findOf (each . _IPv6Range) (isMatchedTo _ip) aForbidden_IP_List
+      findOf (each . _IPv6Range) (isMatchedTo _ip) a_IP_List
 
-checkForbidden_IP_List _ _ = False
+check_IP_List _ _ = False
 
-withCheckedForbidden_IP_List :: AddressType -> [IPRange] -> IO a -> IO ()
-withCheckedForbidden_IP_List aAddressType aForbidden_IP_List aIO = 
-  if checkForbidden_IP_List aAddressType aForbidden_IP_List 
+withChecked_IP_List :: AddressType -> ([IPRange], Maybe [IPRange]) 
+                        -> IO a -> IO ()
+withChecked_IP_List aAddressType (aDenyList, aAllowList) aIO = 
+  if check_IP_List aAddressType aDenyList
     then error_ - show aAddressType
-                <> " is in forbidden-ip list"
-    else () <$ aIO
+                <> " is in the denied list"
+    else 
+      case aAllowList of
+        Nothing -> () <$ aIO
+        Just _allowList ->
+          if not - check_IP_List aAddressType _allowList
+            then error_ - show aAddressType
+                    <> " is NOT in the allowed list"
+            else
+              () <$ aIO
 
+getIPLists :: Env -> ([IPRange], Maybe [IPRange])
+getIPLists aEnv = (aEnv ^. denyList <> aEnv ^. forbidden_IPs, mempty)
 
 showConnectionType :: ConnectionType -> String
 showConnectionType TCP_IP_StreamConnection = "TCP_Stream"
diff --git a/src/Network/MoeSocks/Default.hs b/src/Network/MoeSocks/Default.hs
--- a/src/Network/MoeSocks/Default.hs
+++ b/src/Network/MoeSocks/Default.hs
@@ -75,7 +75,7 @@
 defaultOptions = O.Options
   {
     O._runningMode = O.DebugMode
-  , O._configFile = Nothing
+  , O._configFile = mempty
   , O._verbosity = DEBUG
   , O._forward_TCPs = []
   , O._forward_UDPs = []
@@ -84,10 +84,11 @@
   , O._listMethods = False
   , O._showDefaultConfig = False
   , O._params = []
+  , O._denyList = mempty
   } 
 
-parseForbidden_IPs :: [Text] -> [IPRange]
-parseForbidden_IPs =
+parseIPRangeList :: [Text] -> [IPRange]
+parseIPRangeList =
                     toListOf $ each
                               . to T.strip
                               . _Text
@@ -110,7 +111,8 @@
     , _socketOption_TCP_NOTSENT_LOWAT = _c ^. C.socketOption_TCP_NOTSENT_LOWAT
     , _obfuscation                    = _o ^. O.obfuscation
     , _forbidden_IPs                  = _c ^. C.forbidden_IPs 
-                                            & parseForbidden_IPs
+                                            & parseIPRangeList
+    , _denyList                       = []
     {-, _config = defaultConfig-}
     , _cipherBox = let (a,b,c,d) = constCipherBox in CipherBox a b c d
   }
diff --git a/src/Network/MoeSocks/Options.hs b/src/Network/MoeSocks/Options.hs
--- a/src/Network/MoeSocks/Options.hs
+++ b/src/Network/MoeSocks/Options.hs
@@ -97,6 +97,12 @@
                   <>  metavar "CONFIG"
                   <>  help "Set the path of the configuration file"
 
+      _denyList = optional - textOption -
+                        long "deny-list"
+                    <>  metavar "ACL"
+                    <>  help "Block IPs from an access control list file."
+                              
+
       _remoteHost = textParam -
                       short 's'
                   <>  metavar "REMOTE"
@@ -265,6 +271,7 @@
               <*> _listMethods
               <*> _showDefaultConfig
               <*> _params
+              <*> _denyList 
 
 opts :: ParserInfo Options
 opts = info (helper <*> optionParser) -
diff --git a/src/Network/MoeSocks/Runtime.hs b/src/Network/MoeSocks/Runtime.hs
--- a/src/Network/MoeSocks/Runtime.hs
+++ b/src/Network/MoeSocks/Runtime.hs
@@ -4,20 +4,25 @@
 module Network.MoeSocks.Runtime where
 
 import Control.Lens
-import Control.Monad.Writer hiding (listen)
 import Control.Monad.Except
-import Network.MoeSocks.Helper
-import Network.MoeSocks.Type
+import Control.Monad.Writer hiding (listen)
+import Data.IP
+{-import Data.List (intercalate)-}
+{-import Data.Text (Text)-}
+import Data.Text.IO as T
+import Data.Text.Lens
 import Network.MoeSocks.Bootstrap
-import Network.MoeSocks.Encrypt
 import Network.MoeSocks.Default
-import Data.Text.Lens
-import qualified Network.MoeSocks.Type.Bootstrap.Config as C
-import qualified Network.MoeSocks.Type.Bootstrap.Option as O
+import Network.MoeSocks.Encrypt
+import Network.MoeSocks.Helper
+import Network.MoeSocks.Type
 import Prelude hiding ((-), take)
 import System.Log.Formatter
 import System.Log.Handler.Simple
 import System.Log.Logger
+import qualified Data.Text as T
+import qualified Network.MoeSocks.Type.Bootstrap.Config as C
+import qualified Network.MoeSocks.Type.Bootstrap.Option as O
 import qualified System.IO as IO
 import qualified System.Log.Handler as LogHandler
 
@@ -112,8 +117,23 @@
                             <> _method ^. _Text
     Just (a, b, c, d) -> pure - CipherBox a b c d
 
+  let _readDenyList :: IO [IPRange]
+      _readDenyList = 
+        case someOptions ^. O.denyList of
+          Nothing -> pure []
+          Just _denyListPath ->
+            T.readFile (_denyListPath ^. _Text)
+              <&> T.lines 
+              <&> parseIPRangeList
+                
+
+  _denyList <- io - _readDenyList
+
+  io - debug_ - "denyList: " <> show (length _denyList) <> " items"
+
   let _env = defaultEnv
               & cipherBox .~ _cipherBox
+              & denyList .~ _denyList
 
   pure - _env
 
@@ -135,7 +155,7 @@
         & socketOption_TCP_NOTSENT_LOWAT .~ _s
         & obfuscation                    .~ _o ^. O.obfuscation
         & forbidden_IPs                  .~ (_c ^. C.forbidden_IPs
-                                                & parseForbidden_IPs)
+                                                & parseIPRangeList)
                                             
                                         
   
diff --git a/src/Network/MoeSocks/TCP.hs b/src/Network/MoeSocks/TCP.hs
--- a/src/Network/MoeSocks/TCP.hs
+++ b/src/Network/MoeSocks/TCP.hs
@@ -92,10 +92,10 @@
                         (_partialBytesAfterClientRequest, _clientRequest) 
                         shouldReplyClient aSocket = do
   let _addr = _clientRequest ^. addressType
-      _forbidden_IPs = aEnv ^. forbidden_IPs
+      _IPLists = getIPLists aEnv
 
-  debug_ - "checking: " <> show _addr <> " ? " <> show _forbidden_IPs
-  withCheckedForbidden_IP_List _addr _forbidden_IPs - do
+  debug_ - "checking: " <> show _addr 
+  withChecked_IP_List _addr _IPLists - do
     let 
         _cipherBox = aEnv ^. cipherBox
         _obfuscation = aEnv ^. obfuscation
@@ -234,10 +234,10 @@
   logSA "R target socket" (initTarget _clientRequest) - \_r -> do
     let (_targetSocket, _targetHost) = _r 
         (_addr, _) = sockAddr_To_Pair _targetHost
-        _forbidden_IPs = aEnv ^. forbidden_IPs
+        _IPLists = getIPLists aEnv
 
-    debug_ - "checking: " <> show _addr <> " ? " <> show _forbidden_IPs
-    withCheckedForbidden_IP_List _addr _forbidden_IPs - do
+    debug_ - "checking: " <> show _addr 
+    withChecked_IP_List _addr _IPLists - do
       setSocketConfig aEnv _targetSocket
 
       _remotePeerAddr <- getPeerName aSocket
diff --git a/src/Network/MoeSocks/Type/Bootstrap/Option.hs b/src/Network/MoeSocks/Type/Bootstrap/Option.hs
--- a/src/Network/MoeSocks/Type/Bootstrap/Option.hs
+++ b/src/Network/MoeSocks/Type/Bootstrap/Option.hs
@@ -24,6 +24,7 @@
   , _listMethods :: Bool
   , _showDefaultConfig :: Bool
   , _params :: [(Text, Value)]
+  , _denyList :: Maybe Text
   }
   deriving (Show, Eq)
 
diff --git a/src/Network/MoeSocks/Type/Runtime.hs b/src/Network/MoeSocks/Type/Runtime.hs
--- a/src/Network/MoeSocks/Type/Runtime.hs
+++ b/src/Network/MoeSocks/Type/Runtime.hs
@@ -131,6 +131,7 @@
   , _socketOption_TCP_NOTSENT_LOWAT :: Bool
   , _obfuscation :: Bool
   , _forbidden_IPs :: [IPRange]
+  , _denyList :: [IPRange]
   , _cipherBox :: CipherBox
   }
 
diff --git a/src/Network/MoeSocks/UDP.hs b/src/Network/MoeSocks/UDP.hs
--- a/src/Network/MoeSocks/UDP.hs
+++ b/src/Network/MoeSocks/UDP.hs
@@ -64,11 +64,11 @@
   {-debug_ - "L UDP: " <> show _clientRequest-}
 
   let _addr = _clientRequest ^. addressType
-      _forbidden_IPs = aEnv ^. forbidden_IPs
+      _IPLists = getIPLists aEnv
 
-  debug_ - "checking: " <> show _addr <> " ? " <> show _forbidden_IPs
+  debug_ - "checking: " <> show _addr 
 
-  withCheckedForbidden_IP_List _addr _forbidden_IPs - do
+  withChecked_IP_List _addr _IPLists - do
     _sa <- getSocket aRemoteHost aRemotePort Datagram
 
     logSA "L UDP -->:" (pure _sa) -
@@ -130,10 +130,10 @@
 
     let (_targetSocket, _targetSocketAddress) = _r
         (_addr, _) = sockAddr_To_Pair _targetSocketAddress
-        _forbidden_IPs = aEnv ^. forbidden_IPs
+        _IPLists = getIPLists aEnv
 
-    debug_ - "checking: " <> show _addr <> " ? " <> show _forbidden_IPs
-    withCheckedForbidden_IP_List _addr _forbidden_IPs - do
+    debug_ - "checking: " <> show _addr 
+    withChecked_IP_List _addr _IPLists - do
       let _msg = showRelay aSockAddr _clientRequest
       info_ - "RU: " <> _msg
 
