<html>
  <head>
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <div class="moz-cite-prefix">On 06/08/2015 03:24 PM, BJ wrote:<br>
    </div>
    <blockquote
cite="mid:CAPXrB3vyy58G2Sxnf7_cxX03N+Sg+xzMY67ehPoTLPHmr94SJg@mail.gmail.com"
      type="cite">
      <div dir="ltr">Hello all,
        <div><br>
        </div>
        <div>I was told on IRC that I should come here to discuss a
          recommended change on the networking page in the wiki.</div>
        <div><br>
        </div>
        <div>If you take a look at the "Basic Script" shown here: <a
            moz-do-not-send="true"
href="http://wiki.libvirt.org/page/Networking#Forwarding_Incoming_Connections">http://wiki.libvirt.org/page/Networking#Forwarding_Incoming_Connections</a></div>
        <div><br>
        </div>
        <div>It does two things:</div>
        <div>1) Create a DNAT rule in the NAT table of IPTABLES</div>
        <div>2) Create a FORWARD rule in the FILTER table of IPTABLES</div>
        <div><br>
        </div>
        <div>The FORWARD rule is set up as it ought to be, however, the
          DNAT rule has some unintended consequences. I set up a DNAT on
          port 80, and suddenly, I couldn't access out on port 80
          anymore from my guest machine.</div>
      </div>
    </blockquote>
    <br>
    I'm not seeing the same results here. outbound port 80 is still
    allowed from my host once the rule is in place. Of course incoming
    port 80 isn't being redirected to the guest either, so I think I
    have bigger problems. (this is likely due to the fact that I haven't
    tried the script again since 2013 or so, and a lot has likely
    changed with the iptables rules added to a Fedora system since then)<br>
    <br>
    <blockquote
cite="mid:CAPXrB3vyy58G2Sxnf7_cxX03N+Sg+xzMY67ehPoTLPHmr94SJg@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div> However, if I changed the destination address from
          "anywhere" to the IP of the host machine, the problem
          resolved. So I change the script to as follows. (Changes are
          highlighted. For some reason the original script didn't work
          using /bin/sh, but it did with /bin/bash, so I changed that
          too).</div>
      </div>
    </blockquote>
    <br>
    I don't know for sure, but my guess is that this line:<br>
    <br>
    <font face="monospace, monospace">  length=$(( ${#Host_port[@]} - 1
      ))<br>
      <br>
      which was added by vgerris in order to support forwarding of
      multiple ports, could be what's causing the incompatibility (that
      wasn't in the original, simpler version of the script, written by
      me.)<br>
      <br>
    </font>
    <blockquote
