6S@sdZddlZddlZddlZddlZddlZddlZddlmZm Z ddl m Z m Z m Z mZmZddlZGdddejjZdS)z-backend_iptables.py: iptables backend for ufwN)UFWErrorUFWRule)warndebugmsgcmdcmd_pipec@s eZdZdZddZddZddZdd Zd d d d Zd dZ ddZ ddZ ddZ ddZ ddZddZd ddZdddZd d!Zd d"d#Zd$d%Zd&d'Zd(d)Zd*S)+UFWBackendIptableszInstance class for UFWBackendcCsDdtjjd|_i}tjjtjjd|ddddgD]-}d|||f}|j |j|qWqW|j dj|d|j dj|dqDWdd d!d"d#d$d%g|_d&|_d'S)(z!UFWBackendIptables initializationz# z _comment #z user.rulesruleszufw/before.rulesZ before_ruleszufw/after.rules after_rulesz user6.rulesrules6zufw/before6.rulesZ before6_ruleszufw/after6.rules after6_ruleszufw-initinitiptablesbeforeuseraftermisc46ufwinputoutputforwardz%s-%s-logging-%sz -logging-denyz-logging-allowz-mlimitz--limitz3/minutez-jLOGz --log-prefixz[UFW LIMIT BLOCK]N)rcommonZ programNameZ comment_strospathjoinZ state_dirZ config_dirbackend UFWBackend__init__chainsuse_ipv6appendufw_user_limit_logufw_user_limit_log_text)selfdryrunfilesZver chain_prefixloctargetchainr/6/usr/lib/python3/dist-packages/ufw/backend_iptables.pyr" sB     %       zUFWBackendIptables.__init__cCsztd}|jddkr,|d7}nJ|jddkrL|d7}n*|jddkrl|d7}n |d 7}|S) zGet current policyz New profiles:Zdefault_application_policyacceptz allowZdropz denyrejectz rejectz skip)_defaults)r(rstrr/r/r0get_default_application_policyKs     z1UFWBackendIptables.get_default_application_policyc Cs|js|dkrL|dkrL|dkrLtd|}t|n|dkr|dkr|dkrtd|}t|nd }|dkrd }n|dkrd }nd }d }|dkr y"|j|jd d|dWntk rYnXd}d}n|dkruy"|j|jd d|dWntk reYnXd}d}nFy"|j|jd d|dWntk rYnXd}d}tjd |}x|jd|jdgD]}ytj j |} Wntk rYnX| d} xV| dD]J} |j | ritj j | |j || q2tj j | | q2Wytj j| Wqtk rYqXqWntdi|d6|d6} | td7} | S)zSets default policy of firewallallowdenyr2zUnsupported policy '%s'ZincomingZoutgoingroutedz%Unsupported policy for direction '%s'INPUTOUTPUTFORWARDr4zDEFAULT_%s_POLICYz"ACCEPT"z UFW BLOCKz UFW ALLOWz"REJECT"z"DROP"r r tmporigz5Default %(direction)s policy changed to '%(policy)s' directionpolicyz*(be sure to update your rules accordingly))r)r3rZ set_defaultr* Exceptionrecompilerutil open_filessearch write_to_filesub close_files) r(rAr@err_msgr.Z old_log_strZ new_log_strpatffnsfdliner5r/r/r0set_default_policyYsz $                !  "  z%UFWBackendIptables.set_default_policyc CsT|jr1dtd}|dtd7}|S|jddddg}g}g}|dkr|jd d d d dg}d d dg}n|d krx9dddgD](}|jd||jd|qWx?dddddgD](}|jd||jd|qWx6ddgD](}|jd||jd|q-Wx+dddgD]}|jd|qiWn|dkrxdddgD](}|jd||jd|qWn|dkryx9dddgD](}|jd||jd|qW|jd d!rH|jd"|jd#n|jd d$r|jd%|jd&qn|d'krxdddgD](}|jd(||jd)|qWn|d*krx}dddgD]l}|jd+||jd,||jd-||jd.||jd/||jd0|qW|jd1|jd2|jd3|jd4nd5|}x|D]}d6|kr|jd6\} }|d7| 7}t|jg||d | g\} } n#t|jg||g\} } || 7}|dkr?|d87}n| d9krt|qqW|dksv|j rP|d:7}x|D]}d6|kr|jd6\} }|d7| 7}t|jg||d | g\} } n#t|j g||g\} } || 7}|dkr.|d87}n| d9krt|qqWn|S);z'Show current running status of firewallz> zChecking raw iptables zChecking raw ip6tables z-nz-vz-xz-Lrawz-tfilterZnatZmanglebuiltinsr:r<r;z filter:%sZ PREROUTINGZ POSTROUTINGz mangle:%szraw:%sznat:%srrrrz ufw-before-%szufw6-before-%srz ufw-user-%sz ufw6-user-%srrzufw-user-limit-acceptzufw-user-limitrzufw6-user-limit-acceptzufw6-user-limitrz ufw-after-%sz ufw6-after-%sZloggingzufw-before-logging-%szufw6-before-logging-%szufw-user-logging-%szufw6-user-logging-%szufw-after-logging-%szufw6-after-logging-%szufw-logging-allowzufw-logging-denyzufw6-logging-allowzufw6-logging-denyz IPV4 (%s): :z(%s)  rz IPV6: ) r)r3initcapsr%capssplitrrrr$ ip6tables) r(Z rules_typeoutargsitemsZitems6cbitrcr>r/r/r0get_running_raws                  ,#       ,#    z"UFWBackendIptables.get_running_rawFc#Cs d}|jrFdtd}|jrB|dtd7}n|Std}xdddgD]}t|jd d |d g\}}|d krtd S|dkrt|d|n|jrbt|jd d|d g\}}|dkrt|dqqbqbWd}d} d} |j|j} d } i} xt| D]l}d}i}d}d}| r|j dks|j dkrd}|j }|| krt d|qRqd| | zChecking iptables zChecking ip6tables zproblem runningrrrz-Lz ufw-user-%sz-nzStatus: inactiverz iptables: %s z ufw6-user-%sz ip6tablesTFzSkipping found tuple '%s'dstsrcz::/0z (v6)z 0.0.0.0/0any /z (%s)ZAnywherez on %sr[z (%s)z, z[%2d] ZFWDinz%-26s %-12s%s%s z z ZToZFromZActionz%-26s %-12s%s -rVzDefault: %(in)s (incoming), z%(out)s (outgoing), z%(routed)s (routed)r9z0Status: active %(log)s %(pol)s %(app)s%(status)slogZpolZappZstatuszStatus: active%sN)!r)r3r$rrrrZr r dappsapp get_app_tuplerrev6dportrfsportprotocolr interface_in interface_outlogtyper@lowerr%lenrupperactionZ get_loglevel_get_default_policyr6)#r(verboseZ show_countr[rKr@rbZout6sZstr_outZstr_rter count app_rulesrZtmp_strlocationtuplZ show_protor,Zportr>ZattribsZ attrib_strZdir_strZfull_strZstr_toZstr_fromZ str_actionZrules_header_fmtZ rules_headerlevelZ logging_strZ policy_strZapp_policy_strr/r/r0 get_statussL           %                $ '            $                  zUFWBackendIptables.get_statuscCsn|jr tdtdnJt|jddg\}}|dkrjtd|}t|ndS)zStop the firewallz> zrunning ufw-initrz force-stoprzproblem running ufw-init %sN)r)rr3rr*r)r(rbr[rKr/r/r0 stop_firewalls   z UFWBackendIptables.stop_firewallc Cs%|jr tdtdnt|jddg\}}|dkrjtd|}t|nd|jks|jdt|jj kry|j dWq!t k rtd }t|Yq!XnEy|j |jdWn*t k r td }t|YnXd S) zStart the firewallz> zrunning ufw-initrstartrzproblem running ufw-init %sloglevellowzCould not set LOGLEVELzCould not load logging rulesN) r)rr3rr*rr4list loglevelskeysZ set_loglevelrBupdate_logging)r(rbr[rKr/r/r0start_firewalls$  "    z!UFWBackendIptables.start_firewallcCs|jr dS|jd}|j}|r>d}|j}nxdddddgD]}|dksr|dkr|r|jdd  rqTq| r|jdd  rqTqnt|d d |d |g\}}|dkrTtddSqTWdS)zCheck if all chains existFrufw6rrrrz limit-acceptrrz-nz-Lz-user-rz_need_reload: forcing reloadT)r)rWrrZrXrr)r(rqprefixexer.rbr[r/r/r0 _need_reloads&     &  zUFWBackendIptables._need_reloadc CsZtd}|jr;td|jrVtdqVn|jrVyHxA|jdD]2}|j|d|g|j|d|gqXWWntk rt|YnXt d|j dg|j d g\}}|d krt|d n|jrVt d|j d g|j d g\}}|d krSt|d qSqVndS)zReload firewall rules filezproblem runningz> | iptables-restorez> | ip6tables-restorerz-Fz-Zcatr z-nrz iptablesr z ip6tablesN) r3r)rr$ is_enabledr# _chain_cmdrBrrr*Ziptables_restoreZip6tables_restore)r(rKr^rbr[r/r/r0_reload_user_rules s*         z%UFWBackendIptables._reload_user_rulescCs,g}tjd}tjd}tjd}|j|r|j|r|j|r|j|jd|jd|n|j|jd||j|jd|q|j|jd|n |j|tjd}tjd } tjd } d } xVt|D]H\} } |j| r&|jd | j}|jd krtd}n!|jdkrd}nd}d| |f}| j| sd|}n|jd| || <|j| |jd|d|| |j| | jd|d||jd| |j| | jd|d||jd|| q&q&Wtjd}xt|D]\} } |j| r|jd| }|jddd|d| }|jd|d | }||| <|j| ||j| |qqW|S)!z5Return list of iptables rules appropriate for sendingz-p all zport z-j (REJECT(_log(-all)?)?)z-p tcp z-j \1 --reject-with tcp-resetz-p udp r=z(.*)-j ([A-Z]+)_log(-all)?(.*)z-j [A-Z]+_log-allz(-A|-D) ([a-zA-Z0-9\-]+)z'-m limit --limit 3/min --limit-burst 10z\2r1ZALLOWrZLIMITZBLOCKz"%s -j LOG --log-prefix "[UFW %s] "z-m conntrack --ctstate NEW z \1-j \2\4z\1-j z-user-logging-z\1 z \1-j RETURNz\1z -j LIMITz+ -m conntrack --ctstate NEW -m recent --setz% -m conntrack --ctstate NEW -m recentz# --update --seconds 30 --hitcount 6z -j z -user-limitz-user-limit-accept) rCrDrGr%rI enumeratestriprxinsert)r(frulersuffixsnippetsZ pat_protoZpat_portZ pat_rejectpat_logZ pat_logallZ pat_chain limit_argsr`r~rAZlstrZ pat_limitZtmp1Ztmp2Ztmp3r/r/r0_get_rules_from_formatted<sh        !   z,UFWBackendIptables._get_rules_from_formattedc Csg}|j|||}tjd}xt|D]\}}|j|jd|j|j|r7||jd||j|jd|jdd|||jd|j7td | } t| qq~d } d} d}t| d kstt| d krtd| } | d#j dd} d| d$krd| d%kr,|j| d&r,|j| d'r,| d(j ddjdd} | d)j ddjdd}q| d*jdrY| d+jdd} q| d,jdr| d-jdd}qt| qqny`| d}d}d|krd}|j dd}nt| dkrt|| d| d| d| d| d| |}nt|| d| d| d| d| d| |}t j d}| d dkr|j d| d |_n| d dkr|j d| d |_n| dkr|jd | n|dkr|jd |nWn/tk r*td!| }t|wYnX||jdkr^|jd|jj|q~|jd|jj|qqW|jq:Wd"S).z$Read in rules that were added by ufwr r zCouldn't open '%s' for readingz^### tuple ###\s*zin_\w+zout_\w+r=z\s+ z)Skipping malformed tuple (bad length): %srkz$Skipping malformed tuple (iface): %srdr3r!Zin_Zout_FrUTz%20rlrhr[zSkipping malformed tuple: %sNrrrrrrrrrr)r*r$r%rrEZopen_file_readrBr3rrCrDrrIrYrryrrG partition startswithrrnroZ set_interfaceset_v6r r close)r(ZrfnsrMr?rKZ pat_tupleZ pat_iface_inZ pat_iface_outrPrr>ZwmsgZdtyperurvr{rrule pat_spacewarn_msgr/r/r0 _read_ruless    $  $ $'           zUFWBackendIptables._read_rulescCs|jd}|r#|jd}ntj|tjsWtd|}t|nytjj|}Wnt k rYnX|j d}|j }|rd}|j }n|j rtjj}n |d}tjj|dtjj|d|d tjj|d|d tjj|d|d tjj|d|d tjj|d|d tjj|d|dtjj|d|dtjj|d|dtjj|d|dtjj|d|dtjj|d|dtjj|d|dtjj|d|dtjj|d|d|dkr|jdds|dkr|jddrtjj|d|dtjj|d|dntjj|dx|D]}|j} |jrd|j} n|jdkr@| d|j7} nd} |jdkrp|jdkrp|j} n}|jdkr|jdkrd |j|jf} nF|jdkr| d!|j|jf7} n| d!|j|jf7} |jdkrS|jdkrSd"| |j|j|j|j|j| f} tjj|| d#nt j!d$} d%} |jr| j"d&|j} nd%}|jr| j"d&|j}nd'| |j|j|j|j|j| || f } tjj|| d#d(}|jrd)}n|jd*kr+d+}nd,||f}d-||j#f}x0|j$|||D]}tjj||qgWqWtjj|d.tjj|d/y|j%|j&d0}Wnt k rYnXx|D]\}}}t'|d1kr|d1d2krqn|j(|d%rtjj|d$j)|j*d3d4j*d5d6d#qqWtjj|d7|dkr|jdds|dkrl|jddrltjj|d8|j&d0d9kr tjj|d:|d;d$j)|j+d<|j,d=ntjj|d:|d>tjj|d:|d?tjj|d@ntjj|dAy3|j rtjj-|dBntjj-|Wnt k rYnXdCS)Dz.Write out new rules to file to user chain filer r z'%s' is not writablerrr>z*filter rUz-user-input - [0:0] z-user-output - [0:0] z-user-forward - [0:0] z-before-logging-input - [0:0] z-before-logging-output - [0:0] z -before-logging-forward - [0:0] z-user-logging-input - [0:0] z-user-logging-output - [0:0] z-user-logging-forward - [0:0] z-after-logging-input - [0:0] z-after-logging-output - [0:0] z-after-logging-forward - [0:0] z-logging-deny - [0:0] z-logging-allow - [0:0] rrrz-user-limit - [0:0] z-user-limit-accept - [0:0] z### RULES ### zroute:r=r3z in_%s!out_%sz%s_%sz# ### tuple ### %s %s %s %s %s %s %srVrhrlz%20z) ### tuple ### %s %s %s %s %s %s %s %s %srrr[rz %s-user-%sz -A %s %s z ### END RULES ### z ### LOGGING ### rrz-D[z"[z] z] "z### END LOGGING ### z ### RATE LIMITING ### offz-A z -user-limit z "z " z-user-limit -j REJECT z-user-limit-accept -j ACCEPT z### END RATE LIMITING ### zCOMMIT FN).r*raccessW_OKr3rrrErFrBrWr r r)sysstdoutfilenorHrXr{rrwrurvr@rnrortrrrersrfrCrDrI format_ruler_get_logging_rulesr4ryrrrr&r'rJ)r(rqZ rules_filerKrNr+r rOrr{ZifacesZtstrrrnro chain_suffixr.rule_strr~Zlrules_tr^qr/r/r0 _write_ruless            !   !     " $ 1  zUFWBackendIptables._write_rulesTcCsE|jd}|jru|js@td}t|n|jdkr|jdd rtd|jSn2|jdkr|jdd rtd|jS|jr|jdkr|jd krtd }t|ng}d }d }|j }|j } |jrY|j d krM|j dksC|j dkrMtd S|j}n| dksw| t|krtd| }t|n| dkr|jrtd}t|n| t|krtd| }t|ny|jWntk rYnXd} d } d} d5} x|D]}y|jWntk rgYnX|j|j|j |j f}| | kr| ddkr| ddkr| dks|ddkr|ddks| |kr d} |j|jd6} q| d7} n|} | d7} tj||}|dkrT| d7} n|dkr| r| rd}|js|j|jqq<|dkr|j r| rd}d}|j|jq<|j|q<W| r!| dkrtd}|jr|d7}n|Sn| rH|j rH|j|jn| r|jr|j rtd}|jr|d7}n|S|r|j r| rtd}|jr|d7}n|S|jr||_n ||_ y|j|jWn<tk rYn(tk r5td}t|YnXtd}|jrZtd}n|jrA|j rAd}|s|j|js| rd}| r|td7}n|td7}|jr|d7}n|ry|jWqtk rYqXql|td7}nQ|r?|jr?d }td!}n-| rl| rl|j rld"}td#}n|dkrA|j}d$}|jr|j}d%}|d7}nd&}|j rd'}n|j!d(krd)}nd*||f}td+}t"|d,|d-g\}}|dkr1t|nd.|||j#f}t$j%d/}x|j&|||D]}t"|g|\}}|dkrt'|t(j)t|n|d"kro|j*d0j+|ro|j,d1d0j+|}t"|d |d2d3g\}}|dkr7t-d4|q7qoqoWqAn|S)7aXUpdates firewall with rule by: * appending the rule to the chain if new rule and firewall enabled * deleting the rule from the chain if found and firewall enabled * inserting the rule if possible and firewall enabled * updating user rules file * reloading the user rules file if rule is modified r=z)Adding IPv6 rule failed: IPv6 not enabledrrz#Skipping unsupported IPv6 '%s' rulerz#Skipping unsupported IPv4 '%s' ruleZudpZtcpz/Must specify 'tcp' or 'udp' with multiple portsFz1.4z:Skipping IPv6 application rule. Need at least iptables 1.4rzInvalid position '%d'z Cannot specify insert and deletez#Cannot insert rule at position '%d'rdrrTz Skipping inserting existing rulez (v6)z"Could not delete non-existent rulezSkipping adding existing rulezCouldn't update rules filez Rules updatedzRules updated (v6)z Rule insertedz Rule updatedz (skipped reloading firewall)z-Dz Rule deletedz-Az Rule addedrrrrr[rz %s-user-%sz!Could not update running firewallz-Lz-nz%s %s %sz(-A +)(ufw6?-user-[a-z\-]+)(.*)rhz\2z-jRETURNzFAILOK: -D %s -j RETURN)r=r=r=r=)r=r=r=r=).rWrqr$r3rr{rXZmultirtr positionZiptables_versionrnror ryremove normalizerBrerfr%dup_rulerrr)rrrrrrZrr@rrrCrDrrrstderrrGrrIr)r(rZ allow_reloadr5rKZnewrulesfoundZmodifiedr rrZinsertedZmatcheslastrZcurrentZretZflagrr+rr.rbr[rrr~r^r/r/r0set_rules0    !!'           ,                                            $! zUFWBackendIptables.set_rulec Csg}g}|r|j}n |j}|j}|j||j|j}xL|D]D}|j}|j|j} | |kr]|j|q]q]W|S)z@Return a list of UFWRules from the system based on template rule)r r rrrrpr%) r(templaterqr rZnormrrr>Z tmp_tupler/r/r0get_app_rules_from_systemis            z,UFWBackendIptables.get_app_rules_from_systemcCs|j}|jdr$|j}nt|g|\}}|dkrtd|}|rptd|qt|ndS)zPerform command on chainrrzCould not perform '%s'zFAILOK: N)rrrZrr3rr)r(r.r\fail_okrrbr[rKr/r/r0rs   zUFWBackendIptables._chain_cmdc %CsX|jr dS|jg}y|j|}Wntk rGYnXy$|jdd|jddWn<tk rYn(tk rtd}t|YnX|jsdStd}xt|jd|jd|jd |jd D]D}y|j |d |d gWqtk r9t|YqXqWy^xW|jd|jd |jd D]2}|j |d |g|j |d|gqeWWntk rt|YnXx|D]\}}}d}t |dkr|ddkrd}ny_|dkrOt |dkrO|j |dg|ddddn|j |||Wqtk rt|YqXqWxddgD]}|j ddr|dks|j ddr|dkr|j |d|g|j |j dgdd|jddkrP|j |d|g|j |j dgddqPqqWdS)z#Update loglevel of running firewallNrqFTz&Couldn't update rules file for loggingz!Could not update running firewallrrrrz-Lz-nz-Fz-Zrz-D delete_firstrdrzufw-user-limitzufw6-user-limitrrrrhrrz-I)r)rWrrBrrr3rr#rryrXr&r'r4) r(rrules_trKr^rrrr.r/r/r0rsl        2  " *   z!UFWBackendIptables.update_loggingc Csg}|t|jjkr@td|}t|n|dkrx7|jdD](}|j|d|ddgdgqZW|Sx7|jdD](}|j|d|ddgd gqWd d d d ddg}|j||jdkr8g}|j||jdkr|}nx|jdD]}xdddgD]}|j|rC|j|dks|j|dkrd}|j|d|ddd|g|d gq |j||jdkr d}|j|d|ddd|g|d gq qCqCWq-Wg}|j||jdkr:|}nx|jdD]}|jdrfd}n|jdrd}|j||jdkr|j|d|d d d!d"ddg|d gq|j|d|d d d!d"dddd#g |d gn|j|d|ddd|g|d gqHWn|j||jdkrg}|j||jd$kr{|}n|j||jdkrd d d!d%g|}nd&}xD|jd'D]2}|j|d|ddd|g|d gqWn|S)(z%Get rules for specified logging levelzInvalid log level '%s'rrz-Iz-jrrz-Dr=z-mrz--limitz3/minz --limit-burstZ10rZhighrrrrr2r8z [UFW BLOCK] z-Arz --log-prefixZmediumz [UFW ALLOW] rr7Z conntrackz --ctstateZINVALIDz[UFW AUDIT INVALID] fullZNEWz [UFW AUDIT] r) rrrr3rr#r%endswithr|) r(rrrKr^rZlargsrarr/r/r0rsx &&      z%UFWBackendIptables._get_logging_rulesc Csd}g}x|jD]}|j|jds8qn|j|j|tjjtjjdtjj |j|}tjj |st d|}t |qqWt jd}xO|D]G}d||f}tjj|rt d|}t |qqWx\|D]T}d||f}|t ditjj |d 6|d 67}tj||qWx|D]}d||f}tjtjjtjjdtjj |tjj|tj||y tj|}|tj} Wn/tk r0t d |} t| wyYnX| tj@rU|t d |7}qy| tj@ry|t d |7}qyqyW|S)zReset the firewallr=z.rulesrzCould not find '%s'. Abortingz %Y%m%d_%H%M%Sz%s.%sz'%s' already exists. Abortingz"Backing up '%(old)s' to '%(new)s' oldnewzCouldn't stat '%s'zWARN: '%s' is world writablezWARN: '%s' is world readable)r*rr%rrrrrZ share_dirbasenameisfiler3rtimeZstrftimeexistsrenameshutilcopydirnameZcopymodestatST_MODErBrS_IWOTHS_IROTH) r(resZallfilesr`fnrKZextrZstatinfomoderr/r/r0reset2sP   "     zUFWBackendIptables.resetN)__name__ __module__ __qualname____doc__r"r6rQrcrrrrrrrrrrrrrrrr/r/r/r0r s(  +  K ]    D  [  J Zr )rrrCrrrrZ ufw.commonrrZufw.utilrrrrrZ ufw.backendrr r!r r/r/r/r0s      (