#!/usr/bin/luaweb
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
        else 
            f = io.open("/data/ipconfig.lua","r")
            if f ~= nil then
                dofile("/data/ipconfig.lua")
            end
        end
    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")
            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")

            if my_ip_address_table~=nil then
                --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")
            end

            --flush
            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")

            if my_ip_address_table6~=nil then
                --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")
            end
        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
            if my_ip_address_table~=nil 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
            end
        else
            if my_ip_address_table~=nil 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") .. " 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
end