cite="mid:CAPXrB3vyy58G2Sxnf7_cxX03N+Sg+xzMY67ehPoTLPHmr94SJg@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div><br>
        </div>
        <div>
          <div><font color="#ea9999" face="monospace, monospace"><b
                style="background-color:rgb(0,0,0)">#!/bin/bash</b></font></div>
          <div><font face="monospace, monospace"># used some from
              advanced script to have multiple ports: use an equal
              number of guest and host ports</font></div>
          <div><font face="monospace, monospace"><br>
            </font></div>
          <div><font face="monospace, monospace">Guest_name=xxxxxxx</font></div>
          <div><font face="monospace, monospace">Guest_ipaddr=xxx.xxx.xxx.xx</font></div>
          <div><font color="#ea9999" face="monospace, monospace"><b
                style="background-color:rgb(0,0,0)">Host_ipaddr=xxx.xxx.xxx.xx</b></font></div>
          <div><font face="monospace, monospace">Host_port=( '80' '443'
              )</font></div>
          <div><font face="monospace, monospace">Guest_port=( '80' '443'
              )</font></div>
          <div><font face="monospace, monospace">length=$((
              ${#Host_port[@]} - 1 ))</font></div>
          <div><font face="monospace, monospace">if [ "${1}" =
              "${Guest_name}" ]; then</font></div>
          <div><font face="monospace, monospace">   if [ "${2}" =
              "stopped" -o "${2}" = "reconnect" ]; then</font></div>
          <div><font face="monospace, monospace">       for i in `seq 0
              $length`; do</font></div>
          <div><font face="monospace, monospace">               iptables
              -t nat -D PREROUTING <b><font
                  style="background-color:rgb(0,0,0)" color="#ea9999">-d
                  ${Host_ipaddr}</font></b> -p tcp --dport
              ${Host_port[$i]} -j DNAT --to
              ${Guest_ipaddr}:${Guest_port[$i]}</font></div>
          <div><font face="monospace, monospace">               iptables
              -D FORWARD -d ${Guest_ipaddr}/32 -p tcp -m state --state
              NEW -m tcp --dport ${Guest_port[$i]} -j ACCEPT</font></div>
          <div><font face="monospace, monospace">       done</font></div>
          <div><font face="monospace, monospace">   fi</font></div>
          <div><font face="monospace, monospace">   if [ "${2}" =
              "start" -o "${2}" = "reconnect" ]; then</font></div>
          <div><font face="monospace, monospace">       for i in `seq 0
              $length`; do</font></div>
          <div><font face="monospace, monospace">               iptables
              -t nat -A PREROUTING <b><font
                  style="background-color:rgb(0,0,0)" color="#ea9999">-d
                  ${Host_ipaddr}</font></b> -p tcp --dport
              ${Host_port[$i]} -j DNAT --to
              ${Guest_ipaddr}:${Guest_port[$i]}</font></div>
          <div><font face="monospace, monospace">               iptables
              -I FORWARD 4 -d ${Guest_ipaddr}/32 -p tcp -m state --state
              NEW -m tcp --dport ${Guest_port[$i]} -j ACCEPT</font></div>
          <div><font face="monospace, monospace">       done</font></div>
          <div><font face="monospace, monospace">   fi</font></div>
          <div><font face="monospace, monospace">fi</font></div>
        </div>
        <div><font face="monospace, monospace"><br>
          </font></div>
        <div><font face="monospace, monospace"><br>
          </font></div>
        <div>Lastly, I should note that I am using Ubuntu 14.04, both
          for the host and guest. </div>
        <div><br>
        </div>
        <div>I'm also curious as to why this is considered a hack
          method. It states in the wiki that "This method is a hack",
          but it doesn't express why.</div>
      </div>
    </blockquote>
    <br>
    I consider it a hack because:<br>
    <br>
    1) It requires the IP address of the guest to be known before the
    guest is started, so either you need to guess the guest's IP (if the
    guest is getting its IP address via dhcp) or configured the guest IP
    address in multiple places.<br>
    <br>
    2) It requires using a hook script, which "taints" *all* guests on
    this machine, rendering them "unsupported" in the eyes of some (in
    practice, once you see what is causing the tainting it's not such a
    big deal, but it does mean that an external script gets control with
    elevated privileges).<br>
    <br>
    3) The "configuration" is just the contents of the shell script, so
    it can't be supported by any higher level management application -
    you will always need to directly modify this single shell script
    file.<br>
    <br>
    4) If you change the configuration for a guest while that guest is
    running, any forwarding rules that were a part of the old config but
    not in the new config will be orphaned in your iptables nat table
    until *all* rules are flushed.<br>
    <br>
    5) If anything else messes with the iptables rules, these port
    forwarding rules are broken. Especially on older versions of libvirt
    (0.9.12 and older, which is around the time that entry was written),
    just restarting libvirtd would break the port forwarding.<br>
    <br>
    6) As both of us have experienced here, interaction with the
    iptables rules of the underlying system can easily result in it not
    working at all.<br>
    <br>
    <br>
    The proper way to support this would be XML added to the domain
    configuration, something like:<br>
    <br>
       <interface type='network'><br>
         <source network='default'/><br>
         <model type='virtio'/<br>
         <mac address='52:54:00:11:22:33'/><br>
         <redirect protocol='tcp'><br>
           <public address='1.2.3.4' port='2200'/><br>
           <private port='22'/><br>
         </redirect><br>
         ...<br>
      </interface><br>
    <br>
    (or something like that). libvirt would then auto-determine the IP
    address of the interface and add the necessary iptables rules (or
    perhaps an rinetd config line item, which may be less prone to
    sabotage by distro-specific default iptables setups). The inverse
    would be automatically done when the domain was shutdown.<br>
    <br>
    <br>
    <mac address="52:54:00:9f:56:b7">
    </mac><mac address="52:54:00:9f:56:b7">
    </mac><mac address="52:54:00:9f:56:b7">
    </mac>
    <blockquote
cite="mid:CAPXrB3vyy58G2Sxnf7_cxX03N+Sg+xzMY67ehPoTLPHmr94SJg@mail.gmail.com"
      type="cite">
      <div dir="ltr">
        <div> Many VM Servers have similar features. I know Virtual Box
          does, I use the same feature there. It may not be how I would
          set up a production server, but doesn't make it a hack.</div>
      </div>
    </blockquote>
    <br>
    It's not the port forwarding itself that I consider to be a hack,
    it's the method that's used by that script to accomplish it. (And
    since I was the original author of the script and the entry in the
    wiki, I think I am allowed to criticize it :-)<br>
  </body>
</html>