With only NAT – no. IP packets only have one 'source' field.
If you make iptables keep the original client address (DNAT only), then y.y.y.y will attempt to send replies directly to that original client (who thinks it's talking to x.x.x.x and doesn't expect any packets from y.y.y.y).
If you make iptables put your address as the new source (DNAT+SNAT), then y.y.y.y won't know the original source address.
(This is actually the same problem as with trying to port-forward from LAN to the same LAN, and the 2nd method is called 'NAT hairpinning' or 'NAT reflection'.)
To make this work, you need a tunnel/VPN between x.x.x.x and y.y.y.y – wrap the original packets you receive, without any changes, inside another IP packet that is sent to y.y.y.y (which will then unwrap the tunnelled packet and see the original source).
Of course, this means that you need root privileges on both systems in order to configure the tunnel. Additionally, the destination (y.y.y.y) needs to support "policy routing" – Linux and FreeBSD pf are capable of this. It needs a rule that'll route everything through the VPN if the source address is a VPN address.
You still need the iptables DNAT rule, but its 'to-destination' will be y's VPN address, not the public address. You can use any tunnel/VPN type for this, from basic "IP-in-IP" to GRE to OpenVPN to WireGuard. For example:
x.x.x.x
Bring up the tunnel:
ip link add gre-y type gre local x.x.x.x remote y.y.y.y ttl 64
ip link set gre-y up
ip addr add 192.168.47.1/24 dev gre-y
Add port-forwarding rule, just like on a LAN:
iptables -t nat -I PREROUTING -p tcp --dport 1234 -j DNAT --to-destination 192.168.47.2
y.y.y.y
Bring up the tunnel:
ip link add gre-x type gre local y.y.y.y remote x.x.x.x ttl 64
ip link set gre-x up
ip addr add 192.168.47.2/24 dev gre-x
Make sure it works:
ping 192.168.47.1
Set up policy routing, so that replies (and only replies) will go over the tunnel:
ip route add default via 192.168.47.1 dev gre-x table 1111
ip rule add pref 1000 from 192.168.47.2 lookup 1111
(To use another tunnel/VPN type, replace only the "Bring up the tunnel" part.)
Well, you could put the IP in the payload. It's ugly and I'd recommend finding an alternative first, but it works. For some values of works. If it's just an application requiring the info and doesn't need to have it in an exact location. – Mast – 2018-09-12T11:56:54.217