#!/usr/bin/lua
json = require("json")
omg = require("omg")

dofile("/data/config.lua")

-- correct some config Settings
if config~=nil and config.struct_Box~=nil and config.struct_Box.struct_DChannel~=nil then
   if config.struct_Box.struct_DChannel[1]==nil then
      local t = {}
      t = config.struct_Box.struct_DChannel
      config.struct_Box.struct_DChannel = nil
      config.struct_Box.struct_DChannel = {}
      config.struct_Box.struct_DChannel[1]=t
      for k,v in ipairs(config.struct_Box.struct_DChannel) do
         if(config.struct_Box.struct_DChannel[k].struct_GateParams ~= nil) then
            if(config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTable ~= nil) then
               if(config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTable[1] == nil) then
                  t = config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTable
                  config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTable = nil
                  config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTable = {}
                  config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTable[1]=t
               end
            end
            if(config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTableOut ~= nil) then
               if(config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTableOut[1] == nil) then
                  t = config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTableOut
                  config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTableOut = nil
                  config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTableOut = {}
                  config.struct_Box.struct_DChannel[k].struct_GateParams.struct_CallProcTableOut[1]=t
               end
            end
         end
      end
   end

   ip="/sbin/iptables "
   ip6="/sbin/ip6tables "

   local f
   if io ~= nil and io.open ~= nil then
      f = io.open("/data/ipconfig.json","r")
      if f ~= nil then
         local content = f:read("*all")
         if content ~= nil then
            ip_address_table = json.decode(content)
         end
      end
   elseif f==nil and io ~= nil and io.open ~= nil then
      f = io.open("/data/ipconfig.lua","r")
      dofile("/data/ipconfig.lua")
   end

   if f then
      io.close(f)
      if ip_address_table ~= nil then
         my_ip_address_table = ip_address_table["V4"]
         my_ip_address6_table = ip_address_table["V6"]
      end

      if ip_address_table == nil or ip_address_table.disablefirewall~=true then
         --flush
         os.execute(ip .. "-F")
         os.execute(ip .. "-X")
         os.execute(ip .. "-Z")
         os.execute(ip .. "-t nat -F")

         --set default policies
         os.execute(ip .. "-P INPUT DROP")
         os.execute(ip .. "-P OUTPUT DROP")
         os.execute(ip .. "-P FORWARD DROP")

         --keep established connections
         os.execute(ip .. "-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT")
         --allow loopback
         os.execute(ip .. "-A INPUT -i lo -j ACCEPT")
         --allow outbound traffic
         os.execute(ip .. "-A OUTPUT -j ACCEPT")

         --allow certain inbound connections
         for k,v in pairs(my_ip_address_table) do
            local src
            local additional

            src=nil
            additional=nil

            if v.src and v.src~="" then
               src=" -s " .. v.src
            end

            if v.additional and v.additional~="" then
               additional=" " .. v.additional
            end

            if v.tlsSip then
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. config.struct_Box.string_SipTlsBindPort .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.tcpSip then
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. config.struct_Box.string_SipBindPort .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.udpSip then
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p udp --dport " .. config.struct_Box.string_SipBindPort .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.tlsSip or v.tcpSip or v.udpSip then 
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p udp --dport " .. "7004:7124" .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.website then
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. "80" .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.messagingServer then
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. "3217:3233" .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.snfs or v.management or v.messagingServer then
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. "3215" .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.license or v.management or v.messagingServer then
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. "3214" .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.management then
               --Allows SSH connections (only 16 attempts by an IP every 1 minute, drop the rest)
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource" .. (src or "") .. (additional or ""))
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 16 --name DEFAULT --rsource -j DROP" .. (src or "") .. (additional or ""))
               os.execute(ip .. "-A INPUT -d " .. v.ip .. " -p tcp -m state --state NEW --dport 22 -j ACCEPT" .. (src or "") .. (additional or ""))
            end
         end
         --Allow ping
         os.execute(ip .. "-A INPUT -p icmp -m icmp --icmp-type 58 -j ACCEPT")
         -- Reject all other inbound - default deny unless explicitly allowed policy
         os.execute(ip .. "-A INPUT -j DROP")
         os.execute(ip .. "-A FORWARD -j DROP")


         --flush
         os.execute(ip6 .. "-F")
         os.execute(ip6 .. "-X")
         os.execute(ip6 .. "-Z")

         --set default policies
         os.execute(ip6 .. "-P INPUT DROP")
         os.execute(ip6 .. "-P OUTPUT DROP")
         os.execute(ip6 .. "-P FORWARD DROP")

         --keep established connections
         os.execute(ip6 .. "-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT")
         --allow loopback
         os.execute(ip6 .. "-A INPUT -i lo -j ACCEPT")
         --allow outbound traffic
         os.execute(ip6 .. "-A OUTPUT -j ACCEPT")

         for k,v in pairs(my_ip_address6_table) do
            local src
            local additional

            src=nil
            additional=nil

            if v.src and v.src~="" then
               src=" -s " .. v.src
            end

            if v.additional and v.additional~="" then
               additional=" " .. v.additional
            end

            if v.tlsSip then
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. config.struct_Box.string_SipTlsBindPort .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.tcpSip then
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. config.struct_Box.string_SipBindPort .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.udpSip then
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p udp --dport " .. config.struct_Box.string_SipBindPort .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.tlsSip or v.tcpSip or v.udpSip then 
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p udp --dport " .. "7004:7124" .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.website then
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. "80" .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.messagingServer then
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. "3217:3233" .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.snfs or v.management or v.messagingServer then
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. "3215" .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.license or v.management or v.messagingServer then
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p tcp --dport " .. "3214" .. " -j ACCEPT" .. (src or "") .. (additional or ""))
            end

            if v.management then
               --Allows SSH connections (only 16 attempts by an IP every 1 minute, drop the rest)
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource" .. (src or "") .. (additional or ""))
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 16 --name DEFAULT --rsource -j DROP" .. (src or "") .. (additional or ""))
               os.execute(ip6 .. "-A INPUT -d " .. v.ip .. " -p tcp -m state --state NEW --dport 22 -j ACCEPT" .. (src or "") .. (additional or ""))
            end
         end

         --Allow ping
         os.execute(ip6 .. "-A INPUT -p icmpv6 -m ipv6-icmp --icmpv6-type 58 -j ACCEPT")
         -- Reject all other inbound - default deny unless explicitly allowed policy
         os.execute(ip6 .. "-A INPUT -j DROP")
         os.execute(ip6 .. "-A FORWARD -j DROP")

         --prepare network routings
         -- you search for the folo9owing syntax every time ;-) :
         -- route del -net 172.17.0.0 netmask 255.255.0.0
         -- route del 172.17.0.1
      else
         os.execute(ip .. "-F")
         os.execute(ip .. "-X")
         os.execute(ip .. "-Z")
         os.execute(ip .. "-t nat -F")
         os.execute(ip .. "-t nat -X")
         os.execute(ip .. "-t mangle -F")
         os.execute(ip .. "-t mangle -X")
         os.execute(ip .. "-P INPUT ACCEPT")
         os.execute(ip .. "-P OUTPUT ACCEPT")
         os.execute(ip .. "-P FORWARD ACCEPT")

         os.execute(ip6 .. "-F")
         os.execute(ip6 .. "-X")
         os.execute(ip6 .. "-Z")
         os.execute(ip6 .. "-P INPUT ACCEPT")
         os.execute(ip6 .. "-P OUTPUT ACCEPT")
         os.execute(ip6 .. "-P FORWARD ACCEPT")
      end

      if ip_address_table == nil or ip_address_table.disablerouting~=true then
         for k,v in pairs(my_ip_address_table) do
            if my_ip_address_table[k].route ~= nil then
               for k2,v2 in pairs(my_ip_address_table[k].route) do
                  local cmd,cmd2
                  if v2.net then
                     cmd="route del -net " ..  (v2.ip or "NIL") .. " netmask " .. (v2.mask or "NIL") .. " gw " .. (v2.gw or "NIL")
                     cmd2="route add -net " ..  (v2.ip or "NIL") .. " netmask " .. (v2.mask or "NIL") .. " gw " .. (v2.gw or "NIL")
                  else
                     cmd="route del " ..  (v2.ip or "NIL") .. " gw " .. (v2.gw or "NIL")
                     cmd2="route add " ..  (v2.ip or "NIL") .. " gw " .. (v2.gw or "NIL")
                  end
                  print(cmd)
                  os.execute(cmd)
                  print(cmd2)
                  os.execute(cmd2)
               end
            end
         end
      else
         for k,v in pairs(my_ip_address_table) do
            if my_ip_address_table[k].route ~= nil then
               for k2,v2 in pairs(my_ip_address_table[k].route) do
                  local cmd,cmd2
                  if v2.net then
                     cmd="route del -net " ..  (v2.ip or "NIL") .. " netmask " .. (v2.mask or "NIL") .. " gw " .. (v2.gw or "NIL") .. " 2>/dev/null"
                  else
                     cmd="route del " ..  (v2.ip or "NIL") .. " gw " .. (v2.gw or "NIL") .. " 2>/dev/null"
                  end
                  print(cmd)
                  os.execute(cmd)
               end
            end
         end
      end
   end
end

